using IWS5.Api.Enum;
using IWS5.Api.OptionsSetup;
using IWS5.Core.DTO;
using IWS5.Core.Models;
using IWS5.Core.Models.Request;
using IWS5.Core.Services;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Swashbuckle.AspNetCore.Annotations;

namespace IWS5.Api.Controllers;

/// <summary>
/// 
/// </summary>
/// <param name="documentTemplateService"></param>
/// <param name="logger"></param>
[Route("api/[controller]")]
[SwaggerTag("Controller for managing Document templates.")]
[ApiController]
[Authorize]
public class DocumentTemplateController(IDocumentTemplateService documentTemplateService, ILogger<DocumentTemplateController> logger) : ControllerBase
{
    /// <summary>
    /// Retrieves a list of document templates.
    /// </summary>
    /// <returns>A list of document templates.</returns>
    /// <response code="200">Returns the list of document templates.</response>
    /// <response code="500">If there is an internal server error.</response>
    [HttpGet("list")]
    [Authorize(Roles = nameof(UserGroups.PDAdminGroup))]
    [SwaggerOperation(Summary = "Retrieves a list of document templates.")]
    [ProducesResponseType(typeof(Response<IReadOnlyCollection<DocumentTemplateListItemResponseDTO>>), 200)]
    [ProducesResponseType(500)]
    public async Task<IActionResult> ListDocumentTemplates()
    {
        var userName = JwtTokenHelper.GetUserName(HttpContext, logger, out var actionResult);

        if (string.IsNullOrEmpty(userName))
        {
            return actionResult;
        }

        logger.LogInformation("Fetching documents for user {UserName}", userName);
        var result = await documentTemplateService.ListDocumentTemplates(new BaseRequest(userName));
        logger.LogInformation("Successfully fetched {Process} document templates for user {UserName}", result, userName);

        return Ok(result);
    }
    
    
    /// <summary>
    /// Retrieves a document template by its ID.
    /// </summary>
    /// <param name="templateId">The ID of the document template.</param>
    /// <returns>The document template data.</returns>
    /// <response code="200">Returns the document template data.</response>
    /// <response code="401">If the user is unauthorized.</response>
    /// <response code="404">If the document template is not found.</response>
    /// <response code="500">If there is an internal server error.</response>
    [HttpGet("{templateId:int}")]
    [Authorize(Roles = nameof(UserGroups.PDAdminGroup))]
    [SwaggerOperation(Summary = "Retrieves a document template by its ID.")]
    [ProducesResponseType(typeof(Response<DocumentTemplateResponseDTO>), 200)]
    [ProducesResponseType(401)]
    [ProducesResponseType(404)]
    [ProducesResponseType(500)]
    public async Task<IActionResult> GetTemplateFields([FromRoute] int templateId)
    {
        var userName = JwtTokenHelper.GetUserName(HttpContext, logger, out var actionResult);

        if (string.IsNullOrEmpty(userName))
        {
            return actionResult;
        }

        logger.LogInformation("Fetching documents for user {UserName}", userName);
        var result = await documentTemplateService.GetDocumentTemplateDataById(new GetDocumentTemplateRequest(userName, templateId));
        logger.LogInformation("Successfully fetched {Process} document templates for user {UserName}", result, userName);

        return Ok(result);
    }
    
    
    /// <summary>
    /// Retrieves the fields of a document template by its ID.
    /// </summary>
    /// <param name="templateId">The ID of the document template.</param>
    /// <returns>A response containing the document template fields.</returns>
    /// <response code="200">Returns the document template fields.</response>
    /// <response code="401">If the user is unauthorized.</response>
    /// <response code="404">If the document template is not found.</response>
    /// <response code="500">If there is an internal server error.</response>
    [HttpGet("{templateId:int}/fields")]
    [SwaggerOperation(Summary = "Retrieves the fields of a document template by its ID.")]
    [ProducesResponseType(typeof(Response<DocumentTemplateFieldListResponseDTO>), 200)]
    [ProducesResponseType(401)]
    [ProducesResponseType(404)]
    [ProducesResponseType(500)]
    public async Task<IActionResult> GetDocumentTemplateFieldsById([FromRoute] int templateId)
    {
        var userName = JwtTokenHelper.GetUserName(HttpContext, logger, out var actionResult);

        if (string.IsNullOrEmpty(userName))
        {
            return actionResult;
        }

        logger.LogInformation("Fetching documents for user {UserName}", userName);
        var result = await documentTemplateService.GetDocumentTemplateFieldsById(new GetDocumentTemplateRequest(userName, templateId));
        logger.LogInformation("Successfully fetched {Process} document templates for user {UserName}", result, userName);

        return Ok(result);
    }

    /// <summary>
    /// Retrieves a document template by its ID.
    /// </summary>
    /// <param name="processId">The ID of the process.</param>
    /// <param name="groupId">The ID of the group</param>
    /// <returns>The document template data.</returns>
    /// <response code="200">Returns the limit document template data.</response>
    /// <response code="401">If the user is unauthorized.</response>
    /// <response code="404">If the document template is not found.</response>
    /// <response code="500">If there is an internal server error.</response>
    [SwaggerOperation(Summary = "Retrieves a limit document templates and available buttons by processId and groupId.")]
    [HttpGet("limitTemplate")]
    [Authorize(Roles = nameof(UserGroups.PDAdminGroup))]
    [ProducesResponseType(typeof(Response<List<DocumentTemplateLitimResponseDTO>>), 200)]
    [ProducesResponseType(401)]
    [ProducesResponseType(404)]
    [ProducesResponseType(500)]
    public async Task<IActionResult> GetDocumentTemplateDataById([FromQuery] Guid processId, [FromQuery] Guid groupId)
    {
        var userName = JwtTokenHelper.GetUserName(HttpContext, logger, out var actionResult);

        if (string.IsNullOrEmpty(userName))
        {
            return actionResult;
        }

        logger.LogInformation("Fetching document templates for process {ProcessId} and {GroupId} for user {UserName}", processId, groupId, userName);
        var result = await documentTemplateService.GetLimitDocumentTemplatesDataById(new GetDocumentLimitTemplatesRequest(userName, processId, groupId));
        logger.LogInformation("Successfully fetched document templates for {processId} = {ProcessCount}", processId,  result);

        return Ok(result);
    }

    /// <summary>
    /// Creates a new document template.
    /// </summary>
    /// <param name="request">The request containing the details of the document template to create. 
    /// <see cref="CreateDocumentTemplateRequest"/>. Default value is null.</param>
    /// <returns>A <see cref="Task{IActionResult}"/> indicating the result of the create document template operation.</returns>
    /// <response code="200">If the document template was successfully created.</response>
    /// <response code="400">If the request is invalid.</response>
    /// <response code="401">If the user is unauthorized.</response>
    /// <response code="500">If there is an internal server error.</response>
    [HttpPost("create")]
    [Authorize(Roles = nameof(UserGroups.PDAdminGroup))]
    [SwaggerOperation(Summary = "Creates a new document template.")]
    [ProducesResponseType(200)]
    [ProducesResponseType(400)]
    [ProducesResponseType(401)]
    [ProducesResponseType(500)]
    public async Task<IActionResult> CreateDocumentTemplate([FromBody] CreateDocumentTemplateRequest request)
    {
        var userName = JwtTokenHelper.GetUserName(HttpContext, logger, out var actionResult);

        if (string.IsNullOrEmpty(userName))
        {
            return actionResult;
        }

        logger.LogInformation("Creating document template for user {UserName}", userName);
        await documentTemplateService.CreateDocumentTemplate(request);
        logger.LogInformation("Successfully created document template for user {UserName}", userName);

        return Ok();
    }

    /// <summary>
    /// Updates an existing document cabinet.
    /// </summary>
    /// <param name="request">The request containing the details of the document cabinet to update.</param>
    /// <returns>A <see cref="Task{IActionResult}"/> indicating the result of the update document template operation.</returns>
    /// <response code="200">If the document cabinet was successfully updated.</response>
    /// <response code="400">If the request is invalid.</response>
    /// <response code="500">If there is an internal server error.</response>
    [HttpPut("update-cabinet")]
    [Authorize(Roles = nameof(UserGroups.PDAdminGroup))]
    [SwaggerOperation(Summary = "Updates an existing document cabinet.")]
    [ProducesResponseType(200)]
    [ProducesResponseType(400)]
    [ProducesResponseType(500)]
    public async Task<IActionResult> UpdateDocumentCabinet([FromBody] UpdateDocumentTemplateRequest request)
    {
        var userName = JwtTokenHelper.GetUserName(HttpContext, logger, out var actionResult);

        if (string.IsNullOrEmpty(userName))
        {
            return actionResult;
        }

        logger.LogInformation("Updating document cabinet for user {UserName}", userName);

        try
        {
            await documentTemplateService.UpdateDocumentCabinet(request);
            logger.LogInformation("Successfully updated document cabinet for user {UserName}", userName);
            return Ok();
        }
        catch (Exception ex)
        {
            logger.LogError(ex, "Error updating document cabinet for user {UserName}", userName);
            return StatusCode(500, "Internal server error");
        }
    }
}
