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 ProductLabelController(
    IMediator mediator,
    TakeoutAppDbContext dbContext,
    StoreContextService storeContextService) : BaseApiController
{
    /// <summary>
    /// 商品标签列表。
    /// </summary>
    [HttpGet("label/list")]
    [ProducesResponseType(typeof(ApiResponse<IReadOnlyList<ProductLabelItemResponse>>), StatusCodes.Status200OK)]
    public async Task<ApiResponse<IReadOnlyList<ProductLabelItemResponse>>> GetLabelList(
        [FromQuery] ProductLabelListRequest request,
        CancellationToken cancellationToken)
    {
        var storeId = StoreApiHelpers.ParseRequiredSnowflake(request.StoreId, nameof(request.StoreId));
        await EnsureStoreAccessibleAsync(storeId, cancellationToken);

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

        return ApiResponse<IReadOnlyList<ProductLabelItemResponse>>.Ok(result.Select(MapLabelItem).ToList());
    }

    /// <summary>
    /// 保存商品标签。
    /// </summary>
    [HttpPost("label/save")]
    [ProducesResponseType(typeof(ApiResponse<ProductLabelItemResponse>), StatusCodes.Status200OK)]
    public async Task<ApiResponse<ProductLabelItemResponse>> SaveLabel(
        [FromBody] SaveProductLabelRequest request,
        CancellationToken cancellationToken)
    {
        var storeId = StoreApiHelpers.ParseRequiredSnowflake(request.StoreId, nameof(request.StoreId));
        await EnsureStoreAccessibleAsync(storeId, cancellationToken);

        var result = await mediator.Send(new SaveProductLabelCommand
        {
            StoreId = storeId,
            LabelId = StoreApiHelpers.ParseSnowflakeOrNull(request.Id),
            Name = request.Name,
            Color = request.Color,
            Sort = request.Sort,
            Status = request.Status
        }, cancellationToken);

        return ApiResponse<ProductLabelItemResponse>.Ok(MapLabelItem(result));
    }

    /// <summary>
    /// 删除商品标签。
    /// </summary>
    [HttpPost("label/delete")]
    [ProducesResponseType(typeof(ApiResponse<object>), StatusCodes.Status200OK)]
    public async Task<ApiResponse<object>> DeleteLabel(
        [FromBody] DeleteProductLabelRequest request,
        CancellationToken cancellationToken)
    {
        var storeId = StoreApiHelpers.ParseRequiredSnowflake(request.StoreId, nameof(request.StoreId));
        await EnsureStoreAccessibleAsync(storeId, cancellationToken);

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

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

    /// <summary>
    /// 修改商品标签状态。
    /// </summary>
    [HttpPost("label/status")]
    [ProducesResponseType(typeof(ApiResponse<ProductLabelItemResponse>), StatusCodes.Status200OK)]
    public async Task<ApiResponse<ProductLabelItemResponse>> ChangeLabelStatus(
        [FromBody] ChangeProductLabelStatusRequest request,
        CancellationToken cancellationToken)
    {
        var storeId = StoreApiHelpers.ParseRequiredSnowflake(request.StoreId, nameof(request.StoreId));
        await EnsureStoreAccessibleAsync(storeId, cancellationToken);

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

        return ApiResponse<ProductLabelItemResponse>.Ok(MapLabelItem(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 ProductLabelItemResponse MapLabelItem(ProductLabelItemDto source)
    {
        return new ProductLabelItemResponse
        {
            Id = source.Id.ToString(),
            Name = source.Name,
            Color = source.Color,
            Sort = source.Sort,
            Status = source.Status,
            ProductCount = source.ProductCount,
            UpdatedAt = source.UpdatedAt.ToString("yyyy-MM-dd HH:mm:ss")
        };
    }
}
