using e_suite.API.Common;
using e_suite.API.Common.models;
using e_suite.Utilities.Pagination;
using eSuite.API.Models;
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>
/// This part of the API is responsible for allowing a user to interact with sequences.
/// </summary>
[Route("api/[controller]")]
[ApiController]
public class SequencesController : ESuiteControllerBase
{
    private readonly ISequenceManager _sequenceManager;

    /// <summary>
    /// 
    /// </summary>
    /// <param name="sequenceManager"></param>
    public SequencesController(ISequenceManager sequenceManager)
    {
        _sequenceManager = sequenceManager;
    }

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

    /// <summary>
    /// Returns the details of a specific sequence
    /// </summary>
    /// <remarks>This returns all the sequences in the system that are not soft deleted.</remarks>
    [Route("sequence")]
    [HttpGet]
    [AccessKey(SecurityAccess.ViewSequence)]
    [ProducesResponseType(StatusCodes.Status200OK)]
    [ProducesResponseType(StatusCodes.Status404NotFound)]
    public async Task<IActionResult> GetSequence(
        [FromQuery] long? id,
        [FromQuery] Guid? guid,
        CancellationToken cancellationToken = default!
    )
    {
        var generalIdRef = new GeneralIdRef
        {
            Id = id,
            Guid = guid
        };

        var result = await _sequenceManager.GetSequence(generalIdRef, cancellationToken);

        return Ok(result);
    }

    /// <summary>
    /// Create a sequence
    /// </summary>
    /// <param name="createSequence">Contains the data required to create a sequence</param>
    /// <param name="cancellationToken"></param>
    [Route("sequence")]
    [HttpPost]
    [AccessKey(SecurityAccess.AddSequence)]
    [ProducesResponseType(StatusCodes.Status200OK)]
    [ProducesResponseType(StatusCodes.Status400BadRequest)]
    public async Task<IActionResult> CreateSequence(
        [FromBody] NewSequence createSequence,
        CancellationToken cancellationToken = default!
    )
    {
        await _sequenceManager.CreateSequence(AuditUserDetails, createSequence, cancellationToken);
        return Ok();
    }

    /// <summary>
    /// Edit a sequence
    /// </summary>
    /// <remarks>All the fields can be edited except the Id and Guid field</remarks>
    /// <param name="editSequence">Contains the details of the updated sequence</param>
    /// <param name="cancellationToken"></param>
    [Route("sequence")]
    [HttpPut]
    [AccessKey(SecurityAccess.EditSequence)]
    [ProducesResponseType(StatusCodes.Status200OK)]
    [ProducesResponseType(StatusCodes.Status400BadRequest)]
    public async Task<IActionResult> EditSequence(
        [FromBody] Sequence editSequence,
        CancellationToken cancellationToken = default!
    )
    {
        await _sequenceManager.EditSequence(AuditUserDetails, editSequence, cancellationToken);
        return Ok();
    }

    /// <summary>
    /// Deletes a sequence
    /// </summary>
    /// <remarks>This will perform a soft delete action. The sequence is not actually deleted.</remarks>
    /// <param name="generalIdRef">Either the id or the Guid of the sequence</param>
    /// <param name="cancellationToken"></param>
    [Route("sequence")]
    [HttpDelete]
    [AccessKey(SecurityAccess.DeleteSequence)]
    [ProducesResponseType(StatusCodes.Status200OK)]
    [ProducesResponseType(StatusCodes.Status400BadRequest)]
    public async Task<IActionResult> DeleteSequence(
        GeneralIdRef generalIdRef,
        CancellationToken cancellationToken = default!
    )
    {
        await _sequenceManager.DeleteSequence(AuditUserDetails, generalIdRef, cancellationToken);
        return Ok();
    }

    /// <summary>
    /// Issues one or more sequence numbers
    /// </summary>
    /// <remarks>This will issue a sequence number acording to the pattern of the sequence.</remarks>
    /// <param name="sequenceIssueRequest">details of the sequence requested</param>
    /// <param name="cancellationToken"></param>
    [Route("nextValue")]
    [HttpPost]
    [AccessKey(SecurityAccess.Everyone)]
    [ProducesResponseType(StatusCodes.Status200OK)]
    [ProducesResponseType(StatusCodes.Status400BadRequest)]
    public async Task<IActionResult> NextValue(
        [FromBody] SequenceIssueRequest sequenceIssueRequest,
        CancellationToken cancellationToken = default!
    )
    {
        var values = await _sequenceManager.NextValue(AuditUserDetails, sequenceIssueRequest.GeneralIdRef,
            sequenceIssueRequest.Count, cancellationToken);
        return Ok(values);
    }
}

