import type { ReadonlyDB } from "@tailor-platform/erp-kit/core";
import type { DB } from "../generated/kysely-tailordb";
import {
  decodeJson,
  summarizeOrderProgress,
  type DueScheduleLine,
  type PaymentTermSnapshot,
} from "./domain";

export async function loadSalesOrderAggregate(db: ReadonlyDB<DB>, salesOrderId: string) {
  const salesOrder = await db
    .selectFrom("SalesOrder")
    .selectAll()
    .where("id", "=", salesOrderId)
    .executeTakeFirst();
  if (!salesOrder) return null;

  const lines = await db
    .selectFrom("SalesOrderLine")
    .selectAll()
    .where("salesOrderId", "=", salesOrderId)
    .execute();

  return {
    salesOrder: {
      ...salesOrder,
      paymentTermSnapshot: decodeJson<PaymentTermSnapshot | null>(
        salesOrder.paymentTermSnapshot,
        null,
      ),
      shippingAddressSnapshot: decodeJson<Record<string, unknown> | null>(
        salesOrder.shippingAddressSnapshot,
        null,
      ),
      billingAddressSnapshot: decodeJson<Record<string, unknown> | null>(
        salesOrder.billingAddressSnapshot,
        null,
      ),
    },
    lines: lines.map((line) => ({
      ...line,
      priceSnapshot: decodeJson<Record<string, unknown> | null>(line.priceSnapshot, null),
    })),
    fulfillmentTotals: summarizeOrderProgress(lines),
  };
}

export async function loadShipmentAggregate(db: ReadonlyDB<DB>, shipmentId: string) {
  const shipment = await db
    .selectFrom("Shipment")
    .selectAll()
    .where("id", "=", shipmentId)
    .executeTakeFirst();
  if (!shipment) return null;

  const lines = await db
    .selectFrom("ShipmentLine")
    .selectAll()
    .where("shipmentId", "=", shipmentId)
    .execute();

  return {
    shipment: {
      ...shipment,
      shippingAddressSnapshot: decodeJson<Record<string, unknown> | null>(
        shipment.shippingAddressSnapshot,
        null,
      ),
    },
    lines,
  };
}

export async function loadSalesInvoiceAggregate(db: ReadonlyDB<DB>, salesInvoiceId: string) {
  const salesInvoice = await db
    .selectFrom("SalesInvoice")
    .selectAll()
    .where("id", "=", salesInvoiceId)
    .executeTakeFirst();
  if (!salesInvoice) return null;

  const lines = await db
    .selectFrom("SalesInvoiceLine")
    .selectAll()
    .where("salesInvoiceId", "=", salesInvoiceId)
    .execute();

  return {
    salesInvoice: {
      ...salesInvoice,
      paymentTermSnapshot: decodeJson<PaymentTermSnapshot | null>(
        salesInvoice.paymentTermSnapshot,
        null,
      ),
      dueSchedule: decodeJson<DueScheduleLine[] | null>(salesInvoice.dueSchedule, null),
      taxIdentitySnapshot: decodeJson<Record<string, unknown> | null>(
        salesInvoice.taxIdentitySnapshot,
        null,
      ),
      deliveryMetadata: decodeJson<Record<string, unknown> | null>(
        salesInvoice.deliveryMetadata,
        null,
      ),
    },
    lines: lines.map((line) => ({
      ...line,
      orderPriceSnapshot: decodeJson<Record<string, unknown> | null>(line.orderPriceSnapshot, null),
    })),
  };
}

export async function loadSalesCreditNoteAggregate(db: ReadonlyDB<DB>, salesCreditNoteId: string) {
  const salesCreditNote = await db
    .selectFrom("SalesCreditNote")
    .selectAll()
    .where("id", "=", salesCreditNoteId)
    .executeTakeFirst();
  if (!salesCreditNote) return null;

  const lines = await db
    .selectFrom("SalesCreditNoteLine")
    .selectAll()
    .where("salesCreditNoteId", "=", salesCreditNoteId)
    .execute();

  return {
    salesCreditNote: {
      ...salesCreditNote,
      correctionSnapshot: decodeJson<Record<string, unknown> | null>(
        salesCreditNote.correctionSnapshot,
        null,
      ),
    },
    lines,
  };
}
