using System.Globalization;
using MediatR;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using TakeoutSaaS.Application.App.Coupons.NewCustomer.Commands;
using TakeoutSaaS.Application.App.Coupons.NewCustomer.Dto;
using TakeoutSaaS.Application.App.Coupons.NewCustomer.Queries;
using TakeoutSaaS.Application.App.Stores.Services;
using TakeoutSaaS.Infrastructure.App.Persistence;
using TakeoutSaaS.Module.Authorization.Attributes;
using TakeoutSaaS.Shared.Abstractions.Results;
using TakeoutSaaS.Shared.Web.Api;
using TakeoutSaaS.TenantApi.Contracts.Marketing;

namespace TakeoutSaaS.TenantApi.Controllers;

/// <summary>
/// 营销中心新客有礼管理。
/// </summary>
[ApiVersion("1.0")]
[Authorize]
[Route("api/tenant/v{version:apiVersion}/marketing/new-customer")]
public sealed class MarketingNewCustomerController(
    IMediator mediator,
    TakeoutAppDbContext dbContext,
    StoreContextService storeContextService)
    : BaseApiController
{
    private const string ViewPermission = "tenant:marketing:new-customer:view";
    private const string ManagePermission = "tenant:marketing:new-customer:manage";

    /// <summary>
    /// 获取新客有礼详情。
    /// </summary>
    [HttpGet("detail")]
    [PermissionAuthorize(ViewPermission, ManagePermission)]
    [ProducesResponseType(typeof(ApiResponse<NewCustomerDetailResponse>), StatusCodes.Status200OK)]
    public async Task<ApiResponse<NewCustomerDetailResponse>> Detail(
        [FromQuery] NewCustomerDetailRequest request,
        CancellationToken cancellationToken)
    {
        // 1. 解析并校验门店权限
        var storeId = StoreApiHelpers.ParseRequiredSnowflake(request.StoreId, nameof(request.StoreId));
        await EnsureStoreAccessibleAsync(storeId, cancellationToken);

        // 2. 查询应用层详情
        var result = await mediator.Send(new GetNewCustomerDetailQuery
        {
            StoreId = storeId,
            RecordPage = request.RecordPage,
            RecordPageSize = request.RecordPageSize
        }, cancellationToken);

        // 3. 返回响应
        return ApiResponse<NewCustomerDetailResponse>.Ok(MapDetail(result));
    }

    /// <summary>
    /// 保存新客有礼配置。
    /// </summary>
    [HttpPost("save")]
    [PermissionAuthorize(ManagePermission)]
    [ProducesResponseType(typeof(ApiResponse<NewCustomerSettingsResponse>), StatusCodes.Status200OK)]
    public async Task<ApiResponse<NewCustomerSettingsResponse>> Save(
        [FromBody] SaveNewCustomerSettingsRequest request,
        CancellationToken cancellationToken)
    {
        // 1. 解析并校验门店权限
        var storeId = StoreApiHelpers.ParseRequiredSnowflake(request.StoreId, nameof(request.StoreId));
        await EnsureStoreAccessibleAsync(storeId, cancellationToken);

        // 2. 调用应用层保存
        var result = await mediator.Send(new SaveNewCustomerSettingsCommand
        {
            StoreId = storeId,
            GiftEnabled = request.GiftEnabled,
            GiftType = request.GiftType,
            DirectReduceAmount = request.DirectReduceAmount,
            DirectMinimumSpend = request.DirectMinimumSpend,
            InviteEnabled = request.InviteEnabled,
            ShareChannels = request.ShareChannels,
            WelcomeCoupons = request.WelcomeCoupons.Select(MapSaveCouponRule).ToList(),
            InviterCoupons = request.InviterCoupons.Select(MapSaveCouponRule).ToList(),
            InviteeCoupons = request.InviteeCoupons.Select(MapSaveCouponRule).ToList()
        }, cancellationToken);

        // 3. 返回响应
        return ApiResponse<NewCustomerSettingsResponse>.Ok(MapSettings(result));
    }

    /// <summary>
    /// 获取新客邀请记录分页。
    /// </summary>
    [HttpGet("invite-record/list")]
    [PermissionAuthorize(ViewPermission, ManagePermission)]
    [ProducesResponseType(typeof(ApiResponse<NewCustomerInviteRecordListResultResponse>), StatusCodes.Status200OK)]
    public async Task<ApiResponse<NewCustomerInviteRecordListResultResponse>> InviteRecordList(
        [FromQuery] NewCustomerInviteRecordListRequest request,
        CancellationToken cancellationToken)
    {
        // 1. 解析并校验门店权限
        var storeId = StoreApiHelpers.ParseRequiredSnowflake(request.StoreId, nameof(request.StoreId));
        await EnsureStoreAccessibleAsync(storeId, cancellationToken);

        // 2. 查询应用层分页
        var result = await mediator.Send(new GetNewCustomerInviteRecordListQuery
        {
            StoreId = storeId,
            Page = request.Page,
            PageSize = request.PageSize
        }, cancellationToken);

        // 3. 返回响应
        return ApiResponse<NewCustomerInviteRecordListResultResponse>.Ok(MapInviteRecordList(result));
    }

    /// <summary>
    /// 写入新客邀请记录。
    /// </summary>
    [HttpPost("invite-record/write")]
    [PermissionAuthorize(ManagePermission)]
    [ProducesResponseType(typeof(ApiResponse<NewCustomerInviteRecordResponse>), StatusCodes.Status200OK)]
    public async Task<ApiResponse<NewCustomerInviteRecordResponse>> WriteInviteRecord(
        [FromBody] WriteNewCustomerInviteRecordRequest request,
        CancellationToken cancellationToken)
    {
        // 1. 解析并校验门店权限
        var storeId = StoreApiHelpers.ParseRequiredSnowflake(request.StoreId, nameof(request.StoreId));
        await EnsureStoreAccessibleAsync(storeId, cancellationToken);

        // 2. 调用应用层写入
        var result = await mediator.Send(new WriteNewCustomerInviteRecordCommand
        {
            StoreId = storeId,
            InviterName = request.InviterName,
            InviteeName = request.InviteeName,
            InviteTime = request.InviteTime,
            OrderStatus = request.OrderStatus,
            RewardStatus = request.RewardStatus,
            RewardIssuedAt = request.RewardIssuedAt,
            SourceChannel = request.SourceChannel
        }, cancellationToken);

        // 3. 返回响应
        return ApiResponse<NewCustomerInviteRecordResponse>.Ok(MapInviteRecord(result));
    }

    /// <summary>
    /// 写入新客成长记录。
    /// </summary>
    [HttpPost("growth-record/write")]
    [PermissionAuthorize(ManagePermission)]
    [ProducesResponseType(typeof(ApiResponse<NewCustomerGrowthRecordResponse>), StatusCodes.Status200OK)]
    public async Task<ApiResponse<NewCustomerGrowthRecordResponse>> WriteGrowthRecord(
        [FromBody] WriteNewCustomerGrowthRecordRequest request,
        CancellationToken cancellationToken)
    {
        // 1. 解析并校验门店权限
        var storeId = StoreApiHelpers.ParseRequiredSnowflake(request.StoreId, nameof(request.StoreId));
        await EnsureStoreAccessibleAsync(storeId, cancellationToken);

        // 2. 调用应用层写入
        var result = await mediator.Send(new WriteNewCustomerGrowthRecordCommand
        {
            StoreId = storeId,
            CustomerKey = request.CustomerKey,
            CustomerName = request.CustomerName,
            RegisteredAt = request.RegisteredAt,
            GiftClaimedAt = request.GiftClaimedAt,
            FirstOrderAt = request.FirstOrderAt,
            SourceChannel = request.SourceChannel
        }, cancellationToken);

        // 3. 返回响应
        return ApiResponse<NewCustomerGrowthRecordResponse>.Ok(MapGrowthRecord(result));
    }

    private async Task EnsureStoreAccessibleAsync(long storeId, CancellationToken cancellationToken)
    {
        var (tenantId, merchantId) = StoreApiHelpers.GetTenantMerchantContext(storeContextService);
        await StoreApiHelpers.EnsureStoreAccessibleAsync(dbContext, tenantId, merchantId, storeId, cancellationToken);
    }

    private static NewCustomerSaveCouponRuleInputDto MapSaveCouponRule(NewCustomerSaveCouponRuleRequest source)
    {
        return new NewCustomerSaveCouponRuleInputDto
        {
            CouponType = source.CouponType,
            Value = source.Value,
            MinimumSpend = source.MinimumSpend,
            ValidDays = source.ValidDays
        };
    }

    private static NewCustomerDetailResponse MapDetail(NewCustomerDetailDto source)
    {
        return new NewCustomerDetailResponse
        {
            Settings = MapSettings(source.Settings),
            Stats = new NewCustomerStatsResponse
            {
                MonthlyNewCustomers = source.Stats.MonthlyNewCustomers,
                MonthlyGrowthCount = source.Stats.MonthlyGrowthCount,
                MonthlyGrowthRatePercent = source.Stats.MonthlyGrowthRatePercent,
                GiftClaimRate = source.Stats.GiftClaimRate,
                GiftClaimedCount = source.Stats.GiftClaimedCount,
                FirstOrderConversionRate = source.Stats.FirstOrderConversionRate,
                FirstOrderedCount = source.Stats.FirstOrderedCount
            },
            InviteRecords = MapInviteRecordList(source.InviteRecords)
        };
    }

    private static NewCustomerSettingsResponse MapSettings(NewCustomerSettingsDto source)
    {
        return new NewCustomerSettingsResponse
        {
            StoreId = source.StoreId.ToString(),
            GiftEnabled = source.GiftEnabled,
            GiftType = source.GiftType,
            DirectReduceAmount = source.DirectReduceAmount,
            DirectMinimumSpend = source.DirectMinimumSpend,
            InviteEnabled = source.InviteEnabled,
            ShareChannels = source.ShareChannels.ToList(),
            WelcomeCoupons = source.WelcomeCoupons.Select(MapCouponRule).ToList(),
            InviterCoupons = source.InviterCoupons.Select(MapCouponRule).ToList(),
            InviteeCoupons = source.InviteeCoupons.Select(MapCouponRule).ToList(),
            UpdatedAt = ToDateTime(source.UpdatedAt)
        };
    }

    private static NewCustomerCouponRuleResponse MapCouponRule(NewCustomerCouponRuleDto source)
    {
        return new NewCustomerCouponRuleResponse
        {
            Id = source.Id.ToString(),
            Scene = source.Scene,
            CouponType = source.CouponType,
            Value = source.Value,
            MinimumSpend = source.MinimumSpend,
            ValidDays = source.ValidDays,
            SortOrder = source.SortOrder
        };
    }

    private static NewCustomerInviteRecordListResultResponse MapInviteRecordList(
        NewCustomerInviteRecordListResultDto source)
    {
        return new NewCustomerInviteRecordListResultResponse
        {
            Items = source.Items.Select(MapInviteRecord).ToList(),
            Page = source.Page,
            PageSize = source.PageSize,
            TotalCount = source.TotalCount
        };
    }

    private static NewCustomerInviteRecordResponse MapInviteRecord(NewCustomerInviteRecordDto source)
    {
        return new NewCustomerInviteRecordResponse
        {
            Id = source.Id.ToString(),
            InviterName = source.InviterName,
            InviteeName = source.InviteeName,
            InviteTime = ToDateTime(source.InviteTime),
            OrderStatus = source.OrderStatus,
            RewardStatus = source.RewardStatus,
            RewardIssuedAt = source.RewardIssuedAt.HasValue
                ? ToDateTime(source.RewardIssuedAt.Value)
                : null,
            SourceChannel = source.SourceChannel
        };
    }

    private static NewCustomerGrowthRecordResponse MapGrowthRecord(NewCustomerGrowthRecordDto source)
    {
        return new NewCustomerGrowthRecordResponse
        {
            Id = source.Id.ToString(),
            CustomerKey = source.CustomerKey,
            CustomerName = source.CustomerName,
            RegisteredAt = ToDateTime(source.RegisteredAt),
            GiftClaimedAt = source.GiftClaimedAt.HasValue
                ? ToDateTime(source.GiftClaimedAt.Value)
                : null,
            FirstOrderAt = source.FirstOrderAt.HasValue
                ? ToDateTime(source.FirstOrderAt.Value)
                : null,
            SourceChannel = source.SourceChannel
        };
    }

    private static string ToDateTime(DateTime value)
    {
        return value.ToString("yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture);
    }
}
