using CMSMicroservice.Application.ClubMembershipCQ.Queries.GetAllClubMemberships;
using CMSMicroservice.Application.ClubMembershipCQ.Queries.GetClubMembership;
using CMSMicroservice.Application.ClubMembershipCQ.Queries.GetClubStatistics;
using CMSMicroservice.Domain.Enums;
using AppHistory = CMSMicroservice.Application.ClubMembershipCQ.Queries.GetClubMembershipHistory;
using ProtoClub = CMSMicroservice.Protobuf.Protos.ClubMembership;
using Google.Protobuf.WellKnownTypes;
using Mapster;
using System.Linq;

namespace CMSMicroservice.WebApi.Common.Mappings;

public class ClubMembershipProfile : IRegister
{
    public void Register(TypeAdapterConfig config)
    {
        // =====================
        // GetClubMembership
        // =====================
        
        // GetClubMembershipRequest -> GetClubMembershipQuery
        config.NewConfig<ProtoClub.GetClubMembershipRequest, GetClubMembershipQuery>()
            .MapWith(src => new GetClubMembershipQuery
            {
                UserId = src.UserId
            });

        // ClubMembershipDto -> GetClubMembershipResponse
        config.NewConfig<ClubMembershipDto, ProtoClub.GetClubMembershipResponse>()
            .MapWith(src => new ProtoClub.GetClubMembershipResponse
            {
                Id = src.Id,
                UserId = src.UserId,
                PackageId = 0, // Not available
                PackageName = string.Empty, // Not available
                ActivationCode = string.Empty, // Not available
                ActivatedAt = src.ActivatedAt.HasValue 
                    ? Timestamp.FromDateTime(DateTime.SpecifyKind(src.ActivatedAt.Value, DateTimeKind.Utc)) 
                    : null,
                ExpiresAt = null, // Not available
                IsActive = src.IsActive,
                Created = Timestamp.FromDateTimeOffset(src.Created),
                Features = { }, // Empty for now
                Status = src.IsActive ? "Active" : "Inactive",
                DaysRemaining = 0 // Calculate if ExpiresAt is available
            });

        // =====================
        // GetAllClubMemberships
        // =====================
        
        // GetAllClubMembershipsRequest -> GetAllClubMembershipsQuery
        config.NewConfig<ProtoClub.GetAllClubMembershipsRequest, GetAllClubMembershipsQuery>()
            .MapWith(src => new GetAllClubMembershipsQuery
            {
                PaginationState = new Application.Common.Models.PaginationState
                {
                    PageNumber = src.PageIndex > 0 ? src.PageIndex : 1,
                    PageSize = src.PageSize > 0 ? src.PageSize : 20
                },
                Filter = new GetAllClubMembershipsFilter
                {
                    UserId = src.UserId,
                    IsActive = src.IsActive
                }
            });

        // GetAllClubMembershipsResponseDto -> GetAllClubMembershipsResponse
        config.NewConfig<GetAllClubMembershipsResponseDto, ProtoClub.GetAllClubMembershipsResponse>()
            .MapWith(src => new ProtoClub.GetAllClubMembershipsResponse
            {
                MetaData = new CMSMicroservice.Protobuf.Protos.MetaData
                {
                    CurrentPage = src.MetaData.CurrentPage,
                    PageSize = src.MetaData.PageSize,
                    TotalCount = src.MetaData.TotalCount,
                    TotalPage = src.MetaData.TotalPage
                },
                Models = { src.Models.Select(MapToModel) }
            });

        // =====================
        // GetClubStatistics
        // =====================

        // GetClubStatisticsRequest -> GetClubStatisticsQuery
        config.NewConfig<ProtoClub.GetClubStatisticsRequest, GetClubStatisticsQuery>()
            .MapWith(src => new GetClubStatisticsQuery());

        // GetClubStatisticsResponseDto -> GetClubStatisticsResponse
        config.NewConfig<GetClubStatisticsResponseDto, ProtoClub.GetClubStatisticsResponse>()
            .MapWith(src => new ProtoClub.GetClubStatisticsResponse
            {
                TotalMembers = src.TotalMembers,
                ActiveMembers = src.ActiveMembers,
                InactiveMembers = src.InactiveMembers,
                ExpiredMembers = src.ExpiredMembers,
                ActivePercentage = src.ActivePercentage,
                TotalRevenue = src.TotalRevenue,
                AverageMembershipDurationDays = src.AverageMembershipDurationDays,
                ExpiringSoonCount = src.ExpiringSoonCount,
                PackageDistribution = { src.PackageDistribution.Select(p => new ProtoClub.PackageLevelDistribution
                {
                    PackageId = p.PackageId,
                    PackageName = p.PackageName ?? string.Empty,
                    MemberCount = p.MemberCount,
                    Percentage = p.Percentage
                }) },
                MonthlyTrend = { src.MonthlyTrend.Select(t => new ProtoClub.MonthlyMembershipTrend
                {
                    Month = t.Month ?? string.Empty,
                    Activations = t.Activations,
                    Expirations = t.Expirations,
                    NetChange = t.NetChange
                }) }
            });

        // GetClubMembershipHistory
        config.NewConfig<ProtoClub.GetClubMembershipHistoryRequest, AppHistory.GetClubMembershipHistoryQuery>()
            .Map(dest => dest.PaginationState, src => src.PaginationState)
            .Map(dest => dest.SortBy, src => src.SortBy)
            .Map(dest => dest.Filter, src => src.Filter);

        config.NewConfig<ProtoClub.GetClubMembershipHistoryFilter, AppHistory.GetClubMembershipHistoryFilter>()
            .Map(dest => dest.UserId, src => src.UserId)
            .Map(dest => dest.ClubMembershipId, src => src.ClubMembershipId)
            .Map(dest => dest.Action, src => src.Action == null ? null : (ClubMembershipAction?)src.Action)
            .Map(dest => dest.CreatedFrom, src => src.CreatedFrom != null ? src.CreatedFrom.ToDateTime() : (DateTime?)null)
            .Map(dest => dest.CreatedTo, src => src.CreatedTo != null ? src.CreatedTo.ToDateTime() : (DateTime?)null);

        config.NewConfig<AppHistory.GetClubMembershipHistoryResponseDto, ProtoClub.GetClubMembershipHistoryResponse>()
            .Map(dest => dest.MetaData, src => src.MetaData)
            .Map(dest => dest.Models, src => src.Models);

        config.NewConfig<AppHistory.GetClubMembershipHistoryResponseModel, ProtoClub.ClubMembershipHistoryModel>()
            .Map(dest => dest.Id, src => src.Id)
            .Map(dest => dest.ClubMembershipId, src => src.ClubMembershipId)
            .Map(dest => dest.UserId, src => src.UserId)
            .Map(dest => dest.UserName, src => src.UserName ?? string.Empty)
            .Map(dest => dest.OldIsActive, src => src.OldIsActive)
            .Map(dest => dest.NewIsActive, src => src.NewIsActive)
            .Map(dest => dest.OldInitialContribution, src => src.OldInitialContribution)
            .Map(dest => dest.NewInitialContribution, src => src.NewInitialContribution)
            .Map(dest => dest.Action, src => (int)src.Action)
            .Map(dest => dest.PerformedBy, src => src.PerformedBy ?? string.Empty)
            .Map(dest => dest.Reason, src => src.Reason ?? string.Empty)
            .Map(dest => dest.CreatedAt, src => Timestamp.FromDateTimeOffset(src.Created));
    }

    private static ProtoClub.ClubMembershipModel MapToModel(GetAllClubMembershipsResponseModel src)
    {
        return new ProtoClub.ClubMembershipModel
        {
            Id = src.Id,
            UserId = src.UserId,
            UserName = src.UserName ?? string.Empty,
            PackageId = src.PackageId,
            PackageName = src.PackageName ?? string.Empty,
            ActivationCode = string.Empty,
            ActivatedAt = src.ActivatedAt.HasValue 
                ? Timestamp.FromDateTime(DateTime.SpecifyKind(src.ActivatedAt.Value, DateTimeKind.Utc)) 
                : null,
            ExpiresAt = null,
            IsActive = src.IsActive,
            IsExpired = false,
            Created = Timestamp.FromDateTime(src.Created.UtcDateTime)
        };
    }
}
