using IdokladSdk.Models.BankStatement.Patch;
using IdokladSdk.Models.BankStatement.Post;
using IdokladSdk.Models.IssuedDocumentPayment;
using IdokladSdk.Models.ReceivedDocumentPayments;
using Microsoft.AspNetCore.Mvc;
using Idoklad.Services;

namespace Idoklad.Controllers;

/// <summary>
/// Bank statements and document payments. Requires iDoklad credentials (headers or environment defaults).
/// </summary>
[ApiController]
[Produces("application/json")]
[Tags("Payments")]
public sealed class PaymentsController : ControllerBase
{
    private readonly PaymentsService _service;

    public PaymentsController(PaymentsService service) => _service = service;

    // ---- Bank statements ----

    /// <summary>List bank statements (paged).</summary>
    [HttpGet("bank-statements")]
    public async Task<IActionResult> ListBankStatements(int page = 1, int pageSize = 20, CancellationToken ct = default)
        => Ok(await _service.ListBankStatementsAsync(page, pageSize, ct));

    /// <summary>Get a bank statement detail by id.</summary>
    [HttpGet("bank-statements/{id:int}")]
    public async Task<IActionResult> BankStatementDetail(int id, CancellationToken ct)
        => Ok(await _service.BankStatementDetailAsync(id, ct));

    /// <summary>Create a new bank statement.</summary>
    [HttpPost("bank-statements")]
    public async Task<IActionResult> CreateBankStatement([FromBody] BankStatementPostModel model, CancellationToken ct)
        => Ok(await _service.CreateBankStatementAsync(model, ct));

    /// <summary>Update an existing bank statement (the model id identifies the statement).</summary>
    [HttpPatch("bank-statements")]
    public async Task<IActionResult> UpdateBankStatement([FromBody] BankStatementPatchModel model, CancellationToken ct)
        => Ok(await _service.UpdateBankStatementAsync(model, ct));

    /// <summary>Delete a bank statement by id.</summary>
    [HttpDelete("bank-statements/{id:int}")]
    public async Task<IActionResult> DeleteBankStatement(int id, CancellationToken ct)
        => Ok(await _service.DeleteBankStatementAsync(id, ct));

    // ---- Issued document payments ----

    /// <summary>List issued document payments (paged).</summary>
    [HttpGet("issued-payments")]
    public async Task<IActionResult> ListIssuedPayments(int page = 1, int pageSize = 20, CancellationToken ct = default)
        => Ok(await _service.ListIssuedPaymentsAsync(page, pageSize, ct));

    /// <summary>Get a pre-filled default issued payment model for the given issued invoice id.</summary>
    [HttpGet("issued-payments/default/{invoiceId:int}")]
    public async Task<IActionResult> IssuedPaymentDefault(int invoiceId, CancellationToken ct)
        => Ok(await _service.IssuedPaymentDefaultAsync(invoiceId, ct));

    /// <summary>Get an issued document payment detail by id.</summary>
    [HttpGet("issued-payments/{id:int}")]
    public async Task<IActionResult> IssuedPaymentDetail(int id, CancellationToken ct)
        => Ok(await _service.IssuedPaymentDetailAsync(id, ct));

    /// <summary>Create (register) a new payment for an issued document.</summary>
    [HttpPost("issued-payments")]
    public async Task<IActionResult> CreateIssuedPayment([FromBody] IssuedDocumentPaymentPostModel model, CancellationToken ct)
        => Ok(await _service.CreateIssuedPaymentAsync(model, ct));

    /// <summary>Delete an issued document payment by id.</summary>
    [HttpDelete("issued-payments/{id:int}")]
    public async Task<IActionResult> DeleteIssuedPayment(int id, CancellationToken ct)
        => Ok(await _service.DeleteIssuedPaymentAsync(id, ct));

    /// <summary>Fully unpay an issued invoice (removes all its payments).</summary>
    [HttpPost("issued-payments/fully-unpay/{invoiceId:int}")]
    public async Task<IActionResult> FullyUnpayIssued(int invoiceId, CancellationToken ct)
        => Ok(await _service.FullyUnpayIssuedAsync(invoiceId, ct));

    // ---- Received document payments ----

    /// <summary>List received document payments (paged).</summary>
    [HttpGet("received-payments")]
    public async Task<IActionResult> ListReceivedPayments(int page = 1, int pageSize = 20, CancellationToken ct = default)
        => Ok(await _service.ListReceivedPaymentsAsync(page, pageSize, ct));

    /// <summary>Get a pre-filled default received payment model for the given received invoice id.</summary>
    [HttpGet("received-payments/default/{invoiceId:int}")]
    public async Task<IActionResult> ReceivedPaymentDefault(int invoiceId, CancellationToken ct)
        => Ok(await _service.ReceivedPaymentDefaultAsync(invoiceId, ct));

    /// <summary>Get a received document payment detail by id.</summary>
    [HttpGet("received-payments/{id:int}")]
    public async Task<IActionResult> ReceivedPaymentDetail(int id, CancellationToken ct)
        => Ok(await _service.ReceivedPaymentDetailAsync(id, ct));

    /// <summary>Create (register) a new payment for a received document.</summary>
    [HttpPost("received-payments")]
    public async Task<IActionResult> CreateReceivedPayment([FromBody] ReceivedDocumentPaymentPostModel model, CancellationToken ct)
        => Ok(await _service.CreateReceivedPaymentAsync(model, ct));

    /// <summary>Delete a received document payment by id.</summary>
    [HttpDelete("received-payments/{id:int}")]
    public async Task<IActionResult> DeleteReceivedPayment(int id, CancellationToken ct)
        => Ok(await _service.DeleteReceivedPaymentAsync(id, ct));

    /// <summary>Fully unpay a received invoice (removes all its payments).</summary>
    [HttpPost("received-payments/fully-unpay/{invoiceId:int}")]
    public async Task<IActionResult> FullyUnpayReceived(int invoiceId, CancellationToken ct)
        => Ok(await _service.FullyUnpayReceivedAsync(invoiceId, ct));
}
