using Application.Abstractions.Data;
using Application.Abstractions.Messaging;
using Domain.Entities.Donations;
using Domain.Entities.Donations.ValueObject;
using Microsoft.EntityFrameworkCore;

namespace Application.Features.Api.Crew.SaveWidgetConfig;

internal sealed class Handler(IAppDbContext db) : ICommandHandler<Command>
{
    public async Task Handle(Command r, CancellationToken ct)
    {
        var theme = (CrewWidgetTheme)r.Theme;
        var period = (RankPeriodType)r.Period;

        // 기간 중복 검증 (활성 설정만)
        if (r.IsActive)
        {
            if (period == RankPeriodType.Custom && r.StartAt.HasValue && r.EndAt.HasValue)
            {
                // Custom 기간: 날짜 겹침 체크
                var overlapping = await db.CrewWidgetConfig
                    .AnyAsync(c => c.ChannelID == r.ChannelID
                        && (!r.ID.HasValue || c.ID != r.ID.Value)
                        && c.IsActive
                        && c.Period == RankPeriodType.Custom
                        && c.StartAt < r.EndAt && c.EndAt > r.StartAt, ct);

                if (overlapping)
                {
                    throw new InvalidOperationException("기간이 겹치는 활성 설정이 있습니다.");
                }
            }
            else
            {
                // 같은 기간 타입에 활성 설정 1개만
                var existing = await db.CrewWidgetConfig
                    .AnyAsync(c => c.ChannelID == r.ChannelID
                        && (!r.ID.HasValue || c.ID != r.ID.Value)
                        && c.IsActive
                        && c.Period == period, ct);

                if (existing)
                {
                    throw new InvalidOperationException("같은 기간의 활성 설정이 이미 있습니다.");
                }
            }
        }

        if (r.ID.HasValue)
        {
            var config = await db.CrewWidgetConfig
                .FirstOrDefaultAsync(c => c.ID == r.ID.Value && c.ChannelID == r.ChannelID, ct);

            if (config is null)
            {
                throw new KeyNotFoundException("설정을 찾을 수 없습니다.");
            }

            config.Update(
                r.Title, theme, period, r.StartAt, r.EndAt,
                r.MaxDisplayCount, r.IsShowAmount, r.IsShowDonationCount,
                r.IsShowContributionRate, r.IsShowMemberIcon, r.IsActive, r.BgColor,
                r.TitleFontFamily, r.TitleFontSizePx, r.TitleFontColor,
                r.Rank1FontFamily, r.Rank1FontSizePx, r.Rank1FontColor,
                r.Rank2FontFamily, r.Rank2FontSizePx, r.Rank2FontColor,
                r.Rank3FontFamily, r.Rank3FontSizePx, r.Rank3FontColor,
                r.RowFontFamily, r.RowFontSizePx, r.RowFontColor
            );
        }
        else
        {
            var config = CrewWidgetConfig.Create(
                r.ChannelID, r.MemberID, r.Title,
                theme, period, r.StartAt, r.EndAt,
                r.MaxDisplayCount, r.IsShowAmount, r.IsShowDonationCount,
                r.IsShowContributionRate, r.IsShowMemberIcon, r.IsActive, r.BgColor,
                r.TitleFontFamily, r.TitleFontSizePx, r.TitleFontColor,
                r.Rank1FontFamily, r.Rank1FontSizePx, r.Rank1FontColor,
                r.Rank2FontFamily, r.Rank2FontSizePx, r.Rank2FontColor,
                r.Rank3FontFamily, r.Rank3FontSizePx, r.Rank3FontColor,
                r.RowFontFamily, r.RowFontSizePx, r.RowFontColor
            );
            db.CrewWidgetConfig.Add(config);
        }

        await db.SaveChangesAsync(ct);
    }
}