using MediatR;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using TakeoutSaaS.Application.App.Subscriptions.Commands;
using TakeoutSaaS.Application.App.Subscriptions.Contracts;
using TakeoutSaaS.Application.App.Subscriptions.Queries;
using TakeoutSaaS.Domain.Tenants.Enums;
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}/subscriptions")]
public sealed class SubscriptionsController(IMediator mediator) : BaseApiController
{
    /// <summary>
    /// 获取订阅列表（分页）。
    /// </summary>
    /// <param name="Status">订阅状态。</param>
    /// <param name="TenantPackageId">套餐 ID。</param>
    /// <param name="TenantId">租户 ID。</param>
    /// <param name="TenantKeyword">租户关键词（名称或编码）。</param>
    /// <param name="ExpiringWithinDays">即将到期天数筛选。</param>
    /// <param name="AutoRenew">是否自动续费。</param>
    /// <param name="ExpireFrom">到期时间范围开始。</param>
    /// <param name="ExpireTo">到期时间范围结束。</param>
    /// <param name="Page">页码（从 1 开始）。</param>
    /// <param name="PageSize">每页条数。</param>
    /// <param name="cancellationToken">取消标记。</param>
    /// <returns>订阅分页列表。</returns>
    [HttpGet]
    [PermissionAuthorize("tenant:subscription")]
    [ProducesResponseType(typeof(ApiResponse<PagedResult<SubscriptionListDto>>), StatusCodes.Status200OK)]
    public async Task<ApiResponse<PagedResult<SubscriptionListDto>>> List(
        [FromQuery] SubscriptionStatus? Status,
        [FromQuery] long? TenantPackageId,
        [FromQuery] long? TenantId,
        [FromQuery] string? TenantKeyword,
        [FromQuery] int? ExpiringWithinDays,
        [FromQuery] bool? AutoRenew,
        [FromQuery] DateTime? ExpireFrom,
        [FromQuery] DateTime? ExpireTo,
        [FromQuery] int Page = 1,
        [FromQuery] int PageSize = 10,
        CancellationToken cancellationToken = default)
    {
        // 1. 构造查询
        var query = new ListSubscriptionsQuery
        {
            Status = Status,
            TenantPackageId = TenantPackageId,
            TenantId = TenantId,
            TenantKeyword = TenantKeyword,
            ExpiringWithinDays = ExpiringWithinDays,
            AutoRenew = AutoRenew,
            ExpireFrom = ExpireFrom,
            ExpireTo = ExpireTo,
            Page = Page,
            PageSize = PageSize
        };

        // 2. 执行查询
        var result = await mediator.Send(query, cancellationToken);

        // 3. 返回订阅分页列表
        return ApiResponse<PagedResult<SubscriptionListDto>>.Ok(result);
    }

    /// <summary>
    /// 获取订阅详情。
    /// </summary>
    /// <param name="id">订阅 ID。</param>
    /// <param name="cancellationToken">取消标记。</param>
    /// <returns>订阅详情。</returns>
    [HttpGet("{id:long}")]
    [PermissionAuthorize("tenant:subscription")]
    [ProducesResponseType(typeof(ApiResponse<SubscriptionDetailDto>), StatusCodes.Status200OK)]
    [ProducesResponseType(typeof(ApiResponse<SubscriptionDetailDto>), StatusCodes.Status404NotFound)]
    public async Task<ApiResponse<SubscriptionDetailDto>> GetDetail(
        [FromRoute] long id,
        CancellationToken cancellationToken = default)
    {
        // 1. 构造查询
        var query = new GetSubscriptionDetailQuery { SubscriptionId = id };

        // 2. 执行查询
        var result = await mediator.Send(query, cancellationToken);

        // 3. 如果不存在，返回 404
        if (result is null)
        {
            return ApiResponse<SubscriptionDetailDto>.Error(
                ErrorCodes.NotFound,
                "订阅不存在");
        }

        // 4. 返回订阅详情
        return ApiResponse<SubscriptionDetailDto>.Ok(result);
    }

    /// <summary>
    /// 更新订阅。
    /// </summary>
    /// <param name="id">订阅 ID。</param>
    /// <param name="command">更新命令。</param>
    /// <param name="cancellationToken">取消标记。</param>
    /// <returns>更新后的订阅信息。</returns>
    [HttpPut("{id:long}")]
    [PermissionAuthorize("tenant:subscription")]
    [ProducesResponseType(typeof(ApiResponse<SubscriptionListDto>), StatusCodes.Status200OK)]
    [ProducesResponseType(typeof(ApiResponse<SubscriptionListDto>), StatusCodes.Status404NotFound)]
    public async Task<ApiResponse<SubscriptionListDto>> Update(
        [FromRoute] long id,
        [FromBody] UpdateSubscriptionCommand command,
        CancellationToken cancellationToken = default)
    {
        // 1. 构造命令（使用路由中的 ID）
        var cmd = command with { SubscriptionId = id };

        // 2. 执行命令
        var result = await mediator.Send(cmd, cancellationToken);

        // 3. 如果不存在，返回 404
        if (result is null)
        {
            return ApiResponse<SubscriptionListDto>.Error(
                ErrorCodes.NotFound,
                "订阅不存在");
        }

        // 4. 返回更新后的订阅信息
        return ApiResponse<SubscriptionListDto>.Ok(result);
    }

    /// <summary>
    /// 延期订阅。
    /// </summary>
    /// <param name="id">订阅 ID。</param>
    /// <param name="command">延期命令。</param>
    /// <param name="cancellationToken">取消标记。</param>
    /// <returns>延期后的订阅信息。</returns>
    [HttpPost("{id:long}/extend")]
    [PermissionAuthorize("tenant:subscription")]
    [ProducesResponseType(typeof(ApiResponse<SubscriptionListDto>), StatusCodes.Status200OK)]
    [ProducesResponseType(typeof(ApiResponse<SubscriptionListDto>), StatusCodes.Status404NotFound)]
    public async Task<ApiResponse<SubscriptionListDto>> Extend(
        [FromRoute] long id,
        [FromBody] ExtendSubscriptionCommand command,
        CancellationToken cancellationToken = default)
    {
        // 1. 构造命令（使用路由中的 ID）
        var cmd = command with { SubscriptionId = id };

        // 2. 执行命令
        var result = await mediator.Send(cmd, cancellationToken);

        // 3. 如果不存在，返回 404
        if (result is null)
        {
            return ApiResponse<SubscriptionListDto>.Error(
                ErrorCodes.NotFound,
                "订阅不存在");
        }

        // 4. 返回延期后的订阅信息
        return ApiResponse<SubscriptionListDto>.Ok(result);
    }

    /// <summary>
    /// 变更套餐。
    /// </summary>
    /// <param name="id">订阅 ID。</param>
    /// <param name="command">变更套餐命令。</param>
    /// <param name="cancellationToken">取消标记。</param>
    /// <returns>变更后的订阅信息。</returns>
    [HttpPost("{id:long}/change-plan")]
    [PermissionAuthorize("tenant:subscription")]
    [ProducesResponseType(typeof(ApiResponse<SubscriptionListDto>), StatusCodes.Status200OK)]
    [ProducesResponseType(typeof(ApiResponse<SubscriptionListDto>), StatusCodes.Status404NotFound)]
    public async Task<ApiResponse<SubscriptionListDto>> ChangePlan(
        [FromRoute] long id,
        [FromBody] ChangePlanCommand command,
        CancellationToken cancellationToken = default)
    {
        // 1. 构造命令（使用路由中的 ID）
        var cmd = command with { SubscriptionId = id };

        // 2. 执行命令
        var result = await mediator.Send(cmd, cancellationToken);

        // 3. 如果不存在，返回 404
        if (result is null)
        {
            return ApiResponse<SubscriptionListDto>.Error(
                ErrorCodes.NotFound,
                "订阅不存在");
        }

        // 4. 返回变更后的订阅信息
        return ApiResponse<SubscriptionListDto>.Ok(result);
    }

    /// <summary>
    /// 更新订阅状态。
    /// </summary>
    /// <param name="id">订阅 ID。</param>
    /// <param name="command">更新状态命令。</param>
    /// <param name="cancellationToken">取消标记。</param>
    /// <returns>更新后的订阅信息。</returns>
    [HttpPost("{id:long}/status")]
    [PermissionAuthorize("tenant:subscription")]
    [ProducesResponseType(typeof(ApiResponse<SubscriptionListDto>), StatusCodes.Status200OK)]
    [ProducesResponseType(typeof(ApiResponse<SubscriptionListDto>), StatusCodes.Status404NotFound)]
    public async Task<ApiResponse<SubscriptionListDto>> UpdateStatus(
        [FromRoute] long id,
        [FromBody] UpdateStatusCommand command,
        CancellationToken cancellationToken = default)
    {
        // 1. 构造命令（使用路由中的 ID）
        var cmd = command with { SubscriptionId = id };

        // 2. 执行命令
        var result = await mediator.Send(cmd, cancellationToken);

        // 3. 如果不存在，返回 404
        if (result is null)
        {
            return ApiResponse<SubscriptionListDto>.Error(
                ErrorCodes.NotFound,
                "订阅不存在");
        }

        // 4. 返回更新后的订阅信息
        return ApiResponse<SubscriptionListDto>.Ok(result);
    }
}
