using Books.Api.EventFlow.ReadModels;
using GraphQL.Types;

namespace Books.Api.GraphQL.Types;

public class InvoiceGraphType : ObjectGraphType<InvoiceReadModelDto>
{
    public InvoiceGraphType()
    {
        Name = "Invoice";
        Description = "An invoice or credit note for a customer";

        Field(x => x.Id).Description("Unique identifier");
        Field(x => x.CompanyId).Description("Company this invoice belongs to");
        Field(x => x.FiscalYearId, nullable: true).Description("Fiscal year for this invoice");
        Field(x => x.CustomerId).Description("Customer ID");
        Field(x => x.CustomerName).Description("Customer name at time of invoice creation");
        Field(x => x.CustomerNumber).Description("Customer number");
        Field(x => x.InvoiceNumber).Description("Invoice/credit note number (Momsloven §52 compliant)");

        // Document type fields
        Field(x => x.InvoiceType).Description("Document type: invoice or credit_note");
        Field(x => x.IsCreditNote).Description("True if this is a credit note");
        Field(x => x.OriginalInvoiceId, nullable: true).Description("For credit notes: ID of the original invoice");
        Field(x => x.OriginalInvoiceNumber, nullable: true).Description("For credit notes: number of the original invoice");
        Field(x => x.CreditReason, nullable: true).Description("For credit notes: reason for issuing the credit");

        Field<DateOnlyGraphType>("invoiceDate")
            .Description("Invoice/credit note date")
            .Resolve(ctx => ctx.Source.InvoiceDate.HasValue
                ? DateOnly.FromDateTime(ctx.Source.InvoiceDate.Value)
                : null);
        Field<DateOnlyGraphType>("dueDate")
            .Description("Payment due date (not applicable to credit notes)")
            .Resolve(ctx => ctx.Source.DueDate.HasValue
                ? DateOnly.FromDateTime(ctx.Source.DueDate.Value)
                : null);
        Field(x => x.Status).Description("Status: draft, sent, issued, partially_paid, partially_applied, paid, fully_applied, voided");
        Field(x => x.AmountExVat).Description("Total amount excluding VAT (negative for credit notes)");
        Field(x => x.AmountVat).Description("Total VAT amount (negative for credit notes)");
        Field(x => x.AmountTotal).Description("Total amount including VAT (negative for credit notes)");
        Field(x => x.AmountPaid).Description("Amount paid so far (for invoices)");
        Field(x => x.AmountApplied).Description("Amount applied so far (for credit notes)");
        Field(x => x.AmountRemaining).Description("Remaining amount to pay/apply");
        Field(x => x.Currency).Description("Currency code (default: DKK)");
        Field(x => x.VatCode, nullable: true).Description("Default VAT code for this invoice");
        Field(x => x.PaymentTermsDays).Description("Payment terms in days");
        Field<ListGraphType<InvoiceLineGraphType>>("lines")
            .Description("Invoice lines")
            .Resolve(ctx => ctx.Source.GetLines());
        Field(x => x.LedgerTransactionId, nullable: true).Description("Ledger transaction ID when sent/issued");
        Field(x => x.Notes, nullable: true).Description("Internal notes");
        Field(x => x.Reference, nullable: true).Description("Customer reference");
        Field(x => x.SentAt, nullable: true).Description("When the invoice was sent");
        Field(x => x.IssuedAt, nullable: true).Description("When the credit note was issued");
        Field(x => x.PaidAt, nullable: true).Description("When the invoice was fully paid");
        Field(x => x.VoidedAt, nullable: true).Description("When the invoice was voided");
        Field(x => x.VoidedReason, nullable: true).Description("Reason for voiding");
        Field(x => x.VoidedBy, nullable: true).Description("User who voided the invoice");
        Field(x => x.CreatedBy).Description("User who created the invoice");
        Field(x => x.UpdatedBy, nullable: true).Description("User who last updated the invoice");
        Field(x => x.CreatedAt).Description("When the invoice was created");
        Field(x => x.UpdatedAt).Description("When the invoice was last updated");
    }
}

public class InvoiceLineGraphType : ObjectGraphType<InvoiceLineDto>
{
    public InvoiceLineGraphType()
    {
        Name = "InvoiceLine";
        Description = "A line on an invoice";

        Field(x => x.LineNumber).Description("Line number (1-based)");
        Field(x => x.Description).Description("Description of product/service");
        Field(x => x.Quantity).Description("Quantity");
        Field(x => x.Unit, nullable: true).Description("Unit of measurement");
        Field(x => x.UnitPrice).Description("Price per unit excluding VAT");
        Field(x => x.DiscountPercent).Description("Discount percentage (0-100)");
        Field(x => x.VatCode).Description("VAT code (e.g., U25, UEU, UEXP)");
        Field(x => x.AccountId, nullable: true).Description("Revenue account ID");
        Field(x => x.AmountExVat).Description("Line amount excluding VAT");
        Field(x => x.AmountVat).Description("Line VAT amount");
        Field(x => x.AmountTotal).Description("Line total including VAT");
    }
}

public class InvoiceStatusEnumType : EnumerationGraphType
{
    public InvoiceStatusEnumType()
    {
        Name = "InvoiceStatus";
        Description = "Status of an invoice or credit note";

        Add("DRAFT", "draft", "Invoice/credit note is being prepared");
        Add("SENT", "sent", "Invoice has been sent and posted to ledger");
        Add("ISSUED", "issued", "Credit note has been issued and posted to ledger");
        Add("PARTIALLY_PAID", "partially_paid", "Partial payment received (invoice)");
        Add("PARTIALLY_APPLIED", "partially_applied", "Partial credit applied (credit note)");
        Add("PAID", "paid", "Invoice is fully paid");
        Add("FULLY_APPLIED", "fully_applied", "Credit note is fully applied");
        Add("VOIDED", "voided", "Invoice/credit note has been cancelled");
    }
}

public class InvoiceTypeEnumType : EnumerationGraphType
{
    public InvoiceTypeEnumType()
    {
        Name = "InvoiceDocumentType";
        Description = "Type of invoice document";

        Add("INVOICE", "invoice", "Regular invoice with positive amounts");
        Add("CREDIT_NOTE", "credit_note", "Credit note with negative amounts");
    }
}
