using MediatR;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using System.ComponentModel.DataAnnotations;
using TakeoutSaaS.Application.App.Tenants.Commands;
using TakeoutSaaS.Application.App.Tenants.Dto;
using TakeoutSaaS.Application.App.Tenants.Queries;
using TakeoutSaaS.Application.Identity.Contracts;
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>
    /// <returns>注册的租户信息。</returns>
    [HttpPost]
    [PermissionAuthorize("tenant:create")]
    [ProducesResponseType(typeof(ApiResponse<TenantDto>), StatusCodes.Status200OK)]
    public async Task<ApiResponse<TenantDto>> Register([FromBody] RegisterTenantCommand command, CancellationToken cancellationToken)
    {
        // 1. 注册租户并初始化套餐
        var result = await mediator.Send(command, cancellationToken);

        // 2. 返回注册结果
        return ApiResponse<TenantDto>.Ok(result);
    }

    /// <summary>
    /// 后台手动新增租户并直接入驻（创建租户 + 认证 + 订阅 + 管理员账号）。
    /// </summary>
    /// <returns>新增后的租户详情。</returns>
    [HttpPost("manual")]
    [PermissionAuthorize("tenant:create")]
    [ProducesResponseType(typeof(ApiResponse<TenantDetailDto>), StatusCodes.Status200OK)]
    public async Task<ApiResponse<TenantDetailDto>> CreateManually([FromBody] CreateTenantManuallyCommand command, CancellationToken cancellationToken)
    {
        // 1. 后台手动新增租户（直接可用）
        var result = await mediator.Send(command, cancellationToken);

        // 2. 返回创建结果
        return ApiResponse<TenantDetailDto>.Ok(result);
    }

    /// <summary>
    /// 分页查询租户。
    /// </summary>
    /// <returns>租户分页结果。</returns>
    [HttpGet]
    [PermissionAuthorize("tenant:read")]
    [ProducesResponseType(typeof(ApiResponse<PagedResult<TenantDto>>), StatusCodes.Status200OK)]
    public async Task<ApiResponse<PagedResult<TenantDto>>> Search([FromQuery] SearchTenantsQuery query, CancellationToken cancellationToken)
    {
        // 1. 查询租户分页
        var result = await mediator.Send(query, cancellationToken);

        // 2. 返回分页数据
        return ApiResponse<PagedResult<TenantDto>>.Ok(result);
    }

    /// <summary>
    /// 查看租户详情。
    /// </summary>
    /// <returns>租户详情。</returns>
    [HttpGet("{tenantId:long}")]
    [PermissionAuthorize("tenant:read")]
    [ProducesResponseType(typeof(ApiResponse<TenantDetailDto>), StatusCodes.Status200OK)]
    public async Task<ApiResponse<TenantDetailDto>> Detail(long tenantId, CancellationToken cancellationToken)
    {
        // 1. 查询租户详情
        var result = await mediator.Send(new GetTenantByIdQuery(tenantId), cancellationToken);

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

    /// <summary>
    /// 更新租户基础信息。
    /// </summary>
    /// <param name="tenantId">租户 ID。</param>
    /// <param name="body">更新命令。</param>
    /// <param name="cancellationToken">取消标记。</param>
    /// <returns>更新结果。</returns>
    [HttpPut("{tenantId:long}")]
    [PermissionAuthorize("tenant:update")]
    [ProducesResponseType(typeof(ApiResponse<object>), StatusCodes.Status200OK)]
    public async Task<ApiResponse<object>> Update(
        long tenantId,
        [FromBody, Required] UpdateTenantCommand body,
        CancellationToken cancellationToken)
    {
        // 1. 校验路由与请求体租户标识一致
        if (body.TenantId != 0 && body.TenantId != tenantId)
        {
            return ApiResponse<object>.Error(StatusCodes.Status400BadRequest, "路由 tenantId 与请求体 tenantId 不一致");
        }

        // 2. (空行后) 绑定租户标识并执行更新（若不存在或冲突则抛出业务异常，由全局异常处理转换为 404/409）
        var command = body with { TenantId = tenantId };
        await mediator.Send(command, cancellationToken);

        // 3. (空行后) 返回成功结果
        return ApiResponse<object>.Ok(null);
    }

    /// <summary>
    /// 提交或更新实名认证资料。
    /// </summary>
    /// <returns>提交的实名认证信息。</returns>
    [HttpPost("{tenantId:long}/verification")]
    [PermissionAuthorize("tenant:review")]
    [ProducesResponseType(typeof(ApiResponse<TenantVerificationDto>), StatusCodes.Status200OK)]
    public async Task<ApiResponse<TenantVerificationDto>> SubmitVerification(
        long tenantId,
        [FromBody] SubmitTenantVerificationCommand body,
        CancellationToken cancellationToken)
    {
        // 1. 合并路由中的租户标识
        var command = body with { TenantId = tenantId };

        // 2. 提交或更新认证资料
        var result = await mediator.Send(command, cancellationToken);

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

    /// <summary>
    /// 审核租户。
    /// </summary>
    /// <returns>审核后的租户信息。</returns>
    [HttpPost("{tenantId:long}/review")]
    [PermissionAuthorize("tenant:review")]
    [ProducesResponseType(typeof(ApiResponse<TenantDto>), StatusCodes.Status200OK)]
    public async Task<ApiResponse<TenantDto>> Review(long tenantId, [FromBody] ReviewTenantCommand body, CancellationToken cancellationToken)
    {
        // 1. 绑定租户标识
        var command = body with { TenantId = tenantId };

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

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

    /// <summary>
    /// 查询当前租户审核领取信息。
    /// </summary>
    /// <returns>领取信息，未领取返回 null。</returns>
    [HttpGet("{tenantId:long}/review/claim")]
    [PermissionAuthorize("tenant:review")]
    [ProducesResponseType(typeof(ApiResponse<TenantReviewClaimDto?>), StatusCodes.Status200OK)]
    public async Task<ApiResponse<TenantReviewClaimDto?>> GetReviewClaim(long tenantId, CancellationToken cancellationToken)
    {
        // 1. 查询领取信息
        var result = await mediator.Send(new GetTenantReviewClaimQuery(tenantId), cancellationToken);

        // 2. 返回领取信息
        return ApiResponse<TenantReviewClaimDto?>.Ok(result);
    }

    /// <summary>
    /// 领取租户入驻审核（领取后仅领取人可操作审核）。
    /// </summary>
    /// <returns>领取结果。</returns>
    [HttpPost("{tenantId:long}/review/claim")]
    [PermissionAuthorize("tenant:review")]
    [ProducesResponseType(typeof(ApiResponse<TenantReviewClaimDto>), StatusCodes.Status200OK)]
    public async Task<ApiResponse<TenantReviewClaimDto>> ClaimReview(long tenantId, CancellationToken cancellationToken)
    {
        // 1. 执行领取
        var result = await mediator.Send(new ClaimTenantReviewCommand { TenantId = tenantId }, cancellationToken);

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

    /// <summary>
    /// 强制接管租户入驻审核（仅超级管理员可用）。
    /// </summary>
    /// <returns>接管后的领取信息。</returns>
    [HttpPost("{tenantId:long}/review/force-claim")]
    [PermissionAuthorize("tenant:review:force-claim")]
    [ProducesResponseType(typeof(ApiResponse<TenantReviewClaimDto>), StatusCodes.Status200OK)]
    public async Task<ApiResponse<TenantReviewClaimDto>> ForceClaimReview(long tenantId, CancellationToken cancellationToken)
    {
        // 1. 执行强制接管
        var result = await mediator.Send(new ForceClaimTenantReviewCommand { TenantId = tenantId }, cancellationToken);

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

    /// <summary>
    /// 释放租户入驻审核领取（仅领取人可释放）。
    /// </summary>
    /// <returns>释放后的领取信息，未领取返回 null。</returns>
    [HttpPost("{tenantId:long}/review/release")]
    [PermissionAuthorize("tenant:review")]
    [ProducesResponseType(typeof(ApiResponse<TenantReviewClaimDto?>), StatusCodes.Status200OK)]
    public async Task<ApiResponse<TenantReviewClaimDto?>> ReleaseReview(long tenantId, CancellationToken cancellationToken)
    {
        // 1. 执行释放
        var result = await mediator.Send(new ReleaseTenantReviewClaimCommand { TenantId = tenantId }, cancellationToken);

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

    /// <summary>
    /// 冻结租户（暂停服务）。
    /// </summary>
    /// <returns>冻结后的租户信息。</returns>
    [HttpPost("{tenantId:long}/freeze")]
    [PermissionAuthorize("tenant:review")]
    [ProducesResponseType(typeof(ApiResponse<TenantDto>), StatusCodes.Status200OK)]
    public async Task<ApiResponse<TenantDto>> Freeze(
        long tenantId,
        [FromBody] FreezeTenantCommand body,
        CancellationToken cancellationToken)
    {
        // 1. 合并路由参数
        var command = body with { TenantId = tenantId };

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

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

    /// <summary>
    /// 解冻租户（恢复服务）。
    /// </summary>
    /// <returns>解冻后的租户信息。</returns>
    [HttpPost("{tenantId:long}/unfreeze")]
    [PermissionAuthorize("tenant:review")]
    [ProducesResponseType(typeof(ApiResponse<TenantDto>), StatusCodes.Status200OK)]
    public async Task<ApiResponse<TenantDto>> Unfreeze(
        long tenantId,
        [FromBody] UnfreezeTenantCommand body,
        CancellationToken cancellationToken)
    {
        // 1. 合并路由参数
        var command = body with { TenantId = tenantId };

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

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

    /// <summary>
    /// 创建或续费租户订阅。
    /// </summary>
    /// <returns>创建或续费的订阅信息。</returns>
    [HttpPost("{tenantId:long}/subscriptions")]
    [PermissionAuthorize("tenant:subscription")]
    [ProducesResponseType(typeof(ApiResponse<TenantSubscriptionDto>), StatusCodes.Status200OK)]
    public async Task<ApiResponse<TenantSubscriptionDto>> CreateSubscription(
        long tenantId,
        [FromBody] CreateTenantSubscriptionCommand body,
        CancellationToken cancellationToken)
    {
        // 1. 绑定租户并创建或续费订阅
        var command = body with { TenantId = tenantId };

        // 2. 返回订阅结果
        var result = await mediator.Send(command, cancellationToken);
        return ApiResponse<TenantSubscriptionDto>.Ok(result);
    }

    /// <summary>
    /// 延期/赠送租户订阅时长（按当前订阅套餐续费）。
    /// </summary>
    /// <returns>续费后的订阅信息。</returns>
    [HttpPost("{tenantId:long}/subscriptions/extend")]
    [PermissionAuthorize("tenant:subscription")]
    [ProducesResponseType(typeof(ApiResponse<TenantSubscriptionDto>), StatusCodes.Status200OK)]
    public async Task<ApiResponse<TenantSubscriptionDto>> ExtendSubscription(
        long tenantId,
        [FromBody] ExtendTenantSubscriptionCommand body,
        CancellationToken cancellationToken)
    {
        // 1. 合并租户标识
        var command = body with { TenantId = tenantId };

        // 2. 执行延期/赠送
        var result = await mediator.Send(command, cancellationToken);

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

    /// <summary>
    /// 套餐升降配。
    /// </summary>
    /// <returns>更新后的订阅信息。</returns>
    [HttpPut("{tenantId:long}/subscriptions/{subscriptionId:long}/plan")]
    [PermissionAuthorize("tenant:subscription")]
    [ProducesResponseType(typeof(ApiResponse<TenantSubscriptionDto>), StatusCodes.Status200OK)]
    public async Task<ApiResponse<TenantSubscriptionDto>> ChangePlan(
        long tenantId,
        long subscriptionId,
        [FromBody] ChangeTenantSubscriptionPlanCommand body,
        CancellationToken cancellationToken)
    {
        // 1. 绑定租户与订阅标识
        var command = body with { TenantId = tenantId, TenantSubscriptionId = subscriptionId };

        // 2. 执行升降配
        var result = await mediator.Send(command, cancellationToken);

        // 3. 返回调整后的订阅
        return ApiResponse<TenantSubscriptionDto>.Ok(result);
    }

    /// <summary>
    /// 查询审核日志。
    /// </summary>
    /// <returns>租户审核日志分页结果。</returns>
    [HttpGet("{tenantId:long}/audits")]
    [PermissionAuthorize("tenant:read")]
    [ProducesResponseType(typeof(ApiResponse<PagedResult<TenantAuditLogDto>>), StatusCodes.Status200OK)]
    public async Task<ApiResponse<PagedResult<TenantAuditLogDto>>> AuditLogs(
        long tenantId,
        [FromQuery] int page = 1,
        [FromQuery] int pageSize = 20,
        CancellationToken cancellationToken = default)
    {
        // 1. 构造审核日志查询
        var query = new GetTenantAuditLogsQuery(tenantId, page, pageSize);

        // 2. 查询并返回分页结果
        var result = await mediator.Send(query, cancellationToken);
        return ApiResponse<PagedResult<TenantAuditLogDto>>.Ok(result);
    }

    /// <summary>
    /// 伪装登录租户（仅平台超级管理员可用）。
    /// </summary>
    /// <returns>目标租户主管理员的令牌对。</returns>
    [HttpPost("{tenantId:long}/impersonate")]
    [PermissionAuthorize("tenant:read")]
    [ProducesResponseType(typeof(ApiResponse<TokenResponse>), StatusCodes.Status200OK)]
    public async Task<ApiResponse<TokenResponse>> Impersonate(long tenantId, CancellationToken cancellationToken)
    {
        // 1. 执行伪装登录
        var result = await mediator.Send(new ImpersonateTenantCommand { TenantId = tenantId }, cancellationToken);

        // 2. 返回令牌
        return ApiResponse<TokenResponse>.Ok(result);
    }

    /// <summary>
    /// 生成租户主管理员重置密码链接（仅平台超级管理员可用）。
    /// </summary>
    /// <remarks>链接默认 24 小时有效且仅可使用一次。</remarks>
    /// <returns>重置密码链接。</returns>
    [HttpPost("{tenantId:long}/admin/reset-link")]
    [PermissionAuthorize("tenant:read")]
    [ProducesResponseType(typeof(ApiResponse<string>), StatusCodes.Status200OK)]
    public async Task<ApiResponse<string>> CreateAdminResetLink(long tenantId, CancellationToken cancellationToken)
    {
        // 1. 生成一次性令牌
        var token = await mediator.Send(new CreateTenantAdminResetLinkTokenCommand { TenantId = tenantId }, cancellationToken);

        // 2. (空行后) 解析前端来源（优先 Origin，避免拼成 AdminApi 域名）
        var origin = Request.Headers.Origin.ToString();
        if (string.IsNullOrWhiteSpace(origin))
        {
            origin = $"{Request.Scheme}://{Request.Host}";
        }

        origin = origin.TrimEnd('/');
        var resetUrl = $"{origin}/#/auth/reset-password?token={Uri.EscapeDataString(token)}";

        // 3. (空行后) 返回链接
        return ApiResponse<string>.Ok(data: resetUrl);
    }

    /// <summary>
    /// 配额校验并占用额度（门店/账号/短信/配送）。
    /// </summary>
    /// <remarks>需在请求头携带 X-Tenant-Id 对应的租户。</remarks>
    /// <returns>配额校验结果。</returns>
    [HttpPost("{tenantId:long}/quotas/check")]
    [PermissionAuthorize("tenant:quota:check")]
    [ProducesResponseType(typeof(ApiResponse<QuotaCheckResultDto>), StatusCodes.Status200OK)]
    public async Task<ApiResponse<QuotaCheckResultDto>> CheckQuota(
        long tenantId,
        [FromBody, Required] CheckTenantQuotaCommand body,
        CancellationToken cancellationToken)
    {
        // 1. 绑定租户标识
        var command = body with { TenantId = tenantId };

        // 2. 校验并占用配额
        var result = await mediator.Send(command, cancellationToken);
        return ApiResponse<QuotaCheckResultDto>.Ok(result);
    }

    /// <summary>
    /// 分页查询租户配额使用历史。
    /// </summary>
    /// <param name="tenantId">租户 ID。</param>
    /// <param name="query">查询条件。</param>
    /// <param name="cancellationToken">取消标记。</param>
    /// <returns>配额使用历史分页结果。</returns>
    [HttpGet("{tenantId:long}/quota-usage-history")]
    [PermissionAuthorize("tenant:quota:read")]
    [ProducesResponseType(typeof(ApiResponse<PagedResult<QuotaUsageHistoryDto>>), StatusCodes.Status200OK)]
    public async Task<ApiResponse<PagedResult<QuotaUsageHistoryDto>>> GetQuotaUsageHistory(
        long tenantId,
        [FromQuery] GetTenantQuotaUsageHistoryQuery query,
        CancellationToken cancellationToken)
    {
        // 1. 绑定租户标识
        query = query with { TenantId = tenantId };

        // 2. (空行后) 查询配额使用历史
        var result = await mediator.Send(query, cancellationToken);

        // 3. (空行后) 返回分页结果
        return ApiResponse<PagedResult<QuotaUsageHistoryDto>>.Ok(result);
    }
}
