using Asp.Versioning;
using MediatR;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using TakeoutSaaS.Application.App.Orders.Commands;
using TakeoutSaaS.Application.App.Orders.Dto;
using TakeoutSaaS.Application.App.Orders.Queries;
using TakeoutSaaS.Application.App.Stores.Services;
using TakeoutSaaS.Domain.Orders.Enums;
using TakeoutSaaS.Infrastructure.App.Persistence;
using TakeoutSaaS.Shared.Abstractions.Results;
using TakeoutSaaS.Shared.Web.Api;
using TakeoutSaaS.TenantApi.Contracts.OrderBoard;

namespace TakeoutSaaS.TenantApi.Controllers;

/// <summary>
/// 订单大厅（实时看板）接口。
/// </summary>
[ApiVersion("1.0")]
[Authorize]
[Route("api/tenant/v{version:apiVersion}/order-board")]
public sealed class OrderBoardController(
    IMediator mediator,
    TakeoutAppDbContext dbContext,
    StoreContextService storeContextService) : BaseApiController
{
    /// <summary>
    /// 获取完整看板数据（四列）。
    /// </summary>
    [HttpGet("board")]
    [ProducesResponseType(typeof(ApiResponse<OrderBoardResultDto>), StatusCodes.Status200OK)]
    public async Task<ApiResponse<OrderBoardResultDto>> GetBoard(
        [FromQuery] string storeId,
        [FromQuery] string? channel,
        CancellationToken cancellationToken)
    {
        // 1. 解析并校验门店权限
        var parsedStoreId = StoreApiHelpers.ParseRequiredSnowflake(storeId, nameof(storeId));
        await EnsureStoreAccessibleAsync(parsedStoreId, cancellationToken);

        // 2. 解析渠道筛选
        var channelFilter = ParseChannel(channel);

        // 3. 查询看板数据
        var (_, tenantId, _) = storeContextService.GetRequiredContext();
        var result = await mediator.Send(new GetOrderBoardQuery
        {
            StoreId = parsedStoreId,
            TenantId = tenantId,
            Channel = channelFilter
        }, cancellationToken);

        return ApiResponse<OrderBoardResultDto>.Ok(result);
    }

    /// <summary>
    /// 获取看板统计数据。
    /// </summary>
    [HttpGet("stats")]
    [ProducesResponseType(typeof(ApiResponse<OrderBoardStatsDto>), StatusCodes.Status200OK)]
    public async Task<ApiResponse<OrderBoardStatsDto>> GetStats(
        [FromQuery] string storeId,
        CancellationToken cancellationToken)
    {
        var parsedStoreId = StoreApiHelpers.ParseRequiredSnowflake(storeId, nameof(storeId));
        await EnsureStoreAccessibleAsync(parsedStoreId, cancellationToken);

        var (_, tenantId, _) = storeContextService.GetRequiredContext();
        var result = await mediator.Send(new GetOrderBoardStatsQuery
        {
            StoreId = parsedStoreId,
            TenantId = tenantId
        }, cancellationToken);

        return ApiResponse<OrderBoardStatsDto>.Ok(result);
    }

    /// <summary>
    /// 重连补偿拉取（获取指定时间后的订单变更）。
    /// </summary>
    [HttpGet("pending-since")]
    [ProducesResponseType(typeof(ApiResponse<IReadOnlyList<OrderBoardCardDto>>), StatusCodes.Status200OK)]
    public async Task<ApiResponse<IReadOnlyList<OrderBoardCardDto>>> GetPendingSince(
        [FromQuery] string storeId,
        [FromQuery] DateTime since,
        CancellationToken cancellationToken)
    {
        var parsedStoreId = StoreApiHelpers.ParseRequiredSnowflake(storeId, nameof(storeId));
        await EnsureStoreAccessibleAsync(parsedStoreId, cancellationToken);

        var (_, tenantId, _) = storeContextService.GetRequiredContext();
        var result = await mediator.Send(new GetPendingOrdersSinceQuery
        {
            StoreId = parsedStoreId,
            TenantId = tenantId,
            Since = since
        }, cancellationToken);

        return ApiResponse<IReadOnlyList<OrderBoardCardDto>>.Ok(result);
    }

    /// <summary>
    /// 接单。
    /// </summary>
    [HttpPost("{orderId}/accept")]
    [ProducesResponseType(typeof(ApiResponse<OrderBoardCardDto>), StatusCodes.Status200OK)]
    public async Task<ApiResponse<OrderBoardCardDto>> Accept(
        string orderId,
        CancellationToken cancellationToken)
    {
        var parsedOrderId = StoreApiHelpers.ParseRequiredSnowflake(orderId, nameof(orderId));
        var (userId, tenantId, _) = storeContextService.GetRequiredContext();

        var result = await mediator.Send(new AcceptOrderCommand
        {
            OrderId = parsedOrderId,
            TenantId = tenantId,
            OperatorId = userId
        }, cancellationToken);

        return ApiResponse<OrderBoardCardDto>.Ok(result);
    }

    /// <summary>
    /// 拒单。
    /// </summary>
    [HttpPost("{orderId}/reject")]
    [ProducesResponseType(typeof(ApiResponse<OrderBoardCardDto>), StatusCodes.Status200OK)]
    public async Task<ApiResponse<OrderBoardCardDto>> Reject(
        string orderId,
        [FromBody] RejectOrderRequest request,
        CancellationToken cancellationToken)
    {
        var parsedOrderId = StoreApiHelpers.ParseRequiredSnowflake(orderId, nameof(orderId));
        var (userId, tenantId, _) = storeContextService.GetRequiredContext();

        var result = await mediator.Send(new RejectOrderCommand
        {
            OrderId = parsedOrderId,
            TenantId = tenantId,
            Reason = request.Reason,
            OperatorId = userId
        }, cancellationToken);

        return ApiResponse<OrderBoardCardDto>.Ok(result);
    }

    /// <summary>
    /// 出餐完成。
    /// </summary>
    [HttpPost("{orderId}/complete-preparation")]
    [ProducesResponseType(typeof(ApiResponse<OrderBoardCardDto>), StatusCodes.Status200OK)]
    public async Task<ApiResponse<OrderBoardCardDto>> CompletePreparation(
        string orderId,
        CancellationToken cancellationToken)
    {
        var parsedOrderId = StoreApiHelpers.ParseRequiredSnowflake(orderId, nameof(orderId));
        var (userId, tenantId, _) = storeContextService.GetRequiredContext();

        var result = await mediator.Send(new CompletePreparationCommand
        {
            OrderId = parsedOrderId,
            TenantId = tenantId,
            OperatorId = userId
        }, cancellationToken);

        return ApiResponse<OrderBoardCardDto>.Ok(result);
    }

    /// <summary>
    /// 确认送达/取餐。
    /// </summary>
    [HttpPost("{orderId}/confirm-delivery")]
    [ProducesResponseType(typeof(ApiResponse<OrderBoardCardDto>), StatusCodes.Status200OK)]
    public async Task<ApiResponse<OrderBoardCardDto>> ConfirmDelivery(
        string orderId,
        CancellationToken cancellationToken)
    {
        var parsedOrderId = StoreApiHelpers.ParseRequiredSnowflake(orderId, nameof(orderId));
        var (userId, tenantId, _) = storeContextService.GetRequiredContext();

        var result = await mediator.Send(new ConfirmDeliveryCommand
        {
            OrderId = parsedOrderId,
            TenantId = tenantId,
            OperatorId = userId
        }, cancellationToken);

        return ApiResponse<OrderBoardCardDto>.Ok(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 OrderChannel? ParseChannel(string? value)
    {
        var normalized = (value ?? string.Empty).Trim().ToLowerInvariant();
        return normalized switch
        {
            "miniprogram" => OrderChannel.MiniProgram,
            "scan" => OrderChannel.ScanToOrder,
            "staff" => OrderChannel.StaffConsole,
            "phone" => OrderChannel.PhoneReservation,
            "thirdparty" => OrderChannel.ThirdPartyDelivery,
            _ => null
        };
    }
}
