using IdokladSdk.Models.CreditNote;
using IdokladSdk.Models.IssuedDocumentTemplate.Patch;
using IdokladSdk.Models.IssuedDocumentTemplate.Post;
using IdokladSdk.Models.IssuedTaxDocument.Patch;
using IdokladSdk.Models.IssuedTaxDocument.Post;
using IdokladSdk.Models.ProformaInvoice;
using IdokladSdk.Models.RecurringInvoice;
using IdokladSdk.Models.SalesOrder;
using IdokladSdk.Models.SalesReceipt;
using Microsoft.AspNetCore.Mvc;
using Idoklad.Services;

namespace Idoklad.Controllers;

/// <summary>
/// Sales-side documents. Requires iDoklad credentials (headers or environment defaults).
/// </summary>
[ApiController]
[Produces("application/json")]
[Tags("SalesDocuments")]
public sealed class SalesDocumentsController : ControllerBase
{
    private readonly SalesDocumentsService _service;

    public SalesDocumentsController(SalesDocumentsService service) => _service = service;

    // ---- Proforma invoices ----

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

    /// <summary>Get a pre-filled default model for creating a new proforma invoice.</summary>
    [HttpGet("proforma-invoices/default")]
    public async Task<IActionResult> ProformaDefault(CancellationToken ct)
        => Ok(await _service.ProformaDefaultAsync(ct));

    /// <summary>Get a proforma invoice detail by id.</summary>
    [HttpGet("proforma-invoices/{id:int}")]
    public async Task<IActionResult> ProformaDetail(int id, CancellationToken ct)
        => Ok(await _service.ProformaDetailAsync(id, ct));

    /// <summary>Create a new proforma invoice.</summary>
    [HttpPost("proforma-invoices")]
    public async Task<IActionResult> CreateProforma([FromBody] ProformaInvoicePostModel model, CancellationToken ct)
        => Ok(await _service.CreateProformaAsync(model, ct));

    /// <summary>Update an existing proforma invoice (the model id identifies the document).</summary>
    [HttpPatch("proforma-invoices")]
    public async Task<IActionResult> UpdateProforma([FromBody] ProformaInvoicePatchModel model, CancellationToken ct)
        => Ok(await _service.UpdateProformaAsync(model, ct));

    /// <summary>Create a copy (draft) of an existing proforma invoice.</summary>
    [HttpPost("proforma-invoices/{id:int}/copy")]
    public async Task<IActionResult> CopyProforma(int id, CancellationToken ct)
        => Ok(await _service.ProformaCopyAsync(id, ct));

    /// <summary>Delete a proforma invoice by id.</summary>
    [HttpDelete("proforma-invoices/{id:int}")]
    public async Task<IActionResult> DeleteProforma(int id, CancellationToken ct)
        => Ok(await _service.DeleteProformaAsync(id, ct));

    // ---- Credit notes ----

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

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

    /// <summary>Get a credit note detail by id.</summary>
    [HttpGet("credit-notes/{id:int}")]
    public async Task<IActionResult> CreditNoteDetail(int id, CancellationToken ct)
        => Ok(await _service.CreditNoteDetailAsync(id, ct));

    /// <summary>Create a new credit note.</summary>
    [HttpPost("credit-notes")]
    public async Task<IActionResult> CreateCreditNote([FromBody] CreditNotePostModel model, CancellationToken ct)
        => Ok(await _service.CreateCreditNoteAsync(model, ct));

    /// <summary>Update an existing credit note (the model id identifies the document).</summary>
    [HttpPatch("credit-notes")]
    public async Task<IActionResult> UpdateCreditNote([FromBody] CreditNotePatchModel model, CancellationToken ct)
        => Ok(await _service.UpdateCreditNoteAsync(model, ct));

    /// <summary>Delete a credit note by id.</summary>
    [HttpDelete("credit-notes/{id:int}")]
    public async Task<IActionResult> DeleteCreditNote(int id, CancellationToken ct)
        => Ok(await _service.DeleteCreditNoteAsync(id, ct));

    // ---- Sales receipts ----

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

    /// <summary>Get a pre-filled default model for creating a new sales receipt.</summary>
    [HttpGet("sales-receipts/default")]
    public async Task<IActionResult> SalesReceiptDefault(CancellationToken ct)
        => Ok(await _service.SalesReceiptDefaultAsync(ct));

    /// <summary>Get a sales receipt detail by id.</summary>
    [HttpGet("sales-receipts/{id:int}")]
    public async Task<IActionResult> SalesReceiptDetail(int id, CancellationToken ct)
        => Ok(await _service.SalesReceiptDetailAsync(id, ct));

    /// <summary>Create a new sales receipt.</summary>
    [HttpPost("sales-receipts")]
    public async Task<IActionResult> CreateSalesReceipt([FromBody] SalesReceiptPostModel model, CancellationToken ct)
        => Ok(await _service.CreateSalesReceiptAsync(model, ct));

    /// <summary>Update an existing sales receipt (the model id identifies the document).</summary>
    [HttpPatch("sales-receipts")]
    public async Task<IActionResult> UpdateSalesReceipt([FromBody] SalesReceiptPatchModel model, CancellationToken ct)
        => Ok(await _service.UpdateSalesReceiptAsync(model, ct));

    /// <summary>Create a copy (draft) of an existing sales receipt.</summary>
    [HttpPost("sales-receipts/{id:int}/copy")]
    public async Task<IActionResult> CopySalesReceipt(int id, CancellationToken ct)
        => Ok(await _service.SalesReceiptCopyAsync(id, ct));

    /// <summary>Delete a sales receipt by id.</summary>
    [HttpDelete("sales-receipts/{id:int}")]
    public async Task<IActionResult> DeleteSalesReceipt(int id, CancellationToken ct)
        => Ok(await _service.DeleteSalesReceiptAsync(id, ct));

    // ---- Sales orders ----

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

    /// <summary>Get a pre-filled default model for creating a new sales order.</summary>
    [HttpGet("sales-orders/default")]
    public async Task<IActionResult> SalesOrderDefault(CancellationToken ct)
        => Ok(await _service.SalesOrderDefaultAsync(ct));

    /// <summary>Get a sales order detail by id.</summary>
    [HttpGet("sales-orders/{id:int}")]
    public async Task<IActionResult> SalesOrderDetail(int id, CancellationToken ct)
        => Ok(await _service.SalesOrderDetailAsync(id, ct));

    /// <summary>Create a new sales order.</summary>
    [HttpPost("sales-orders")]
    public async Task<IActionResult> CreateSalesOrder([FromBody] SalesOrderPostModel model, CancellationToken ct)
        => Ok(await _service.CreateSalesOrderAsync(model, ct));

    /// <summary>Update an existing sales order (the model id identifies the document).</summary>
    [HttpPatch("sales-orders")]
    public async Task<IActionResult> UpdateSalesOrder([FromBody] SalesOrderPatchModel model, CancellationToken ct)
        => Ok(await _service.UpdateSalesOrderAsync(model, ct));

    /// <summary>Create a copy (draft) of an existing sales order.</summary>
    [HttpPost("sales-orders/{id:int}/copy")]
    public async Task<IActionResult> CopySalesOrder(int id, CancellationToken ct)
        => Ok(await _service.SalesOrderCopyAsync(id, ct));

    /// <summary>Delete a sales order by id.</summary>
    [HttpDelete("sales-orders/{id:int}")]
    public async Task<IActionResult> DeleteSalesOrder(int id, CancellationToken ct)
        => Ok(await _service.DeleteSalesOrderAsync(id, ct));

    // ---- Recurring invoices ----

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

    /// <summary>Get a pre-filled default model for creating a new recurring invoice.</summary>
    [HttpGet("recurring-invoices/default")]
    public async Task<IActionResult> RecurringDefault(CancellationToken ct)
        => Ok(await _service.RecurringDefaultAsync(ct));

    /// <summary>Get a recurring invoice detail by id.</summary>
    [HttpGet("recurring-invoices/{id:int}")]
    public async Task<IActionResult> RecurringDetail(int id, CancellationToken ct)
        => Ok(await _service.RecurringDetailAsync(id, ct));

    /// <summary>Create a new recurring invoice template.</summary>
    [HttpPost("recurring-invoices")]
    public async Task<IActionResult> CreateRecurring([FromBody] RecurringInvoicePostModel model, CancellationToken ct)
        => Ok(await _service.CreateRecurringAsync(model, ct));

    /// <summary>Update an existing recurring invoice (the model id identifies the template).</summary>
    [HttpPatch("recurring-invoices")]
    public async Task<IActionResult> UpdateRecurring([FromBody] RecurringInvoicePatchModel model, CancellationToken ct)
        => Ok(await _service.UpdateRecurringAsync(model, ct));

    /// <summary>Create a copy (draft) of an existing recurring invoice.</summary>
    [HttpPost("recurring-invoices/{id:int}/copy")]
    public async Task<IActionResult> CopyRecurring(int id, CancellationToken ct)
        => Ok(await _service.RecurringCopyAsync(id, ct));

    /// <summary>Delete a recurring invoice by id.</summary>
    [HttpDelete("recurring-invoices/{id:int}")]
    public async Task<IActionResult> DeleteRecurring(int id, CancellationToken ct)
        => Ok(await _service.DeleteRecurringAsync(id, ct));

    // ---- Issued tax documents ----

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

    /// <summary>Get a pre-filled default tax document model for the given advance (proforma) invoice id.</summary>
    [HttpGet("issued-tax-documents/default/{advanceInvoiceId:int}")]
    public async Task<IActionResult> TaxDocumentDefault(int advanceInvoiceId, CancellationToken ct)
        => Ok(await _service.TaxDocumentDefaultAsync(advanceInvoiceId, ct));

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

    /// <summary>Create a new issued tax document.</summary>
    [HttpPost("issued-tax-documents")]
    public async Task<IActionResult> CreateTaxDocument([FromBody] IssuedTaxDocumentPostModel model, CancellationToken ct)
        => Ok(await _service.CreateTaxDocumentAsync(model, ct));

    /// <summary>Update an existing issued tax document (the model id identifies the document).</summary>
    [HttpPatch("issued-tax-documents")]
    public async Task<IActionResult> UpdateTaxDocument([FromBody] IssuedTaxDocumentPatchModel model, CancellationToken ct)
        => Ok(await _service.UpdateTaxDocumentAsync(model, ct));

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

    // ---- Issued document templates ----

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

    /// <summary>Get a pre-filled default model for creating a new issued document template.</summary>
    [HttpGet("issued-document-templates/default")]
    public async Task<IActionResult> TemplateDefault(CancellationToken ct)
        => Ok(await _service.TemplateDefaultAsync(ct));

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

    /// <summary>Create a new issued document template.</summary>
    [HttpPost("issued-document-templates")]
    public async Task<IActionResult> CreateTemplate([FromBody] IssuedDocumentTemplatePostModel model, CancellationToken ct)
        => Ok(await _service.CreateTemplateAsync(model, ct));

    /// <summary>Update an existing issued document template (the model id identifies the template).</summary>
    [HttpPatch("issued-document-templates")]
    public async Task<IActionResult> UpdateTemplate([FromBody] IssuedDocumentTemplatePatchModel model, CancellationToken ct)
        => Ok(await _service.UpdateTemplateAsync(model, ct));

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