using System.Globalization;
using MediatR;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using TakeoutSaaS.Application.App.Members.StoredCard.Commands;
using TakeoutSaaS.Application.App.Members.StoredCard.Dto;
using TakeoutSaaS.Application.App.Members.StoredCard.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.Member;

namespace TakeoutSaaS.TenantApi.Controllers;

/// <summary>
/// 会员中心储值卡管理。
/// </summary>
[ApiVersion("1.0")]
[Authorize]
[Route("api/tenant/v{version:apiVersion}/member/stored-card")]
public sealed class MemberStoredCardController(
    IMediator mediator,
    TakeoutAppDbContext dbContext,
    StoreContextService storeContextService)
    : BaseApiController
{
    private const string ViewPermission = "tenant:member:stored-card:view";
    private const string ManagePermission = "tenant:member:stored-card:manage";

    /// <summary>
    /// 获取储值卡方案列表。
    /// </summary>
    [HttpGet("plan/list")]
    [PermissionAuthorize(ViewPermission, ManagePermission)]
    [ProducesResponseType(typeof(ApiResponse<StoredCardPlanListResultResponse>), StatusCodes.Status200OK)]
    public async Task<ApiResponse<StoredCardPlanListResultResponse>> PlanList(
        [FromQuery] StoredCardPlanListRequest request,
        CancellationToken cancellationToken)
    {
        var storeId = StoreApiHelpers.ParseRequiredSnowflake(request.StoreId, nameof(request.StoreId));
        await EnsureStoreAccessibleAsync(storeId, cancellationToken);

        var result = await mediator.Send(new GetStoredCardPlanListQuery
        {
            StoreId = storeId
        }, cancellationToken);

        return ApiResponse<StoredCardPlanListResultResponse>.Ok(new StoredCardPlanListResultResponse
        {
            Items = result.Items.Select(MapPlan).ToList(),
            Stats = new StoredCardPlanStatsResponse
            {
                TotalRechargeAmount = result.Stats.TotalRechargeAmount,
                TotalGiftAmount = result.Stats.TotalGiftAmount,
                CurrentMonthRechargeAmount = result.Stats.CurrentMonthRechargeAmount,
                RechargeMemberCount = result.Stats.RechargeMemberCount
            }
        });
    }

    /// <summary>
    /// 保存储值卡方案。
    /// </summary>
    [HttpPost("plan/save")]
    [PermissionAuthorize(ManagePermission)]
    [ProducesResponseType(typeof(ApiResponse<StoredCardPlanResponse>), StatusCodes.Status200OK)]
    public async Task<ApiResponse<StoredCardPlanResponse>> SavePlan(
        [FromBody] SaveStoredCardPlanRequest request,
        CancellationToken cancellationToken)
    {
        var storeId = StoreApiHelpers.ParseRequiredSnowflake(request.StoreId, nameof(request.StoreId));
        await EnsureStoreAccessibleAsync(storeId, cancellationToken);

        var result = await mediator.Send(new SaveStoredCardPlanCommand
        {
            StoreId = storeId,
            PlanId = StoreApiHelpers.ParseSnowflakeOrNull(request.PlanId),
            RechargeAmount = request.RechargeAmount,
            GiftAmount = request.GiftAmount,
            SortOrder = request.SortOrder,
            Status = request.Status
        }, cancellationToken);

        return ApiResponse<StoredCardPlanResponse>.Ok(MapPlan(result));
    }

    /// <summary>
    /// 修改储值卡方案状态。
    /// </summary>
    [HttpPost("plan/status")]
    [PermissionAuthorize(ManagePermission)]
    [ProducesResponseType(typeof(ApiResponse<StoredCardPlanResponse>), StatusCodes.Status200OK)]
    public async Task<ApiResponse<StoredCardPlanResponse>> ChangePlanStatus(
        [FromBody] ChangeStoredCardPlanStatusRequest request,
        CancellationToken cancellationToken)
    {
        var storeId = StoreApiHelpers.ParseRequiredSnowflake(request.StoreId, nameof(request.StoreId));
        await EnsureStoreAccessibleAsync(storeId, cancellationToken);

        var result = await mediator.Send(new ChangeStoredCardPlanStatusCommand
        {
            StoreId = storeId,
            PlanId = StoreApiHelpers.ParseRequiredSnowflake(request.PlanId, nameof(request.PlanId)),
            Status = request.Status
        }, cancellationToken);

        return ApiResponse<StoredCardPlanResponse>.Ok(MapPlan(result));
    }

    /// <summary>
    /// 删除储值卡方案。
    /// </summary>
    [HttpPost("plan/delete")]
    [PermissionAuthorize(ManagePermission)]
    [ProducesResponseType(typeof(ApiResponse<object>), StatusCodes.Status200OK)]
    public async Task<ApiResponse<object>> DeletePlan(
        [FromBody] DeleteStoredCardPlanRequest request,
        CancellationToken cancellationToken)
    {
        var storeId = StoreApiHelpers.ParseRequiredSnowflake(request.StoreId, nameof(request.StoreId));
        await EnsureStoreAccessibleAsync(storeId, cancellationToken);

        await mediator.Send(new DeleteStoredCardPlanCommand
        {
            StoreId = storeId,
            PlanId = StoreApiHelpers.ParseRequiredSnowflake(request.PlanId, nameof(request.PlanId))
        }, cancellationToken);

        return ApiResponse<object>.Ok(null);
    }

    /// <summary>
    /// 获取充值记录分页。
    /// </summary>
    [HttpGet("record/list")]
    [PermissionAuthorize(ViewPermission, ManagePermission)]
    [ProducesResponseType(typeof(ApiResponse<StoredCardRechargeRecordListResultResponse>), StatusCodes.Status200OK)]
    public async Task<ApiResponse<StoredCardRechargeRecordListResultResponse>> RecordList(
        [FromQuery] StoredCardRechargeRecordListRequest request,
        CancellationToken cancellationToken)
    {
        var storeId = StoreApiHelpers.ParseRequiredSnowflake(request.StoreId, nameof(request.StoreId));
        await EnsureStoreAccessibleAsync(storeId, cancellationToken);

        var result = await mediator.Send(new GetStoredCardRechargeRecordListQuery
        {
            StoreId = storeId,
            StartDateUtc = ParseDateOrNull(request.StartDate, nameof(request.StartDate)),
            EndDateUtc = ParseDateOrNull(request.EndDate, nameof(request.EndDate)),
            Keyword = request.Keyword,
            Page = request.Page,
            PageSize = request.PageSize
        }, cancellationToken);

        return ApiResponse<StoredCardRechargeRecordListResultResponse>.Ok(new StoredCardRechargeRecordListResultResponse
        {
            Items = result.Items.Select(MapRecord).ToList(),
            Page = result.Page,
            PageSize = result.PageSize,
            TotalCount = result.TotalCount
        });
    }

    /// <summary>
    /// 导出充值记录 CSV。
    /// </summary>
    [HttpGet("record/export")]
    [PermissionAuthorize(ManagePermission)]
    [ProducesResponseType(typeof(ApiResponse<StoredCardRechargeRecordExportResponse>), StatusCodes.Status200OK)]
    public async Task<ApiResponse<StoredCardRechargeRecordExportResponse>> ExportRecord(
        [FromQuery] ExportStoredCardRechargeRecordRequest request,
        CancellationToken cancellationToken)
    {
        var storeId = StoreApiHelpers.ParseRequiredSnowflake(request.StoreId, nameof(request.StoreId));
        await EnsureStoreAccessibleAsync(storeId, cancellationToken);

        var result = await mediator.Send(new ExportStoredCardRechargeRecordCsvQuery
        {
            StoreId = storeId,
            StartDateUtc = ParseDateOrNull(request.StartDate, nameof(request.StartDate)),
            EndDateUtc = ParseDateOrNull(request.EndDate, nameof(request.EndDate)),
            Keyword = request.Keyword
        }, cancellationToken);

        return ApiResponse<StoredCardRechargeRecordExportResponse>.Ok(new StoredCardRechargeRecordExportResponse
        {
            FileName = result.FileName,
            FileContentBase64 = result.FileContentBase64,
            TotalCount = result.TotalCount
        });
    }

    /// <summary>
    /// 写入充值记录。
    /// </summary>
    [HttpPost("record/write")]
    [PermissionAuthorize(ManagePermission)]
    [ProducesResponseType(typeof(ApiResponse<StoredCardRechargeRecordResponse>), StatusCodes.Status200OK)]
    public async Task<ApiResponse<StoredCardRechargeRecordResponse>> WriteRecord(
        [FromBody] WriteStoredCardRechargeRecordRequest request,
        CancellationToken cancellationToken)
    {
        var storeId = StoreApiHelpers.ParseRequiredSnowflake(request.StoreId, nameof(request.StoreId));
        await EnsureStoreAccessibleAsync(storeId, cancellationToken);

        var result = await mediator.Send(new WriteStoredCardRechargeRecordCommand
        {
            StoreId = storeId,
            MemberId = StoreApiHelpers.ParseRequiredSnowflake(request.MemberId, nameof(request.MemberId)),
            PlanId = StoreApiHelpers.ParseSnowflakeOrNull(request.PlanId),
            RechargeAmount = request.RechargeAmount,
            GiftAmount = request.GiftAmount,
            PaymentMethod = request.PaymentMethod,
            RechargedAt = request.RechargedAt,
            Remark = request.Remark
        }, cancellationToken);

        return ApiResponse<StoredCardRechargeRecordResponse>.Ok(MapRecord(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 DateTime? ParseDateOrNull(string? value, string fieldName)
    {
        return string.IsNullOrWhiteSpace(value)
            ? null
            : StoreApiHelpers.ParseDateOnly(value, fieldName);
    }

    private static StoredCardPlanResponse MapPlan(MemberStoredCardPlanDto source)
    {
        return new StoredCardPlanResponse
        {
            PlanId = source.PlanId.ToString(),
            RechargeAmount = source.RechargeAmount,
            GiftAmount = source.GiftAmount,
            ArrivedAmount = source.ArrivedAmount,
            SortOrder = source.SortOrder,
            Status = source.Status,
            RechargeCount = source.RechargeCount,
            TotalRechargeAmount = source.TotalRechargeAmount
        };
    }

    private static StoredCardRechargeRecordResponse MapRecord(MemberStoredCardRechargeRecordDto source)
    {
        return new StoredCardRechargeRecordResponse
        {
            RecordId = source.RecordId.ToString(),
            RecordNo = source.RecordNo,
            MemberId = source.MemberId.ToString(),
            MemberName = source.MemberName,
            MemberMobileMasked = source.MemberMobileMasked,
            RechargeAmount = source.RechargeAmount,
            GiftAmount = source.GiftAmount,
            ArrivedAmount = source.ArrivedAmount,
            PaymentMethod = source.PaymentMethod,
            PaymentMethodText = ResolvePaymentMethodText(source.PaymentMethod),
            RechargedAt = source.RechargedAt.ToString("yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture),
            PlanId = source.PlanId?.ToString(),
            Remark = source.Remark
        };
    }

    private static string ResolvePaymentMethodText(string paymentMethod)
    {
        return (paymentMethod ?? string.Empty).Trim().ToLowerInvariant() switch
        {
            "wechat" => "微信支付",
            "alipay" => "支付宝",
            "cash" => "现金",
            "card" => "刷卡",
            "balance" => "余额",
            _ => "未知"
        };
    }
}
