using Books.Api.Invoicing.Services;
using GraphQL.Types;

namespace Books.Api.GraphQL.Types;

public class SuggestedPaymentMatchType : ObjectGraphType<SuggestedPaymentMatch>
{
    public SuggestedPaymentMatchType()
    {
        Name = "SuggestedPaymentMatch";
        Description = "A suggested match between a bank transaction and an invoice";

        Field(x => x.Id).Description("Unique identifier");
        Field(x => x.CompanyId).Description("Company ID");
        Field(x => x.BankTransactionId).Description("Bank transaction ID");
        Field(x => x.InvoiceId).Description("Invoice ID");

        // Bank transaction details
        Field(x => x.BankTransactionAmount).Description("Bank transaction amount");
        Field<DateOnlyGraphType>("bankTransactionDate")
            .Description("Bank transaction date")
            .Resolve(ctx => ctx.Source.BankTransactionDate);
        Field(x => x.BankTransactionDescription, nullable: true).Description("Bank transaction description");
        Field(x => x.BankTransactionCounterparty, nullable: true).Description("Bank transaction counterparty name");

        // Invoice details
        Field(x => x.InvoiceNumber).Description("Invoice number");
        Field(x => x.CustomerName).Description("Customer name");
        Field(x => x.InvoiceAmountRemaining).Description("Remaining amount on invoice");
        Field<DateOnlyGraphType>("invoiceDueDate")
            .Description("Invoice due date")
            .Resolve(ctx => ctx.Source.InvoiceDueDate);

        // Match scoring
        Field(x => x.Confidence).Description("Match confidence score (0.0 - 1.0)");
        Field(x => x.SuggestedAmount).Description("Suggested payment amount");
        Field<ListGraphType<MatchReasonType>>("matchReasons")
            .Description("Reasons for the suggested match")
            .Resolve(ctx => ctx.Source.MatchReasons);

        // Status
        Field(x => x.Status).Description("Match status: pending, accepted, rejected, expired");
        Field(x => x.CreatedAt).Description("When the suggestion was created");
    }
}

public class MatchReasonType : ObjectGraphType<MatchReason>
{
    public MatchReasonType()
    {
        Name = "MatchReason";
        Description = "A reason why a match was suggested";

        Field(x => x.Reason).Description("Reason code: exact_amount, close_amount, reference_match, name_match, recent_invoice");
        Field(x => x.Description).Description("Human-readable description (in Danish)");
        Field(x => x.Score).Description("Contribution to the confidence score");
    }
}

public class PaymentAllocationType : ObjectGraphType<PaymentAllocation>
{
    public PaymentAllocationType()
    {
        Name = "PaymentAllocation";
        Description = "A confirmed match between a bank transaction and an invoice";

        Field(x => x.Id).Description("Unique identifier");
        Field(x => x.CompanyId).Description("Company ID");
        Field(x => x.BankTransactionId).Description("Bank transaction ID");
        Field(x => x.InvoiceId, nullable: true).Description("Invoice ID");
        Field(x => x.CreditNoteId, nullable: true).Description("Credit note ID");
        Field(x => x.Amount).Description("Allocated amount");
        Field(x => x.AllocationType).Description("Type: payment, credit_note, refund");
        Field(x => x.MatchMethod).Description("How the match was made: manual, auto_amount, auto_reference, auto_name");
        Field(x => x.MatchConfidence, nullable: true).Description("Confidence score when match was made");
        Field(x => x.LedgerTransactionId, nullable: true).Description("Ledger transaction ID");
        Field(x => x.CreatedAt).Description("When the allocation was created");
        Field(x => x.CreatedBy).Description("User who created the allocation");
    }
}

public class PaymentAllocationResultType : ObjectGraphType<PaymentAllocationResult>
{
    public PaymentAllocationResultType()
    {
        Name = "PaymentAllocationResult";
        Description = "Result of confirming a payment match";

        Field(x => x.Success).Description("Whether the operation succeeded");
        Field<PaymentAllocationType>("allocation")
            .Description("The created allocation (if successful)")
            .Resolve(ctx => ctx.Source.Allocation);
        Field(x => x.ErrorCode, nullable: true).Description("Error code (if failed)");
        Field(x => x.ErrorMessage, nullable: true).Description("Error message (if failed)");
    }
}
