using MediatR;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using TakeoutSaaS.Application.App.Products.Commands;
using TakeoutSaaS.Application.App.Products.Dto;
using TakeoutSaaS.Application.App.Products.Queries;
using TakeoutSaaS.Application.App.Stores.Services;
using TakeoutSaaS.Infrastructure.App.Persistence;
using TakeoutSaaS.Shared.Abstractions.Results;
using TakeoutSaaS.Shared.Web.Api;
using TakeoutSaaS.TenantApi.Contracts.Product;

namespace TakeoutSaaS.TenantApi.Controllers;

/// <summary>
/// 租户端规格做法模板管理。
/// </summary>
[ApiVersion("1.0")]
[Authorize]
[Route("api/tenant/v{version:apiVersion}/product")]
public sealed class ProductSpecController(
    IMediator mediator,
    TakeoutAppDbContext dbContext,
    StoreContextService storeContextService) : BaseApiController
{
    /// <summary>
    /// 规格做法模板列表。
    /// </summary>
    [HttpGet("spec/list")]
    [ProducesResponseType(typeof(ApiResponse<IReadOnlyList<ProductSpecItemResponse>>), StatusCodes.Status200OK)]
    public async Task<ApiResponse<IReadOnlyList<ProductSpecItemResponse>>> GetSpecList(
        [FromQuery] ProductSpecListRequest request,
        CancellationToken cancellationToken)
    {
        var storeId = StoreApiHelpers.ParseRequiredSnowflake(request.StoreId, nameof(request.StoreId));
        await EnsureStoreAccessibleAsync(storeId, cancellationToken);

        var result = await mediator.Send(new GetProductSpecTemplateListQuery
        {
            StoreId = storeId,
            Keyword = request.Keyword,
            Type = request.Type,
            Status = request.Status
        }, cancellationToken);

        return ApiResponse<IReadOnlyList<ProductSpecItemResponse>>.Ok(result.Select(MapSpecItem).ToList());
    }

    /// <summary>
    /// 保存规格做法模板。
    /// </summary>
    [HttpPost("spec/save")]
    [ProducesResponseType(typeof(ApiResponse<ProductSpecItemResponse>), StatusCodes.Status200OK)]
    public async Task<ApiResponse<ProductSpecItemResponse>> SaveSpec(
        [FromBody] SaveProductSpecRequest request,
        CancellationToken cancellationToken)
    {
        var storeId = StoreApiHelpers.ParseRequiredSnowflake(request.StoreId, nameof(request.StoreId));
        await EnsureStoreAccessibleAsync(storeId, cancellationToken);

        var result = await mediator.Send(new SaveProductSpecTemplateCommand
        {
            StoreId = storeId,
            SpecId = StoreApiHelpers.ParseSnowflakeOrNull(request.Id),
            Name = request.Name,
            Type = request.Type,
            SelectionType = request.SelectionType,
            IsRequired = request.IsRequired,
            Sort = request.Sort,
            Status = request.Status,
            ProductIds = StoreApiHelpers.ParseSnowflakeList(request.ProductIds),
            Values = (request.Values ?? [])
                .Select(item => new SaveProductSpecTemplateValueCommand
                {
                    Id = StoreApiHelpers.ParseSnowflakeOrNull(item.Id),
                    Name = item.Name,
                    ExtraPrice = item.ExtraPrice,
                    Sort = item.Sort
                })
                .ToList()
        }, cancellationToken);

        return ApiResponse<ProductSpecItemResponse>.Ok(MapSpecItem(result));
    }

    /// <summary>
    /// 删除规格做法模板。
    /// </summary>
    [HttpPost("spec/delete")]
    [ProducesResponseType(typeof(ApiResponse<object>), StatusCodes.Status200OK)]
    public async Task<ApiResponse<object>> DeleteSpec(
        [FromBody] DeleteProductSpecRequest request,
        CancellationToken cancellationToken)
    {
        var storeId = StoreApiHelpers.ParseRequiredSnowflake(request.StoreId, nameof(request.StoreId));
        await EnsureStoreAccessibleAsync(storeId, cancellationToken);

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

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

    /// <summary>
    /// 修改规格做法模板状态。
    /// </summary>
    [HttpPost("spec/status")]
    [ProducesResponseType(typeof(ApiResponse<ProductSpecItemResponse>), StatusCodes.Status200OK)]
    public async Task<ApiResponse<ProductSpecItemResponse>> ChangeSpecStatus(
        [FromBody] ChangeProductSpecStatusRequest request,
        CancellationToken cancellationToken)
    {
        var storeId = StoreApiHelpers.ParseRequiredSnowflake(request.StoreId, nameof(request.StoreId));
        await EnsureStoreAccessibleAsync(storeId, cancellationToken);

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

        return ApiResponse<ProductSpecItemResponse>.Ok(MapSpecItem(result));
    }

    /// <summary>
    /// 复制规格做法模板。
    /// </summary>
    [HttpPost("spec/copy")]
    [ProducesResponseType(typeof(ApiResponse<ProductSpecItemResponse>), StatusCodes.Status200OK)]
    public async Task<ApiResponse<ProductSpecItemResponse>> CopySpec(
        [FromBody] CopyProductSpecRequest request,
        CancellationToken cancellationToken)
    {
        var storeId = StoreApiHelpers.ParseRequiredSnowflake(request.StoreId, nameof(request.StoreId));
        await EnsureStoreAccessibleAsync(storeId, cancellationToken);

        var result = await mediator.Send(new CopyProductSpecTemplateCommand
        {
            StoreId = storeId,
            SpecId = StoreApiHelpers.ParseRequiredSnowflake(request.SpecId, nameof(request.SpecId)),
            NewName = request.NewName
        }, cancellationToken);

        return ApiResponse<ProductSpecItemResponse>.Ok(MapSpecItem(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 ProductSpecItemResponse MapSpecItem(ProductSpecTemplateItemDto source)
    {
        return new ProductSpecItemResponse
        {
            Id = source.Id.ToString(),
            Name = source.Name,
            Type = source.Type,
            SelectionType = source.SelectionType,
            IsRequired = source.IsRequired,
            Sort = source.Sort,
            Status = source.Status,
            ProductCount = source.ProductCount,
            ProductIds = source.ProductIds.Select(item => item.ToString()).ToList(),
            Values = source.Values
                .Select(item => new ProductSpecValueResponse
                {
                    Id = item.Id.ToString(),
                    Name = item.Name,
                    ExtraPrice = item.ExtraPrice,
                    Sort = item.Sort
                })
                .ToList(),
            UpdatedAt = source.UpdatedAt.ToString("yyyy-MM-dd HH:mm:ss")
        };
    }
}
