using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Tiku.Api.Contracts;
using Tiku.Application.Assets;
using Tiku.Application.PlatformAdmin;
using Tiku.Application.Security;

namespace Tiku.Api.Controllers;

[ApiController]
[Tags("平台端-公共题库")]
[Authorize(Policy = BackendPermissions.PlatformQuestionBankManage)]
[Produces("application/json")]
[Route("api/platform-admin/question-banks")]
public sealed class PlatformQuestionBanksController(
    IPlatformQuestionBankService service,
    ICurrentUser currentUser) : ControllerBase
{
    [HttpGet]
    [EndpointSummary("查询平台公共题库")]
    public async Task<ActionResult<IReadOnlyCollection<PlatformQuestionBankItem>>> GetBanks(
        [FromQuery] string? keyword,
        [FromQuery] string? status,
        CancellationToken cancellationToken)
    {
        return Ok(await service.GetBanksAsync(ResolveActor(), new PlatformQuestionBankFilter(Keyword: keyword, Status: status), cancellationToken));
    }

    [HttpPut]
    [EndpointSummary("新增或更新平台公共题库")]
    public async Task<ActionResult<PlatformQuestionBankItem>> UpsertBank(
        UpsertPlatformQuestionBankCommand request,
        CancellationToken cancellationToken)
    {
        return Ok(await service.UpsertBankAsync(ResolveActor(), request, cancellationToken));
    }

    [HttpPost("{bankId:guid}/archive")]
    [EndpointSummary("归档平台公共题库")]
    public async Task<ActionResult<PlatformQuestionBankItem>> ArchiveBank(Guid bankId, CancellationToken cancellationToken)
    {
        return Ok(await service.ArchiveBankAsync(ResolveActor(), bankId, cancellationToken));
    }

    [HttpGet("{bankId:guid}/nodes")]
    [EndpointSummary("查询公共题库内容结构")]
    public async Task<ActionResult<IReadOnlyCollection<PlatformQuestionBankNodeItem>>> GetNodes(Guid bankId, CancellationToken cancellationToken)
    {
        return Ok(await service.GetNodesAsync(ResolveActor(), bankId, cancellationToken));
    }

    [HttpPut("nodes")]
    [EndpointSummary("新增或更新公共题库内容节点")]
    public async Task<ActionResult<PlatformQuestionBankNodeItem>> UpsertNode(
        UpsertPlatformQuestionBankNodeCommand request,
        CancellationToken cancellationToken)
    {
        return Ok(await service.UpsertNodeAsync(ResolveActor(), request, cancellationToken));
    }

    [HttpPost("nodes/batch")]
    [EndpointSummary("批量创建公共题库章节或试卷")]
    public async Task<ActionResult<IReadOnlyCollection<PlatformQuestionBankNodeItem>>> BatchCreateNodes(
        BatchCreatePlatformQuestionBankNodesCommand request,
        CancellationToken cancellationToken)
    {
        return Ok(await service.BatchCreateNodesAsync(ResolveActor(), request, cancellationToken));
    }

    [HttpPost("nodes/{nodeId:guid}/archive")]
    [EndpointSummary("归档公共题库内容节点")]
    public async Task<ActionResult<PlatformQuestionBankNodeItem>> ArchiveNode(Guid nodeId, CancellationToken cancellationToken)
    {
        return Ok(await service.ArchiveNodeAsync(ResolveActor(), nodeId, cancellationToken));
    }

    [HttpGet("questions")]
    [EndpointSummary("分页查询公共题库题目")]
    public async Task<ActionResult<PlatformQuestionPage>> GetQuestions(
        [FromQuery] Guid questionBankId,
        [FromQuery] Guid? contentNodeId,
        [FromQuery] string? keyword,
        [FromQuery] string? type,
        [FromQuery] int? difficulty,
        [FromQuery] string? status,
        [FromQuery] int page = 1,
        [FromQuery] int pageSize = 20,
        CancellationToken cancellationToken = default)
    {
        return Ok(await service.GetQuestionsAsync(ResolveActor(), new PlatformQuestionBankFilter(
            questionBankId, contentNodeId, keyword, type, difficulty, status, page, pageSize), cancellationToken));
    }

    [HttpPut("questions")]
    [EndpointSummary("新增或更新公共题库题目并保留版本")]
    public async Task<ActionResult<PlatformQuestionItem>> UpsertQuestion(
        UpsertPlatformQuestionCommand request,
        CancellationToken cancellationToken)
    {
        return Ok(await service.UpsertQuestionAsync(ResolveActor(), request, cancellationToken));
    }

    [HttpPost("questions/archive")]
    [EndpointSummary("批量归档公共题库题目")]
    public async Task<ActionResult<int>> ArchiveQuestions(
        ArchivePlatformQuestionsCommand request,
        CancellationToken cancellationToken)
    {
        return Ok(await service.ArchiveQuestionsAsync(ResolveActor(), request, cancellationToken));
    }

    [HttpPost("imports/preview")]
    [EndpointSummary("预检公共题库 JSON 导入")]
    public async Task<ActionResult<PlatformQuestionImportResult>> PreviewImport(
        PlatformQuestionImportCommand request,
        CancellationToken cancellationToken)
    {
        return Ok(await service.PreviewImportAsync(ResolveActor(), request, cancellationToken));
    }

    [HttpPost("imports")]
    [EndpointSummary("执行公共题库 JSON 导入")]
    public async Task<ActionResult<PlatformQuestionImportResult>> ExecuteImport(
        PlatformQuestionImportCommand request,
        CancellationToken cancellationToken)
    {
        return Ok(await service.ExecuteImportAsync(ResolveActor(), request, cancellationToken));
    }

    [HttpGet("imports/{jobId:guid}")]
    [EndpointSummary("查询公共题库导入结果")]
    public async Task<ActionResult<ContentImportJobDetail>> GetImport(Guid jobId, CancellationToken cancellationToken)
    {
        return Ok(await service.GetImportAsync(ResolveActor(), jobId, cancellationToken));
    }

    [HttpPost("assets/upload-sign")]
    [EndpointSummary("签发公共题库图片上传地址")]
    public async Task<ActionResult<AssetUploadSignResult>> SignAssetUpload(
        AssetUploadSignDto request,
        CancellationToken cancellationToken)
    {
        return Ok(await service.SignQuestionAssetUploadAsync(ResolveActor(), request.ToCommand(), cancellationToken));
    }

    [HttpPost("assets/upload-confirm")]
    [EndpointSummary("确认公共题库图片上传结果")]
    public async Task<ActionResult<AssetUploadConfirmResult>> ConfirmAssetUpload(
        AssetUploadConfirmDto request,
        CancellationToken cancellationToken)
    {
        return Ok(await service.ConfirmQuestionAssetUploadAsync(ResolveActor(), request.ToCommand(), cancellationToken));
    }

    private PlatformAdminActor ResolveActor()
    {
        return currentUser.UserId is { } userId
            ? new PlatformAdminActor(userId)
            : throw new PlatformAdminException("无法识别当前平台员工。", "platform_access_denied");
    }
}
