using IdokladSdk.Enums;
using IdokladSdk.Models.Attachment;
using IdokladSdk.Models.Webhook;
using Microsoft.AspNetCore.Mvc;
using Idoklad.Services;

namespace Idoklad.Controllers;

/// <summary>
/// Integration / utility agendas: webhooks, notifications, change log, registered sales,
/// unpaired documents, attachments and system code books. Requires iDoklad credentials.
/// </summary>
[ApiController]
[Produces("application/json")]
[Tags("Integration")]
public sealed class IntegrationController : ControllerBase
{
    private readonly IntegrationService _service;

    public IntegrationController(IntegrationService service) => _service = service;

    // ---- Webhooks ----

    /// <summary>List configured webhooks (paged).</summary>
    [HttpGet("webhooks")]
    public async Task<IActionResult> ListWebhooks(int page = 1, int pageSize = 20, CancellationToken ct = default)
        => Ok(await _service.ListWebhooksAsync(page, pageSize, ct));

    /// <summary>Get a webhook detail by id.</summary>
    [HttpGet("webhooks/{id:int}")]
    public async Task<IActionResult> WebhookDetail(int id, CancellationToken ct)
        => Ok(await _service.WebhookDetailAsync(id, ct));

    /// <summary>Create (register) a new webhook subscription.</summary>
    [HttpPost("webhooks")]
    public async Task<IActionResult> CreateWebhook([FromBody] AgendaWebhookSettingsPostModel model, CancellationToken ct)
        => Ok(await _service.CreateWebhookAsync(model, ct));

    /// <summary>Delete a webhook by id.</summary>
    [HttpDelete("webhooks/{id:int}")]
    public async Task<IActionResult> DeleteWebhook(int id, CancellationToken ct)
        => Ok(await _service.DeleteWebhookAsync(id, ct));

    // ---- Notifications ----

    /// <summary>List notifications (paged).</summary>
    [HttpGet("notifications")]
    public async Task<IActionResult> ListNotifications(int page = 1, int pageSize = 20, CancellationToken ct = default)
        => Ok(await _service.ListNotificationsAsync(page, pageSize, ct));

    /// <summary>Delete (dismiss) a notification by id.</summary>
    [HttpDelete("notifications/{id:int}")]
    public async Task<IActionResult> DeleteNotification(int id, CancellationToken ct)
        => Ok(await _service.DeleteNotificationAsync(id, ct));

    // ---- Change log ----

    /// <summary>List the agenda change log (paged).</summary>
    [HttpGet("logs")]
    public async Task<IActionResult> ListLog(int page = 1, int pageSize = 20, CancellationToken ct = default)
        => Ok(await _service.ListLogAsync(page, pageSize, ct));

    // ---- Registered sales (EET) ----

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

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

    // ---- Unpaired documents ----

    /// <summary>List unpaired documents for a movement type and pairing document type.</summary>
    [HttpGet("unpaired-documents/{movementType}/{pairingDocumentType}")]
    public async Task<IActionResult> ListUnpairedDocuments(
        MovementType movementType, PairingDocumentType pairingDocumentType, int page = 1, int pageSize = 20, CancellationToken ct = default)
        => Ok(await _service.ListUnpairedDocumentsAsync(movementType, pairingDocumentType, page, pageSize, ct));

    // ---- Attachments ----

    /// <summary>Get a single attachment by its id.</summary>
    [HttpGet("attachments/{attachmentId:int}")]
    public async Task<IActionResult> GetAttachment(int attachmentId, bool compressed = false, CancellationToken ct = default)
        => Ok(await _service.GetAttachmentAsync(attachmentId, compressed, ct));

    /// <summary>Get all attachments of a document.</summary>
    [HttpGet("attachments/document/{documentId:int}/{documentType}")]
    public async Task<IActionResult> GetDocumentAttachments(
        int documentId, AttachmentDocumentType documentType, bool compressed = false, CancellationToken ct = default)
        => Ok(await _service.GetDocumentAttachmentsAsync(documentId, documentType, compressed, ct));

    /// <summary>Upload an attachment for a document.</summary>
    [HttpPost("attachments")]
    public async Task<IActionResult> UploadAttachment([FromBody] AttachmentUploadModel model, CancellationToken ct)
        => Ok(await _service.UploadAttachmentAsync(model, ct));

    /// <summary>Delete a single attachment by its id.</summary>
    [HttpDelete("attachments/{attachmentId:int}")]
    public async Task<IActionResult> DeleteAttachment(int attachmentId, CancellationToken ct)
        => Ok(await _service.DeleteAttachmentAsync(attachmentId, ct));

    /// <summary>Delete all attachments of a document.</summary>
    [HttpDelete("attachments/document/{documentId:int}/{documentType}")]
    public async Task<IActionResult> DeleteDocumentAttachments(int documentId, AttachmentDocumentType documentType, CancellationToken ct)
        => Ok(await _service.DeleteDocumentAttachmentsAsync(documentId, documentType, ct));

    // ---- System code books ----

    /// <summary>Get the iDoklad system code books.</summary>
    [HttpGet("system/code-books")]
    public async Task<IActionResult> CodeBooks(CancellationToken ct)
        => Ok(await _service.CodeBooksAsync(ct));

    /// <summary>Get changes to the code books since the given timestamp.</summary>
    [HttpGet("system/code-books/changes")]
    public async Task<IActionResult> CodeBooksChanges([FromQuery] DateTime lastCheck, CancellationToken ct = default)
        => Ok(await _service.CodeBooksChangesAsync(lastCheck, ct));
}
