using MediatR;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Swashbuckle.AspNetCore.Annotations;
using System.ComponentModel.DataAnnotations;
using TakeoutSaaS.Application.App.Tenants.Commands;
using TakeoutSaaS.Application.App.Tenants.Dto;
using TakeoutSaaS.Application.App.Tenants.Queries;
using TakeoutSaaS.Domain.Tenants.Enums;
using TakeoutSaaS.Module.Authorization.Attributes;
using TakeoutSaaS.Shared.Abstractions.Results;
using TakeoutSaaS.Shared.Abstractions.Tenancy;
using TakeoutSaaS.Shared.Web.Api;

namespace TakeoutSaaS.AdminApi.Controllers;

/// <summary>
/// 平台公告管理。
/// </summary>
[ApiVersion("1.0")]
[Authorize]
[Route("api/platform/announcements")]
[Route("api/admin/v{version:apiVersion}/platform/announcements")]
public sealed class PlatformAnnouncementsController(IMediator mediator, ITenantContextAccessor tenantContextAccessor) : BaseApiController
{
    /// <summary>
    /// 创建平台公告。
    /// </summary>
    /// <remarks>
    /// 示例：
    /// <code>
    /// POST /api/platform/announcements
    /// Header: Authorization: Bearer &lt;JWT&gt;
    /// Body:
    /// {
    ///   "title": "平台升级通知",
    ///   "content": "系统将于今晚 23:00 维护。",
    ///   "announcementType": 0,
    ///   "priority": 10,
    ///   "effectiveFrom": "2025-12-20T00:00:00Z",
    ///   "effectiveTo": null,
    ///   "targetType": "all",
    ///   "targetParameters": null
    /// }
    /// 响应:
    /// {
    ///   "success": true,
    ///   "code": 200,
    ///   "data": {
    ///     "id": "900123456789012345",
    ///     "tenantId": "0",
    ///     "title": "平台升级通知",
    ///     "status": "Draft"
    ///   }
    /// }
    /// </code>
    /// </remarks>
    [HttpPost]
    [PermissionAuthorize("platform-announcement:create")]
    [SwaggerOperation(Summary = "创建平台公告", Description = "需要权限：platform-announcement:create")]
    [ProducesResponseType(typeof(ApiResponse<TenantAnnouncementDto>), StatusCodes.Status200OK)]
    [ProducesResponseType(typeof(ApiResponse<object>), StatusCodes.Status400BadRequest)]
    [ProducesResponseType(typeof(ApiResponse<object>), StatusCodes.Status403Forbidden)]
    public async Task<ApiResponse<TenantAnnouncementDto>> Create([FromBody, Required] CreateTenantAnnouncementCommand command, CancellationToken cancellationToken)
    {
        command = command with
        {
            TenantId = 0,
            PublisherScope = PublisherScope.Platform
        };

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

    /// <summary>
    /// 查询平台公告列表。
    /// </summary>
    /// <remarks>
    /// 示例：
    /// <code>
    /// GET /api/platform/announcements?page=1&amp;pageSize=20&amp;status=Published
    /// 响应:
    /// {
    ///   "success": true,
    ///   "code": 200,
    ///   "data": {
    ///     "items": [],
    ///     "page": 1,
    ///     "pageSize": 20,
    ///     "totalCount": 0
    ///   }
    /// }
    /// </code>
    /// </remarks>
    [HttpGet]
    [PermissionAuthorize("platform-announcement:create")]
    [SwaggerOperation(Summary = "查询平台公告列表", Description = "需要权限：platform-announcement:create")]
    [ProducesResponseType(typeof(ApiResponse<PagedResult<TenantAnnouncementDto>>), StatusCodes.Status200OK)]
    [ProducesResponseType(typeof(ApiResponse<object>), StatusCodes.Status403Forbidden)]
    public async Task<ApiResponse<PagedResult<TenantAnnouncementDto>>> List([FromQuery] GetTenantsAnnouncementsQuery query, CancellationToken cancellationToken)
    {
        var request = query with { TenantId = 0 };
        var result = await ExecuteAsPlatformAsync(() => mediator.Send(request, cancellationToken));
        return ApiResponse<PagedResult<TenantAnnouncementDto>>.Ok(result);
    }

    /// <summary>
    /// 获取平台公告详情。
    /// </summary>
    /// <remarks>
    /// 示例：
    /// <code>
    /// GET /api/platform/announcements/900123456789012345
    /// 响应:
    /// {
    ///   "success": true,
    ///   "code": 200,
    ///   "data": {
    ///     "id": "900123456789012345",
    ///     "tenantId": "0",
    ///     "title": "平台升级通知",
    ///     "status": "Draft"
    ///   }
    /// }
    /// </code>
    /// </remarks>
    [HttpGet("{announcementId:long}")]
    [PermissionAuthorize("platform-announcement:create")]
    [SwaggerOperation(Summary = "获取平台公告详情", Description = "需要权限：platform-announcement:create")]
    [ProducesResponseType(typeof(ApiResponse<TenantAnnouncementDto>), StatusCodes.Status200OK)]
    [ProducesResponseType(typeof(ApiResponse<object>), StatusCodes.Status404NotFound)]
    [ProducesResponseType(typeof(ApiResponse<object>), StatusCodes.Status403Forbidden)]
    public async Task<ApiResponse<TenantAnnouncementDto>> Detail(long announcementId, CancellationToken cancellationToken)
    {
        var result = await ExecuteAsPlatformAsync(() =>
            mediator.Send(new GetAnnouncementByIdQuery { TenantId = 0, AnnouncementId = announcementId }, cancellationToken));

        return result is null
            ? ApiResponse<TenantAnnouncementDto>.Error(StatusCodes.Status404NotFound, "公告不存在")
            : ApiResponse<TenantAnnouncementDto>.Ok(result);
    }

    /// <summary>
    /// 更新平台公告（仅草稿）。
    /// </summary>
    /// <remarks>
    /// 示例：
    /// <code>
    /// PUT /api/platform/announcements/900123456789012345
    /// Body:
    /// {
    ///   "title": "平台升级通知（更新）",
    ///   "content": "维护时间调整为 23:30。",
    ///   "targetType": "all",
    ///   "targetParameters": null,
    ///   "rowVersion": "AAAAAAAAB9E="
    /// }
    /// 响应:
    /// {
    ///   "success": true,
    ///   "code": 200,
    ///   "data": {
    ///     "id": "900123456789012345",
    ///     "status": "Draft"
    ///   }
    /// }
    /// </code>
    /// </remarks>
    [HttpPut("{announcementId:long}")]
    [PermissionAuthorize("platform-announcement:create")]
    [SwaggerOperation(Summary = "更新平台公告", Description = "仅草稿可更新；需要权限：platform-announcement:create")]
    [ProducesResponseType(typeof(ApiResponse<TenantAnnouncementDto>), StatusCodes.Status200OK)]
    [ProducesResponseType(typeof(ApiResponse<object>), StatusCodes.Status404NotFound)]
    [ProducesResponseType(typeof(ApiResponse<object>), StatusCodes.Status409Conflict)]
    [ProducesResponseType(typeof(ApiResponse<object>), StatusCodes.Status403Forbidden)]
    public async Task<ApiResponse<TenantAnnouncementDto>> Update(long announcementId, [FromBody, Required] UpdateTenantAnnouncementCommand command, CancellationToken cancellationToken)
    {
        command = command with { TenantId = 0, AnnouncementId = announcementId };
        var result = await mediator.Send(command, cancellationToken);

        return result is null
            ? ApiResponse<TenantAnnouncementDto>.Error(StatusCodes.Status404NotFound, "公告不存在")
            : ApiResponse<TenantAnnouncementDto>.Ok(result);
    }

    /// <summary>
    /// 发布平台公告。
    /// </summary>
    /// <remarks>
    /// 示例：
    /// <code>
    /// POST /api/platform/announcements/900123456789012345/publish
    /// Body:
    /// {
    ///   "rowVersion": "AAAAAAAAB9E="
    /// }
    /// 响应:
    /// {
    ///   "success": true,
    ///   "code": 200,
    ///   "data": {
    ///     "id": "900123456789012345",
    ///     "status": "Published"
    ///   }
    /// }
    /// </code>
    /// </remarks>
    [HttpPost("{announcementId:long}/publish")]
    [PermissionAuthorize("platform-announcement:publish")]
    [SwaggerOperation(Summary = "发布平台公告", Description = "需要权限：platform-announcement:publish")]
    [ProducesResponseType(typeof(ApiResponse<TenantAnnouncementDto>), StatusCodes.Status200OK)]
    [ProducesResponseType(typeof(ApiResponse<object>), StatusCodes.Status404NotFound)]
    [ProducesResponseType(typeof(ApiResponse<object>), StatusCodes.Status409Conflict)]
    [ProducesResponseType(typeof(ApiResponse<object>), StatusCodes.Status403Forbidden)]
    public async Task<ApiResponse<TenantAnnouncementDto>> Publish(long announcementId, [FromBody, Required] PublishAnnouncementCommand command, CancellationToken cancellationToken)
    {
        command = command with { AnnouncementId = announcementId };
        var result = await ExecuteAsPlatformAsync(() => mediator.Send(command, cancellationToken));

        return result is null
            ? ApiResponse<TenantAnnouncementDto>.Error(StatusCodes.Status404NotFound, "公告不存在")
            : ApiResponse<TenantAnnouncementDto>.Ok(result);
    }

    /// <summary>
    /// 撤销平台公告。
    /// </summary>
    /// <remarks>
    /// 示例：
    /// <code>
    /// POST /api/platform/announcements/900123456789012345/revoke
    /// Body:
    /// {
    ///   "rowVersion": "AAAAAAAAB9E="
    /// }
    /// 响应:
    /// {
    ///   "success": true,
    ///   "code": 200,
    ///   "data": {
    ///     "id": "900123456789012345",
    ///     "status": "Revoked"
    ///   }
    /// }
    /// </code>
    /// </remarks>
    [HttpPost("{announcementId:long}/revoke")]
    [PermissionAuthorize("platform-announcement:revoke")]
    [SwaggerOperation(Summary = "撤销平台公告", Description = "需要权限：platform-announcement:revoke")]
    [ProducesResponseType(typeof(ApiResponse<TenantAnnouncementDto>), StatusCodes.Status200OK)]
    [ProducesResponseType(typeof(ApiResponse<object>), StatusCodes.Status404NotFound)]
    [ProducesResponseType(typeof(ApiResponse<object>), StatusCodes.Status409Conflict)]
    [ProducesResponseType(typeof(ApiResponse<object>), StatusCodes.Status403Forbidden)]
    public async Task<ApiResponse<TenantAnnouncementDto>> Revoke(long announcementId, [FromBody, Required] RevokeAnnouncementCommand command, CancellationToken cancellationToken)
    {
        command = command with { AnnouncementId = announcementId };
        var result = await ExecuteAsPlatformAsync(() => mediator.Send(command, cancellationToken));

        return result is null
            ? ApiResponse<TenantAnnouncementDto>.Error(StatusCodes.Status404NotFound, "公告不存在")
            : ApiResponse<TenantAnnouncementDto>.Ok(result);
    }

    private async Task<T> ExecuteAsPlatformAsync<T>(Func<Task<T>> action)
    {
        var original = tenantContextAccessor.Current;
        tenantContextAccessor.Current = new TenantContext(0, null, "platform");
        try
        {
            return await action();
        }
        finally
        {
            tenantContextAccessor.Current = original;
        }
    }
}
