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 ProductScheduleController(
    IMediator mediator,
    TakeoutAppDbContext dbContext,
    StoreContextService storeContextService) : BaseApiController
{
    /// <summary>
    /// 商品时段规则列表。
    /// </summary>
    [HttpGet("schedule/list")]
    [ProducesResponseType(typeof(ApiResponse<IReadOnlyList<ProductScheduleItemResponse>>), StatusCodes.Status200OK)]
    public async Task<ApiResponse<IReadOnlyList<ProductScheduleItemResponse>>> GetScheduleList(
        [FromQuery] ProductScheduleListRequest request,
        CancellationToken cancellationToken)
    {
        var storeId = StoreApiHelpers.ParseRequiredSnowflake(request.StoreId, nameof(request.StoreId));
        await EnsureStoreAccessibleAsync(storeId, cancellationToken);

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

        return ApiResponse<IReadOnlyList<ProductScheduleItemResponse>>.Ok(result.Select(MapScheduleItem).ToList());
    }

    /// <summary>
    /// 保存商品时段规则。
    /// </summary>
    [HttpPost("schedule/save")]
    [ProducesResponseType(typeof(ApiResponse<ProductScheduleItemResponse>), StatusCodes.Status200OK)]
    public async Task<ApiResponse<ProductScheduleItemResponse>> SaveSchedule(
        [FromBody] SaveProductScheduleRequest request,
        CancellationToken cancellationToken)
    {
        var storeId = StoreApiHelpers.ParseRequiredSnowflake(request.StoreId, nameof(request.StoreId));
        await EnsureStoreAccessibleAsync(storeId, cancellationToken);

        var result = await mediator.Send(new SaveProductScheduleCommand
        {
            StoreId = storeId,
            ScheduleId = StoreApiHelpers.ParseSnowflakeOrNull(request.Id),
            Name = request.Name,
            StartTime = request.StartTime,
            EndTime = request.EndTime,
            WeekDays = request.WeekDays ?? [],
            ProductIds = StoreApiHelpers.ParseSnowflakeList(request.ProductIds),
            Status = request.Status
        }, cancellationToken);

        return ApiResponse<ProductScheduleItemResponse>.Ok(MapScheduleItem(result));
    }

    /// <summary>
    /// 删除商品时段规则。
    /// </summary>
    [HttpPost("schedule/delete")]
    [ProducesResponseType(typeof(ApiResponse<object>), StatusCodes.Status200OK)]
    public async Task<ApiResponse<object>> DeleteSchedule(
        [FromBody] DeleteProductScheduleRequest request,
        CancellationToken cancellationToken)
    {
        var storeId = StoreApiHelpers.ParseRequiredSnowflake(request.StoreId, nameof(request.StoreId));
        await EnsureStoreAccessibleAsync(storeId, cancellationToken);

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

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

    /// <summary>
    /// 修改商品时段规则状态。
    /// </summary>
    [HttpPost("schedule/status")]
    [ProducesResponseType(typeof(ApiResponse<ProductScheduleItemResponse>), StatusCodes.Status200OK)]
    public async Task<ApiResponse<ProductScheduleItemResponse>> ChangeScheduleStatus(
        [FromBody] ChangeProductScheduleStatusRequest request,
        CancellationToken cancellationToken)
    {
        var storeId = StoreApiHelpers.ParseRequiredSnowflake(request.StoreId, nameof(request.StoreId));
        await EnsureStoreAccessibleAsync(storeId, cancellationToken);

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

        return ApiResponse<ProductScheduleItemResponse>.Ok(MapScheduleItem(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 ProductScheduleItemResponse MapScheduleItem(ProductScheduleItemDto source)
    {
        return new ProductScheduleItemResponse
        {
            Id = source.Id.ToString(),
            Name = source.Name,
            StartTime = source.StartTime,
            EndTime = source.EndTime,
            WeekDays = source.WeekDays.ToList(),
            Status = source.Status,
            ProductCount = source.ProductCount,
            ProductIds = source.ProductIds.Select(item => item.ToString()).ToList(),
            UpdatedAt = source.UpdatedAt.ToString("yyyy-MM-dd HH:mm:ss")
        };
    }
}
