using MediatR;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using TakeoutSaaS.Application.App.Tenants.Commands;
using TakeoutSaaS.Application.App.Tenants.Contracts;
using TakeoutSaaS.Application.App.Tenants.Queries;
using TakeoutSaaS.Module.Authorization.Attributes;
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}/tenants")]
public sealed class TenantsController(IMediator mediator) : BaseApiController
{
    /// <summary>
    /// 获取租户列表（用于下拉选择器）。
    /// </summary>
    /// <param name="keyword">关键字（租户名称/编码）。</param>
    /// <param name="page">页码（从 1 开始）。</param>
    /// <param name="pageSize">每页条数。</param>
    /// <param name="cancellationToken">取消标记。</param>
    /// <returns>租户分页列表。</returns>
    [HttpGet]
    [PermissionAuthorize("tenant:read")]
    [ProducesResponseType(typeof(ApiResponse<PagedResult<TenantListItemDto>>), StatusCodes.Status200OK)]
    public async Task<ApiResponse<PagedResult<TenantListItemDto>>> List(
        [FromQuery] string? keyword,
        [FromQuery] int page = 1,
        [FromQuery] int pageSize = 20,
        CancellationToken cancellationToken = default)
    {
        // 1. 构造查询
        var query = new ListTenantsQuery
        {
            Keyword = keyword,
            Page = page,
            PageSize = pageSize
        };

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

        // 3. 返回租户分页列表
        return ApiResponse<PagedResult<TenantListItemDto>>.Ok(result);
    }

    /// <summary>
    /// 后台手动新增租户（直接入驻：创建租户 + 认证 + 订阅 + 管理员账号）。
    /// </summary>
    /// <param name="command">新增租户命令。</param>
    /// <param name="cancellationToken">取消标记。</param>
    /// <returns>租户详情。</returns>
    [HttpPost("manual")]
    [PermissionAuthorize("tenant:create")]
    [ProducesResponseType(typeof(ApiResponse<TenantDetailDto>), StatusCodes.Status200OK)]
    [ProducesResponseType(typeof(ApiResponse<object>), StatusCodes.Status400BadRequest)]
    [ProducesResponseType(typeof(ApiResponse<object>), StatusCodes.Status409Conflict)]
    public async Task<ApiResponse<TenantDetailDto>> CreateManually(
        [FromBody] CreateTenantManuallyCommand command,
        CancellationToken cancellationToken = default)
    {
        // 1. 执行命令
        var result = await mediator.Send(command, cancellationToken);

        // 2. 返回租户详情
        return ApiResponse<TenantDetailDto>.Ok(result);
    }

    /// <summary>
    /// 获取租户详情（包含认证、订阅、套餐信息）。
    /// </summary>
    /// <param name="id">租户 ID（雪花算法）。</param>
    /// <param name="cancellationToken">取消标记。</param>
    /// <returns>租户详情。</returns>
    [HttpGet("{id:long}")]
    [PermissionAuthorize("tenant:read")]
    [ProducesResponseType(typeof(ApiResponse<TenantDetailDto>), StatusCodes.Status200OK)]
    [ProducesResponseType(typeof(ApiResponse<object>), StatusCodes.Status404NotFound)]
    public async Task<IActionResult> GetDetail(long id, CancellationToken cancellationToken = default)
    {
        // 1. 构造查询
        var query = new GetTenantDetailQuery { TenantId = id };

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

        // 3. 返回结果
        if (result is null)
        {
            return NotFound(ApiResponse<object>.Error(404, "租户不存在"));
        }

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

    /// <summary>
    /// 更新租户基本信息。
    /// </summary>
    /// <param name="id">租户 ID（雪花算法）。</param>
    /// <param name="command">更新命令。</param>
    /// <param name="cancellationToken">取消标记。</param>
    /// <returns>无内容。</returns>
    [HttpPut("{id:long}")]
    [PermissionAuthorize("tenant:update")]
    [ProducesResponseType(typeof(ApiResponse<object>), StatusCodes.Status200OK)]
    [ProducesResponseType(typeof(ApiResponse<object>), StatusCodes.Status400BadRequest)]
    [ProducesResponseType(typeof(ApiResponse<object>), StatusCodes.Status404NotFound)]
    public async Task<ApiResponse<object>> Update(
        long id,
        [FromBody] UpdateTenantCommand command,
        CancellationToken cancellationToken = default)
    {
        // 1. 确保路径参数与请求体一致
        var updatedCommand = command with { TenantId = id.ToString() };

        // 2. 执行命令
        await mediator.Send(updatedCommand, cancellationToken);

        // 3. 返回成功
        return ApiResponse<object>.Ok(null, "更新成功");
    }

    /// <summary>
    /// 更新租户认证信息。
    /// </summary>
    /// <param name="id">租户 ID（雪花算法）。</param>
    /// <param name="command">更新命令。</param>
    /// <param name="cancellationToken">取消标记。</param>
    /// <returns>无内容。</returns>
    [HttpPut("{id:long}/verification")]
    [PermissionAuthorize("tenant:update")]
    [ProducesResponseType(typeof(ApiResponse<object>), StatusCodes.Status200OK)]
    [ProducesResponseType(typeof(ApiResponse<object>), StatusCodes.Status400BadRequest)]
    [ProducesResponseType(typeof(ApiResponse<object>), StatusCodes.Status404NotFound)]
    public async Task<ApiResponse<object>> UpdateVerification(
        long id,
        [FromBody] UpdateTenantVerificationCommand command,
        CancellationToken cancellationToken = default)
    {
        // 1. 确保路径参数与请求体一致
        var updatedCommand = command with { TenantId = id.ToString() };

        // 2. 执行命令
        await mediator.Send(updatedCommand, cancellationToken);

        // 3. 返回成功
        return ApiResponse<object>.Ok(null, "更新成功");
    }

    /// <summary>
    /// 获取租户配额使用情况。
    /// </summary>
    /// <param name="id">租户 ID（雪花算法）。</param>
    /// <param name="cancellationToken">取消标记。</param>
    /// <returns>配额使用情况列表。</returns>
    [HttpGet("{id:long}/quota-usage")]
    [PermissionAuthorize("tenant:read")]
    [ProducesResponseType(typeof(ApiResponse<IReadOnlyList<TenantQuotaUsageDto>>), StatusCodes.Status200OK)]
    public async Task<ApiResponse<IReadOnlyList<TenantQuotaUsageDto>>> GetQuotaUsage(
        long id,
        CancellationToken cancellationToken = default)
    {
        // 1. 构造查询
        var query = new GetTenantQuotaUsageQuery { TenantId = id };

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

        // 3. 返回配额使用情况列表
        return ApiResponse<IReadOnlyList<TenantQuotaUsageDto>>.Ok(result);
    }

    /// <summary>
    /// 获取租户账单列表（分页）。
    /// </summary>
    /// <param name="id">租户 ID（雪花算法）。</param>
    /// <param name="Page">页码（从 1 开始）。</param>
    /// <param name="PageSize">每页条数。</param>
    /// <param name="cancellationToken">取消标记。</param>
    /// <returns>账单分页列表。</returns>
    [HttpGet("{id:long}/billings")]
    [PermissionAuthorize("tenant:read")]
    [ProducesResponseType(typeof(ApiResponse<PagedResult<TenantBillingListDto>>), StatusCodes.Status200OK)]
    public async Task<ApiResponse<PagedResult<TenantBillingListDto>>> GetBillings(
        long id,
        [FromQuery] int Page = 1,
        [FromQuery] int PageSize = 10,
        CancellationToken cancellationToken = default)
    {
        // 1. 构造查询
        var query = new GetTenantBillingsQuery
        {
            TenantId = id,
            Page = Page,
            PageSize = PageSize
        };

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

        // 3. 返回账单分页列表
        return ApiResponse<PagedResult<TenantBillingListDto>>.Ok(result);
    }

    /// <summary>
    /// 审核通过租户。
    /// </summary>
    /// <param name="id">租户 ID（雪花算法）。</param>
    /// <param name="command">审核通过命令。</param>
    /// <param name="cancellationToken">取消标记。</param>
    /// <returns>无内容。</returns>
    [HttpPut("{id:long}/approve")]
    [PermissionAuthorize("tenant:review")]
    [ProducesResponseType(typeof(ApiResponse<object>), StatusCodes.Status200OK)]
    [ProducesResponseType(typeof(ApiResponse<object>), StatusCodes.Status400BadRequest)]
    [ProducesResponseType(typeof(ApiResponse<object>), StatusCodes.Status404NotFound)]
    public async Task<ApiResponse<object>> Approve(
        long id,
        [FromBody] ApproveTenantCommand command,
        CancellationToken cancellationToken = default)
    {
        // 1. 确保路径参数与请求体一致
        var updatedCommand = command with { TenantId = id.ToString() };

        // 2. 执行命令
        await mediator.Send(updatedCommand, cancellationToken);

        // 3. 返回成功
        return ApiResponse<object>.Ok(null, "审核通过");
    }

    /// <summary>
    /// 审核驳回租户。
    /// </summary>
    /// <param name="id">租户 ID（雪花算法）。</param>
    /// <param name="command">审核驳回命令。</param>
    /// <param name="cancellationToken">取消标记。</param>
    /// <returns>无内容。</returns>
    [HttpPut("{id:long}/reject")]
    [PermissionAuthorize("tenant:review")]
    [ProducesResponseType(typeof(ApiResponse<object>), StatusCodes.Status200OK)]
    [ProducesResponseType(typeof(ApiResponse<object>), StatusCodes.Status400BadRequest)]
    [ProducesResponseType(typeof(ApiResponse<object>), StatusCodes.Status404NotFound)]
    public async Task<ApiResponse<object>> Reject(
        long id,
        [FromBody] RejectTenantCommand command,
        CancellationToken cancellationToken = default)
    {
        // 1. 确保路径参数与请求体一致
        var updatedCommand = command with { TenantId = id.ToString() };

        // 2. 执行命令
        await mediator.Send(updatedCommand, cancellationToken);

        // 3. 返回成功
        return ApiResponse<object>.Ok(null, "审核驳回");
    }

    /// <summary>
    /// 获取租户审核领取信息。
    /// </summary>
    /// <param name="id">租户 ID（雪花算法）。</param>
    /// <param name="cancellationToken">取消标记。</param>
    /// <returns>审核领取信息，未领取返回 null。</returns>
    [HttpGet("{id:long}/review/claim")]
    [PermissionAuthorize("tenant:review")]
    [ProducesResponseType(typeof(ApiResponse<TenantReviewClaimDto>), StatusCodes.Status200OK)]
    public async Task<ApiResponse<TenantReviewClaimDto?>> GetReviewClaim(
        long id,
        CancellationToken cancellationToken = default)
    {
        // 1. 构造查询
        var query = new GetTenantReviewClaimQuery(id);

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

        // 3. 返回结果
        return ApiResponse<TenantReviewClaimDto?>.Ok(result);
    }

    /// <summary>
    /// 领取租户审核。
    /// </summary>
    /// <param name="id">租户 ID（雪花算法）。</param>
    /// <param name="cancellationToken">取消标记。</param>
    /// <returns>审核领取信息。</returns>
    [HttpPost("{id:long}/review/claim")]
    [PermissionAuthorize("tenant:review")]
    [ProducesResponseType(typeof(ApiResponse<TenantReviewClaimDto>), StatusCodes.Status200OK)]
    [ProducesResponseType(typeof(ApiResponse<object>), StatusCodes.Status400BadRequest)]
    [ProducesResponseType(typeof(ApiResponse<object>), StatusCodes.Status409Conflict)]
    public async Task<ApiResponse<TenantReviewClaimDto>> ClaimReview(
        long id,
        CancellationToken cancellationToken = default)
    {
        // 1. 构造命令
        var command = new ClaimTenantReviewCommand(id);

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

        // 3. 返回结果
        return ApiResponse<TenantReviewClaimDto>.Ok(result);
    }

    /// <summary>
    /// 强制接管租户审核（仅超级管理员）。
    /// </summary>
    /// <param name="id">租户 ID（雪花算法）。</param>
    /// <param name="cancellationToken">取消标记。</param>
    /// <returns>审核领取信息。</returns>
    [HttpPost("{id:long}/review/force-claim")]
    [PermissionAuthorize("tenant:review:force-claim")]
    [ProducesResponseType(typeof(ApiResponse<TenantReviewClaimDto>), StatusCodes.Status200OK)]
    [ProducesResponseType(typeof(ApiResponse<object>), StatusCodes.Status400BadRequest)]
    public async Task<ApiResponse<TenantReviewClaimDto>> ForceClaimReview(
        long id,
        CancellationToken cancellationToken = default)
    {
        // 1. 构造命令
        var command = new ForceClaimTenantReviewCommand(id);

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

        // 3. 返回结果
        return ApiResponse<TenantReviewClaimDto>.Ok(result);
    }

    /// <summary>
    /// 释放租户审核领取。
    /// </summary>
    /// <param name="id">租户 ID（雪花算法）。</param>
    /// <param name="cancellationToken">取消标记。</param>
    /// <returns>无内容。</returns>
    [HttpPost("{id:long}/review/release")]
    [PermissionAuthorize("tenant:review")]
    [ProducesResponseType(typeof(ApiResponse<object>), StatusCodes.Status200OK)]
    [ProducesResponseType(typeof(ApiResponse<object>), StatusCodes.Status400BadRequest)]
    [ProducesResponseType(typeof(ApiResponse<object>), StatusCodes.Status403Forbidden)]
    public async Task<ApiResponse<object>> ReleaseReviewClaim(
        long id,
        CancellationToken cancellationToken = default)
    {
        // 1. 构造命令
        var command = new ReleaseTenantReviewClaimCommand(id);

        // 2. 执行命令
        await mediator.Send(command, cancellationToken);

        // 3. 返回成功
        return ApiResponse<object>.Ok(null, "已释放审核");
    }

    /// <summary>
    /// 获取租户审核日志列表（分页）。
    /// </summary>
    /// <param name="id">租户 ID（雪花算法）。</param>
    /// <param name="page">页码（从 1 开始）。</param>
    /// <param name="pageSize">每页条数。</param>
    /// <param name="cancellationToken">取消标记。</param>
    /// <returns>审核日志分页列表。</returns>
    [HttpGet("{id:long}/audits")]
    [PermissionAuthorize("tenant:read")]
    [ProducesResponseType(typeof(ApiResponse<PagedResult<TenantAuditLogDto>>), StatusCodes.Status200OK)]
    public async Task<ApiResponse<PagedResult<TenantAuditLogDto>>> GetAuditLogs(
        long id,
        [FromQuery] int page = 1,
        [FromQuery] int pageSize = 20,
        CancellationToken cancellationToken = default)
    {
        // 1. 构造查询
        var query = new GetTenantAuditLogsQuery
        {
            TenantId = id,
            Page = page,
            PageSize = pageSize
        };

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

        // 3. 返回审核日志分页列表
        return ApiResponse<PagedResult<TenantAuditLogDto>>.Ok(result);
    }
}
