using System.Text.Json.Serialization;

namespace Books.Api.AiBookkeeper;

/// <summary>
/// Client for the AI Bookkeeper service that analyzes documents
/// and suggests bookkeeping entries.
/// </summary>
public interface IAiBookkeeperClient
{
    /// <summary>
    /// Process a document (invoice, receipt, etc.) and get AI-suggested bookkeeping.
    /// </summary>
    /// <param name="document">The document file stream</param>
    /// <param name="fileName">Original filename</param>
    /// <param name="contentType">MIME type of the document</param>
    /// <param name="chartOfAccounts">Chart of accounts data</param>
    /// <param name="cancellationToken">Cancellation token</param>
    /// <returns>AI extraction and suggested bookkeeping</returns>
    Task<AiBookkeeperResponse> ProcessDocumentAsync(
        Stream document,
        string fileName,
        string contentType,
        ChartOfAccountsDto chartOfAccounts,
        CancellationToken cancellationToken = default);
}

/// <summary>
/// Response from AI Bookkeeper document processing.
/// </summary>
public class AiBookkeeperResponse
{
    /// <summary>
    /// Whether the document was successfully analyzed.
    /// </summary>
    public bool Success { get; set; }

    /// <summary>
    /// Error message if processing failed.
    /// </summary>
    public string? ErrorMessage { get; set; }

    /// <summary>
    /// Extracted document information.
    /// </summary>
    public DocumentExtraction? Extraction { get; set; }

    /// <summary>
    /// Suggested bookkeeping entry.
    /// </summary>
    public BookkeepingSuggestion? Suggestion { get; set; }
}

/// <summary>
/// Extracted information from the document.
/// </summary>
public class DocumentExtraction
{
    /// <summary>
    /// Detected document type (invoice, receipt, credit_note, etc.)
    /// </summary>
    [JsonPropertyName("documentType")]
    public string? DocumentType { get; set; }

    /// <summary>
    /// Vendor/supplier name.
    /// </summary>
    [JsonPropertyName("vendor")]
    public string? Vendor { get; set; }

    /// <summary>
    /// Vendor CVR number (Danish company registration).
    /// </summary>
    [JsonPropertyName("vendorCvr")]
    public string? VendorCvr { get; set; }

    /// <summary>
    /// Invoice/receipt number.
    /// </summary>
    [JsonPropertyName("invoiceNumber")]
    public string? InvoiceNumber { get; set; }

    /// <summary>
    /// Document date.
    /// </summary>
    [JsonPropertyName("date")]
    public DateOnly? Date { get; set; }

    /// <summary>
    /// Due date (for invoices).
    /// </summary>
    [JsonPropertyName("dueDate")]
    public DateOnly? DueDate { get; set; }

    /// <summary>
    /// Total amount including VAT.
    /// </summary>
    [JsonPropertyName("totalAmount")]
    public decimal? TotalAmount { get; set; }

    /// <summary>
    /// Amount excluding VAT.
    /// </summary>
    [JsonPropertyName("amountExVat")]
    public decimal? AmountExVat { get; set; }

    /// <summary>
    /// VAT amount.
    /// </summary>
    [JsonPropertyName("vatAmount")]
    public decimal? VatAmount { get; set; }

    /// <summary>
    /// Currency code (default DKK).
    /// </summary>
    [JsonPropertyName("currency")]
    public string Currency { get; set; } = "DKK";

    /// <summary>
    /// Extracted line items.
    /// </summary>
    [JsonPropertyName("lineItems")]
    public List<ExtractedLineItem> LineItems { get; set; } = [];

    /// <summary>
    /// Payment reference (FIK, girocard number, etc.)
    /// </summary>
    [JsonPropertyName("paymentReference")]
    public string? PaymentReference { get; set; }

    /// <summary>
    /// Raw text extracted from the document.
    /// </summary>
    [JsonPropertyName("rawText")]
    public string? RawText { get; set; }
}

/// <summary>
/// Extracted line item from invoice/receipt.
/// </summary>
public class ExtractedLineItem
{
    [JsonPropertyName("description")]
    public string? Description { get; set; }

    [JsonPropertyName("quantity")]
    public decimal? Quantity { get; set; }

    [JsonPropertyName("unitPrice")]
    public decimal? UnitPrice { get; set; }

    [JsonPropertyName("amount")]
    public decimal? Amount { get; set; }

    [JsonPropertyName("vatRate")]
    public decimal? VatRate { get; set; }
}

/// <summary>
/// AI-suggested bookkeeping entry.
/// </summary>
public class BookkeepingSuggestion
{
    /// <summary>
    /// Suggested description for the journal entry.
    /// </summary>
    public string? Description { get; set; }

    /// <summary>
    /// Suggested account lines.
    /// </summary>
    public List<SuggestedLine> Lines { get; set; } = [];

    /// <summary>
    /// Overall confidence in the suggestion (0.0 - 1.0).
    /// </summary>
    public decimal Confidence { get; set; }
}

/// <summary>
/// A suggested bookkeeping line with standard account number.
/// </summary>
public class SuggestedLine
{
    /// <summary>
    /// Standard account number from Erhvervsstyrelsen.
    /// </summary>
    public string? StandardAccountNumber { get; set; }

    /// <summary>
    /// Suggested account name/description.
    /// </summary>
    public string? AccountName { get; set; }

    /// <summary>
    /// Debit amount.
    /// </summary>
    public decimal DebitAmount { get; set; }

    /// <summary>
    /// Credit amount.
    /// </summary>
    public decimal CreditAmount { get; set; }

    /// <summary>
    /// VAT code (I25, U25, etc.)
    /// </summary>
    public string? VatCode { get; set; }

    /// <summary>
    /// Confidence in this specific line (0.0 - 1.0).
    /// </summary>
    public decimal Confidence { get; set; }
}

/// <summary>
/// AI service's single account suggestion.
/// The AI analyzes the document and suggests the most appropriate expense account.
/// </summary>
public class AiAccountSuggestion
{
    /// <summary>
    /// Company account number suggested by AI (e.g., "6080" for parking).
    /// </summary>
    public required string AccountNumber { get; init; }

    /// <summary>
    /// Account name (e.g., "Parkering (gulplade)").
    /// </summary>
    public required string AccountName { get; init; }

    /// <summary>
    /// VAT code for this account (e.g., "I25" for 25% input VAT).
    /// </summary>
    public string? VatCode { get; init; }

    /// <summary>
    /// Confidence in the suggestion (0.0 - 1.0).
    /// </summary>
    public decimal Confidence { get; init; }

    /// <summary>
    /// AI's reasoning for why this account was chosen.
    /// </summary>
    public string? Reasoning { get; init; }
}
