using Application.Abstractions.Data;
using Application.Abstractions.Messaging;
using Microsoft.EntityFrameworkCore;

namespace Application.Features.Admin.Member.List.Search;

public sealed class Handler(IAppDbContext db) : IQueryHandler<Query, Response>
{
    public async Task<Response> Handle(Query request, CancellationToken ct)
    {
        var query = db.Member.AsNoTracking().Include(x => x.MemberGrade).Include(x => x.MemberStats).AsQueryable();

        // 키워드 검색
        if (!string.IsNullOrWhiteSpace(request.Keyword))
        {
            query = request.Search switch
            {
                1 => query.Where(x => x.ID.ToString().Contains(request.Keyword)),
                2 => query.Where(x => x.Email.Contains(request.Keyword)),
                3 => query.Where(x => x.Name != null && x.Name.Contains(request.Keyword)),
                4 => query.Where(x => x.FullName != null && x.FullName.Contains(request.Keyword)),
                5 => query.Where(x => x.Phone != null && x.Phone.Contains(request.Keyword)),
                _ => query
            };
        }

        // 날짜 필터
        if (!string.IsNullOrWhiteSpace(request.StartAt) && DateTime.TryParse(request.StartAt, out var startAt))
        {
            query = query.Where(x => x.CreatedAt >= startAt);
        }

        if (!string.IsNullOrWhiteSpace(request.EndAt) && DateTime.TryParse(request.EndAt, out var endAt))
        {
            query = query.Where(x => x.CreatedAt <= endAt);
        }

        // 성별 필터
        if (request.Gender.HasValue)
        {
            query = query.Where(x => x.Gender == request.Gender.Value);
        }

        // 이메일 인증 필터
        if (request.IsEmailVerified == 1)
        {
            query = query.Where(x => x.IsEmailVerified);
        }

        // 본인 인증 필터
        if (request.IsAuthCertified == 1)
        {
            query = query.Where(x => x.IsAuthCertified);
        }

        var counts = await query.GroupBy(c => 1).Select(c => new Response.TabCounts
        {
            All = c.Count(),
            Denied = c.Count(x => x.IsDenied),
            Withdraw = c.Count(x => x.IsWithdraw),
            Admin = c.Count(x => x.IsAdmin)
        }).FirstOrDefaultAsync(ct) ?? new Response.TabCounts();

        query = request.Tab switch
        {
            1 => query.Where(x => x.IsDenied),
            2 => query.Where(x => x.IsWithdraw),
            3 => query.Where(x => x.IsAdmin),
            _ => query
        };

        var total = await query.CountAsync(ct);
        var skip = (request.PageNum - 1) * request.PerPage;

        var list = await query
            .OrderByDescending(x => x.ID)
            .Skip(skip)
            .Take(request.PerPage)
            .Select(x => new
            {
                x.ID,
                x.Email,
                x.Name,
                x.FullName,
                x.Icon,
                x.Phone,
                x.Birthday,
                x.Gender,
                GradeName = x.MemberGrade != null ? x.MemberGrade.KorName : null,
                x.IsEmailVerified,
                x.IsAuthCertified,
                x.IsDenied,
                x.IsWithdraw,
                Following = x.MemberStats != null ? x.MemberStats.FollowingCount : 0,
                Followed = x.MemberStats != null ? x.MemberStats.FollowerCount : 0,
                x.LastLoginAt,
                x.LastLoginIp,
                x.CreatedAt,
                x.UpdatedAt
            })
            .ToListAsync(ct);

        var rows = list.Select((x, idx) => new Response.Row
        {
            Num = total - skip - idx,
            ID = x.ID,
            Email = x.Email,
            Name = x.Name,
            FullName = x.FullName,
            Icon = x.Icon,
            Phone = x.Phone,
            Birthday = x.Birthday?.ToString("yyyy-MM-dd"),
            Gender = x.Gender switch
            {
                Domain.Entities.Members.ValueObject.Gender.Male => "남자",
                Domain.Entities.Members.ValueObject.Gender.Female => "여자",
                _ => null
            },
            GradeName = x.GradeName,
            IsEmailVerified = x.IsEmailVerified,
            IsAuthCertified = x.IsAuthCertified,
            IsDenied = x.IsDenied,
            IsWithdraw = x.IsWithdraw,
            Following = x.Following,
            Followed = x.Followed,
            LastLoginAt = x.LastLoginAt,
            LastLoginIp = x.LastLoginIp,
            CreatedAt = x.CreatedAt,
            UpdatedAt = x.UpdatedAt
        }).ToList();

        return new Response
        {
            Total = total,
            Counts = counts,
            List = rows
        };
    }
}