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.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/{tenantId:long}/announcements")]
public sealed class TenantAnnouncementsController(IMediator mediator) : BaseApiController
{
    private const string TenantIdHeaderName = "X-Tenant-Id";

    /// <summary>
    /// 分页查询公告。
    /// </summary>
    /// <remarks>
    /// 示例：
    /// <code>
    /// GET /api/admin/v1/tenants/100000000000000001/announcements?page=1&amp;pageSize=20
    /// 响应:
    /// {
    ///   "success": true,
    ///   "code": 200,
    ///   "data": {
    ///     "items": [],
    ///     "page": 1,
    ///     "pageSize": 20,
    ///     "totalCount": 0
    ///   }
    /// }
    /// </code>
    /// </remarks>
    [HttpGet]
    [PermissionAuthorize("tenant-announcement:read")]
    [SwaggerOperation(Summary = "查询租户公告列表", Description = "需要权限：tenant-announcement:read")]
    [ProducesResponseType(typeof(ApiResponse<PagedResult<TenantAnnouncementDto>>), StatusCodes.Status200OK)]
    [ProducesResponseType(typeof(ApiResponse<object>), StatusCodes.Status403Forbidden)]
    public async Task<ApiResponse<PagedResult<TenantAnnouncementDto>>> Search(long tenantId, [FromQuery] GetTenantsAnnouncementsQuery query, CancellationToken cancellationToken)
    {
        var headerError = EnsureTenantHeader<PagedResult<TenantAnnouncementDto>>();
        if (headerError != null)
        {
            return headerError;
        }

        query = query with { TenantId = tenantId };
        var result = await mediator.Send(query, cancellationToken);
        return ApiResponse<PagedResult<TenantAnnouncementDto>>.Ok(result);
    }

    /// <summary>
    /// 公告详情。
    /// </summary>
    /// <remarks>
    /// 示例：
    /// <code>
    /// GET /api/admin/v1/tenants/100000000000000001/announcements/900123456789012345
    /// 响应:
    /// {
    ///   "success": true,
    ///   "code": 200,
    ///   "data": {
    ///     "id": "900123456789012345",
    ///     "tenantId": "100000000000000001",
    ///     "title": "租户公告",
    ///     "status": "Draft"
    ///   }
    /// }
    /// </code>
    /// </remarks>
    [HttpGet("{announcementId:long}")]
    [PermissionAuthorize("tenant-announcement:read")]
    [SwaggerOperation(Summary = "获取公告详情", Description = "需要权限：tenant-announcement:read")]
    [ProducesResponseType(typeof(ApiResponse<TenantAnnouncementDto>), StatusCodes.Status200OK)]
    [ProducesResponseType(typeof(ApiResponse<TenantAnnouncementDto>), StatusCodes.Status404NotFound)]
    [ProducesResponseType(typeof(ApiResponse<object>), StatusCodes.Status403Forbidden)]
    public async Task<ApiResponse<TenantAnnouncementDto>> Detail(long tenantId, long announcementId, CancellationToken cancellationToken)
    {
        var headerError = EnsureTenantHeader<TenantAnnouncementDto>();
        if (headerError != null)
        {
            return headerError;
        }

        var result = await mediator.Send(new GetAnnouncementByIdQuery { TenantId = tenantId, AnnouncementId = announcementId }, cancellationToken);
        return result is null
            ? ApiResponse<TenantAnnouncementDto>.Error(StatusCodes.Status404NotFound, "公告不存在")
            : ApiResponse<TenantAnnouncementDto>.Ok(result);
    }

    /// <summary>
    /// 创建公告。
    /// </summary>
    /// <remarks>
    /// 示例：
    /// <code>
    /// POST /api/admin/v1/tenants/100000000000000001/announcements
    /// Body:
    /// {
    ///   "title": "租户公告",
    ///   "content": "新品上线提醒",
    ///   "announcementType": 0,
    ///   "priority": 5,
    ///   "effectiveFrom": "2025-12-20T00:00:00Z",
    ///   "targetType": "roles",
    ///   "targetParameters": "{\"roles\":[\"OpsManager\"]}"
    /// }
    /// 响应:
    /// {
    ///   "success": true,
    ///   "code": 200,
    ///   "data": {
    ///     "id": "900123456789012345",
    ///     "tenantId": "100000000000000001",
    ///     "title": "租户公告",
    ///     "status": "Draft"
    ///   }
    /// }
    /// </code>
    /// </remarks>
    [HttpPost]
    [PermissionAuthorize("tenant-announcement:create")]
    [SwaggerOperation(Summary = "创建租户公告", Description = "需要权限：tenant-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(long tenantId, [FromBody, Required] CreateTenantAnnouncementCommand command, CancellationToken cancellationToken)
    {
        var headerError = EnsureTenantHeader<TenantAnnouncementDto>();
        if (headerError != null)
        {
            return headerError;
        }

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

    /// <summary>
    /// 更新公告（仅草稿）。
    /// </summary>
    /// <remarks>
    /// 示例：
    /// <code>
    /// PUT /api/admin/v1/tenants/100000000000000001/announcements/900123456789012345
    /// Body:
    /// {
    ///   "title": "租户公告（更新）",
    ///   "content": "公告内容更新",
    ///   "targetType": "all",
    ///   "targetParameters": null,
    ///   "rowVersion": "AAAAAAAAB9E="
    /// }
    /// 响应:
    /// {
    ///   "success": true,
    ///   "code": 200,
    ///   "data": {
    ///     "id": "900123456789012345",
    ///     "status": "Draft"
    ///   }
    /// }
    /// </code>
    /// </remarks>
    [HttpPut("{announcementId:long}")]
    [PermissionAuthorize("tenant-announcement:update")]
    [SwaggerOperation(Summary = "更新租户公告", Description = "仅草稿可更新；需要权限：tenant-announcement:update")]
    [ProducesResponseType(typeof(ApiResponse<TenantAnnouncementDto>), StatusCodes.Status200OK)]
    [ProducesResponseType(typeof(ApiResponse<TenantAnnouncementDto>), StatusCodes.Status404NotFound)]
    [ProducesResponseType(typeof(ApiResponse<object>), StatusCodes.Status409Conflict)]
    [ProducesResponseType(typeof(ApiResponse<object>), StatusCodes.Status403Forbidden)]
    public async Task<ApiResponse<TenantAnnouncementDto>> Update(long tenantId, long announcementId, [FromBody, Required] UpdateTenantAnnouncementCommand command, CancellationToken cancellationToken)
    {
        var headerError = EnsureTenantHeader<TenantAnnouncementDto>();
        if (headerError != null)
        {
            return headerError;
        }

        command = command with { TenantId = tenantId, 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/admin/v1/tenants/100000000000000001/announcements/900123456789012345/publish
    /// Body:
    /// {
    ///   "rowVersion": "AAAAAAAAB9E="
    /// }
    /// 响应:
    /// {
    ///   "success": true,
    ///   "code": 200,
    ///   "data": {
    ///     "id": "900123456789012345",
    ///     "status": "Published"
    ///   }
    /// }
    /// </code>
    /// </remarks>
    [HttpPost("{announcementId:long}/publish")]
    [PermissionAuthorize("tenant-announcement:publish")]
    [SwaggerOperation(Summary = "发布租户公告", Description = "需要权限：tenant-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 tenantId, long announcementId, [FromBody, Required] PublishAnnouncementCommand command, CancellationToken cancellationToken)
    {
        var headerError = EnsureTenantHeader<TenantAnnouncementDto>();
        if (headerError != null)
        {
            return headerError;
        }

        command = command with { 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/admin/v1/tenants/100000000000000001/announcements/900123456789012345/revoke
    /// Body:
    /// {
    ///   "rowVersion": "AAAAAAAAB9E="
    /// }
    /// 响应:
    /// {
    ///   "success": true,
    ///   "code": 200,
    ///   "data": {
    ///     "id": "900123456789012345",
    ///     "status": "Revoked"
    ///   }
    /// }
    /// </code>
    /// </remarks>
    [HttpPost("{announcementId:long}/revoke")]
    [PermissionAuthorize("tenant-announcement:revoke")]
    [SwaggerOperation(Summary = "撤销租户公告", Description = "需要权限：tenant-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 tenantId, long announcementId, [FromBody, Required] RevokeAnnouncementCommand command, CancellationToken cancellationToken)
    {
        var headerError = EnsureTenantHeader<TenantAnnouncementDto>();
        if (headerError != null)
        {
            return headerError;
        }

        command = command with { 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>
    /// DELETE /api/admin/v1/tenants/100000000000000001/announcements/900123456789012345
    /// 响应:
    /// {
    ///   "success": true,
    ///   "code": 200,
    ///   "data": true
    /// }
    /// </code>
    /// </remarks>
    [HttpDelete("{announcementId:long}")]
    [PermissionAuthorize("tenant-announcement:delete")]
    [SwaggerOperation(Summary = "删除租户公告", Description = "需要权限：tenant-announcement:delete")]
    [ProducesResponseType(typeof(ApiResponse<bool>), StatusCodes.Status200OK)]
    [ProducesResponseType(typeof(ApiResponse<object>), StatusCodes.Status403Forbidden)]
    public async Task<ApiResponse<bool>> Delete(long tenantId, long announcementId, CancellationToken cancellationToken)
    {
        var headerError = EnsureTenantHeader<bool>();
        if (headerError != null)
        {
            return headerError;
        }

        var result = await mediator.Send(new DeleteTenantAnnouncementCommand { TenantId = tenantId, AnnouncementId = announcementId }, cancellationToken);
        return ApiResponse<bool>.Ok(result);
    }

    /// <summary>
    /// 标记公告已读（兼容旧路径）。
    /// </summary>
    /// <remarks>
    /// 示例：
    /// <code>
    /// POST /api/admin/v1/tenants/100000000000000001/announcements/900123456789012345/read
    /// 响应:
    /// {
    ///   "success": true,
    ///   "code": 200,
    ///   "data": {
    ///     "id": "900123456789012345",
    ///     "isRead": true
    ///   }
    /// }
    /// </code>
    /// </remarks>
    [HttpPost("{announcementId:long}/read")]
    [PermissionAuthorize("tenant-announcement:read")]
    [SwaggerOperation(Summary = "标记公告已读", Description = "需要权限：tenant-announcement:read")]
    [ProducesResponseType(typeof(ApiResponse<TenantAnnouncementDto>), StatusCodes.Status200OK)]
    [ProducesResponseType(typeof(ApiResponse<TenantAnnouncementDto>), StatusCodes.Status404NotFound)]
    [ProducesResponseType(typeof(ApiResponse<object>), StatusCodes.Status403Forbidden)]
    public async Task<ApiResponse<TenantAnnouncementDto>> MarkRead(long tenantId, long announcementId, CancellationToken cancellationToken)
    {
        var headerError = EnsureTenantHeader<TenantAnnouncementDto>();
        if (headerError != null)
        {
            return headerError;
        }

        var result = await mediator.Send(new MarkAnnouncementAsReadCommand { TenantId = tenantId, AnnouncementId = announcementId }, cancellationToken);
        return result is null
            ? ApiResponse<TenantAnnouncementDto>.Error(StatusCodes.Status404NotFound, "公告不存在")
            : ApiResponse<TenantAnnouncementDto>.Ok(result);
    }

    private ApiResponse<T>? EnsureTenantHeader<T>()
    {
        if (!Request.Headers.TryGetValue(TenantIdHeaderName, out var tenantHeader) || string.IsNullOrWhiteSpace(tenantHeader))
        {
            return ApiResponse<T>.Error(StatusCodes.Status400BadRequest, $"缺少租户标识，请在请求头 {TenantIdHeaderName} 指定租户");
        }

        if (!long.TryParse(tenantHeader.FirstOrDefault(), out _))
        {
            return ApiResponse<T>.Error(StatusCodes.Status400BadRequest, $"租户标识无效，请在请求头 {TenantIdHeaderName} 指定正确的租户 ID");
        }

        return null;
    }
}
