using e_suite.API.Common;
using e_suite.API.Common.models;
using e_suite.Database.Core.Tables.CustomFields;
using e_suite.Utilities.Pagination;
using eSuite.API.security;
using eSuite.API.Utilities;
using eSuite.Core.Miscellaneous;
using eSuite.Core.Security;
using Microsoft.AspNetCore.Mvc;

namespace eSuite.API.Controllers;

/// <summary>
/// Custom fields manager is responsible for managing Custom fields within e-suite.
/// </summary>
[Route("api/[controller]")]
[ApiController]
public class CustomFieldsController : ESuiteControllerBase
{
    private readonly ICustomFieldManager _customFieldManager;
    /// <summary>
    /// Constructor for the FieldController
    /// </summary>
    /// <param name="customFieldManager"></param>
    public CustomFieldsController(ICustomFieldManager customFieldManager)
    {
        _customFieldManager = customFieldManager;
    }

    /// <summary>
    /// Returns a list of all the fields in the system
    /// </summary>
    /// <remarks>This returns all the fields in the system that are not soft deleted.</remarks>
    [Route("fields")]
    [HttpGet]
    [AccessKey(SecurityAccess.ViewField)]
    [ProducesResponseType(StatusCodes.Status200OK)]
    public async Task<IActionResult> GetFields(
        [FromQuery] Paging paging,
        CancellationToken cancellationToken = default!
    )
    {
        var result = await _customFieldManager.GetFieldsAsync(paging, cancellationToken);
        return Ok(result);
    }

    /// <summary>
    /// Gets the custom field by and id 
    /// </summary>
    /// <param name="genralIdRef"></param>
    /// <param name="cancellationToken"></param>
    /// <returns></returns>
    [Route("field")]
    [HttpGet]
    [AccessKey(SecurityAccess.ViewField)]
    [ProducesResponseType(StatusCodes.Status200OK)]
    [ProducesResponseType(StatusCodes.Status404NotFound)]
    [ProducesResponseType(StatusCodes.Status400BadRequest)]
    public async Task<IActionResult> GetField(
        [FromQuery] GeneralIdRef genralIdRef,
        CancellationToken cancellationToken = default!
    )
    {
        var field = await _customFieldManager.GetFieldAsync(genralIdRef, cancellationToken);
        return Ok(field);
    }

    /// <summary>
    /// Create a custom field
    /// </summary>
    /// <param name="customField"></param>
    /// <param name="cancellationToken"></param>
    /// <returns></returns>
    [Route("field")]
    [HttpPost]
    [AccessKey(SecurityAccess.AddField)]
    [ProducesResponseType(StatusCodes.Status200OK)]
    [ProducesResponseType(StatusCodes.Status400BadRequest)]
    public async Task<IActionResult> CreateField(
        [FromBody] CreateCustomField customField,
        CancellationToken cancellationToken = default!
    )
    {
        await _customFieldManager.CreateFieldAsync(AuditUserDetails, customField, cancellationToken);
        return Ok();
    }

    /// <summary>
    /// Updates the values of a created Custom field
    /// </summary>
    /// <param name="customFields"></param>
    /// <param name="cancellationToken"></param>
    /// <returns></returns>
    [Route("field")]
    [HttpPut]
    [AccessKey(SecurityAccess.EditField)]
    [ProducesResponseType(StatusCodes.Status200OK)]
    [ProducesResponseType(StatusCodes.Status400BadRequest)]
    public async Task<IActionResult> EditField(
        [FromBody] EditCustomFields customFields,
        CancellationToken cancellationToken = default!
    )
    {
        await _customFieldManager.EditFieldAsync(AuditUserDetails, customFields, cancellationToken);
        return Ok();
    }

    /// <summary>
    /// Patching is useful when you only want to update a few fields of the user rather than the whole object.
    /// </summary>
    /// <param name="id"></param>
    /// <param name="customFields"></param>>
    /// <param name="cancellationToken"></param>
    /// <returns></returns>
    [Route("field")]
    [HttpPatch]
    [AccessKey(SecurityAccess.EditField)]
    [ProducesResponseType(StatusCodes.Status200OK)]
    [ProducesResponseType(StatusCodes.Status400BadRequest)]
    public async Task<IActionResult> PatchField(
        [FromQuery] IGeneralIdRef id,
        [FromBody] PatchCustomFields customFields,
        CancellationToken cancellationToken = default!
    )
    {
        await _customFieldManager.PatchFieldAsync(AuditUserDetails, id, customFields, cancellationToken);
        return Ok();
    }

    /// <summary>
    /// Delete a custom field by giving a Id
    /// </summary>
    /// <param name="id"></param>
    /// <param name="cancellationToken"></param>
    /// <returns></returns>
    [Route("field")]
    [HttpDelete]
    [AccessKey(SecurityAccess.DeleteField)]
    [ProducesResponseType(StatusCodes.Status200OK)]
    [ProducesResponseType(StatusCodes.Status404NotFound)]
    [ProducesResponseType(StatusCodes.Status400BadRequest)]
    public async Task<IActionResult> DeleteField(
        [FromBody] GeneralIdRef id,
        CancellationToken cancellationToken = default!
    )
    {
        await _customFieldManager.DeleteFieldAsync(AuditUserDetails, id, cancellationToken);
        return Ok();
    }
}
