using MediatR;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using TakeoutSaaS.Application.App.Inventory.Commands;
using TakeoutSaaS.Application.App.Inventory.Dto;
using TakeoutSaaS.Application.App.Inventory.Queries;
using TakeoutSaaS.Module.Authorization.Attributes;
using TakeoutSaaS.Shared.Abstractions.Constants;
using TakeoutSaaS.Shared.Abstractions.Results;
using TakeoutSaaS.Shared.Web.Api;

namespace TakeoutSaaS.AdminApi.Controllers;

/// <summary>
/// 库存管理。
/// </summary>
[ApiVersion("1.0")]
[Authorize]
[Route("api/admin/v{version:apiVersion}/stores/{storeId:long}/inventory")]
public sealed class InventoryController(IMediator mediator) : BaseApiController
{
    /// <summary>
    /// 查询库存。
    /// </summary>
    [HttpGet("{productSkuId:long}")]
    [PermissionAuthorize("inventory:read")]
    [ProducesResponseType(typeof(ApiResponse<InventoryItemDto>), StatusCodes.Status200OK)]
    public async Task<ApiResponse<InventoryItemDto>> Get(long storeId, long productSkuId, CancellationToken cancellationToken)
    {
        var result = await mediator.Send(new GetInventoryItemQuery { StoreId = storeId, ProductSkuId = productSkuId }, cancellationToken);
        return result is null
            ? ApiResponse<InventoryItemDto>.Error(ErrorCodes.NotFound, "库存不存在")
            : ApiResponse<InventoryItemDto>.Ok(result);
    }

    /// <summary>
    /// 调整库存（入库/盘点/报损）。
    /// </summary>
    [HttpPost("adjust")]
    [PermissionAuthorize("inventory:adjust")]
    [ProducesResponseType(typeof(ApiResponse<InventoryItemDto>), StatusCodes.Status200OK)]
    public async Task<ApiResponse<InventoryItemDto>> Adjust(long storeId, [FromBody] AdjustInventoryCommand command, CancellationToken cancellationToken)
    {
        if (command.StoreId == 0)
        {
            command = command with { StoreId = storeId };
        }

        var result = await mediator.Send(command, cancellationToken);
        return ApiResponse<InventoryItemDto>.Ok(result);
    }

    /// <summary>
    /// 锁定库存（下单占用）。
    /// </summary>
    [HttpPost("lock")]
    [PermissionAuthorize("inventory:lock")]
    [ProducesResponseType(typeof(ApiResponse<InventoryItemDto>), StatusCodes.Status200OK)]
    public async Task<ApiResponse<InventoryItemDto>> Lock(long storeId, [FromBody] LockInventoryCommand command, CancellationToken cancellationToken)
    {
        if (command.StoreId == 0)
        {
            command = command with { StoreId = storeId };
        }

        var result = await mediator.Send(command, cancellationToken);
        return ApiResponse<InventoryItemDto>.Ok(result);
    }

    /// <summary>
    /// 释放库存（取消订单等）。
    /// </summary>
    [HttpPost("release")]
    [PermissionAuthorize("inventory:release")]
    [ProducesResponseType(typeof(ApiResponse<InventoryItemDto>), StatusCodes.Status200OK)]
    public async Task<ApiResponse<InventoryItemDto>> Release(long storeId, [FromBody] ReleaseInventoryCommand command, CancellationToken cancellationToken)
    {
        if (command.StoreId == 0)
        {
            command = command with { StoreId = storeId };
        }

        var result = await mediator.Send(command, cancellationToken);
        return ApiResponse<InventoryItemDto>.Ok(result);
    }

    /// <summary>
    /// 扣减库存（支付或履约成功）。
    /// </summary>
    [HttpPost("deduct")]
    [PermissionAuthorize("inventory:deduct")]
    [ProducesResponseType(typeof(ApiResponse<InventoryItemDto>), StatusCodes.Status200OK)]
    public async Task<ApiResponse<InventoryItemDto>> Deduct(long storeId, [FromBody] DeductInventoryCommand command, CancellationToken cancellationToken)
    {
        if (command.StoreId == 0)
        {
            command = command with { StoreId = storeId };
        }

        var result = await mediator.Send(command, cancellationToken);
        return ApiResponse<InventoryItemDto>.Ok(result);
    }

    /// <summary>
    /// 查询批次列表。
    /// </summary>
    [HttpGet("{productSkuId:long}/batches")]
    [PermissionAuthorize("inventory:batch:read")]
    [ProducesResponseType(typeof(ApiResponse<IReadOnlyList<InventoryBatchDto>>), StatusCodes.Status200OK)]
    public async Task<ApiResponse<IReadOnlyList<InventoryBatchDto>>> GetBatches(long storeId, long productSkuId, CancellationToken cancellationToken)
    {
        var result = await mediator.Send(new GetInventoryBatchesQuery
        {
            StoreId = storeId,
            ProductSkuId = productSkuId
        }, cancellationToken);
        return ApiResponse<IReadOnlyList<InventoryBatchDto>>.Ok(result);
    }

    /// <summary>
    /// 新增或更新批次。
    /// </summary>
    [HttpPost("{productSkuId:long}/batches")]
    [PermissionAuthorize("inventory:batch:update")]
    [ProducesResponseType(typeof(ApiResponse<InventoryBatchDto>), StatusCodes.Status200OK)]
    public async Task<ApiResponse<InventoryBatchDto>> UpsertBatch(long storeId, long productSkuId, [FromBody] UpsertInventoryBatchCommand command, CancellationToken cancellationToken)
    {
        if (command.StoreId == 0 || command.ProductSkuId == 0)
        {
            command = command with { StoreId = storeId, ProductSkuId = productSkuId };
        }

        var result = await mediator.Send(command, cancellationToken);
        return ApiResponse<InventoryBatchDto>.Ok(result);
    }

    /// <summary>
    /// 释放过期锁定。
    /// </summary>
    [HttpPost("locks/expire")]
    [PermissionAuthorize("inventory:release")]
    [ProducesResponseType(typeof(ApiResponse<int>), StatusCodes.Status200OK)]
    public async Task<ApiResponse<int>> ReleaseExpiredLocks(CancellationToken cancellationToken)
    {
        var count = await mediator.Send(new ReleaseExpiredInventoryLocksCommand(), cancellationToken);
        return ApiResponse<int>.Ok(count);
    }
}
