import {
  encodeJson,
  type PaymentTermScheduleLineInput,
  type SalesCreditNoteLineInput,
  type SalesInvoiceLineInput,
  type SalesOrderLineInput,
  type ShipmentLineInput,
} from "../lib/domain";
import type {
  Channel,
  Listing,
  SalesCreditNote,
  SalesCreditNoteLine,
  SalesInvoice,
  SalesInvoiceLine,
  SalesOrder,
  SalesOrderLine,
  SalesPaymentTerm,
  SalesPriceList,
  SalesPriceRule,
  Schema,
  Shipment,
  ShipmentLine,
  SyncJob,
  ChannelOrder,
} from "../lib/types";
import type { Company, Currency, Item, Partner, PartnerRole } from "./moduleMocks";

const createdAt = new Date("2024-01-01T00:00:00.000Z");

export const baseCompany = {
  id: "company-1",
  status: "ACTIVE",
  legalName: "Test Corp",
  baseCurrencyId: "currency-1",
  taxId: null,
  registrationNumber: null,
  street: "123 Main St",
  city: "New York",
  state: "NY",
  postalCode: "10001",
  country: "US",
  createdAt,
  updatedAt: null,
} as const satisfies Company;

export const baseCustomer = {
  id: "customer-1",
  companyId: baseCompany.id,
  name: "Customer One",
  status: "ACTIVE",
  type: "ORGANIZATION",
  preferredCurrencyId: null,
  createdAt,
  updatedAt: null,
} as const satisfies Partner;

export const inactiveCustomer = {
  ...baseCustomer,
  id: "customer-2",
  status: "INACTIVE",
} as const satisfies Partner;

export const baseCustomerRole = {
  id: "partner-role-1",
  partnerId: baseCustomer.id,
  role: "CUSTOMER",
  createdAt,
  updatedAt: null,
} as const satisfies PartnerRole;

export const baseSite = {
  id: "site-1",
  companyId: baseCompany.id,
  status: "ACTIVE",
};

export const otherCompanySite = {
  ...baseSite,
  id: "site-2",
  companyId: "company-2",
};

export const baseCurrency = {
  id: "currency-1",
  code: "USD",
  status: "ACTIVE",
  symbol: "$",
  name: "US Dollar",
  decimalPlaces: 2,
  isBaseCurrency: true,
  createdAt,
  updatedAt: null,
} as const satisfies Currency;

export const baseUnit = {
  id: "unit-1",
  categoryId: "uom-category-1",
  symbol: "EA",
  status: "ACTIVE" as const,
};

export const compatibleUnit = {
  ...baseUnit,
  id: "unit-2",
  symbol: "BOX",
};

export const baseItem = {
  id: "item-1",
  sku: "ITEM-001",
  name: "Base Item",
  barcode: null,
  unitId: baseUnit.id,
  status: "ACTIVE",
  companyId: baseCompany.id,
  createdAt,
  updatedAt: null,
} as const satisfies Item & { companyId: string };

export const inactiveItem = {
  ...baseItem,
  id: "item-2",
  status: "INACTIVE",
} as const satisfies Item & { companyId: string };

export const otherCompanyItem = {
  ...baseItem,
  id: "item-3",
  companyId: "company-2",
} as const satisfies Item & { companyId: string };

export const baseChannel = {
  id: "channel-1",
  companyId: baseCompany.id,
  type: "MARKETPLACE",
  name: "Marketplace",
  code: "MKT",
  status: "ACTIVE",
  settings: null,
  lastSyncAt: null,
  createdAt,
  updatedAt: null,
} as const satisfies Channel<Schema>;

export const draftChannel = {
  ...baseChannel,
  id: "channel-2",
  status: "DRAFT",
} as const satisfies Channel<Schema>;

export const inactiveChannel = {
  ...baseChannel,
  id: "channel-3",
  status: "INACTIVE",
} as const satisfies Channel<Schema>;

export const baseScheduleLines: PaymentTermScheduleLineInput[] = [{ kind: "NET_DAYS", days: 30 }];

export const installmentScheduleLines: PaymentTermScheduleLineInput[] = [
  { kind: "INSTALLMENT", days: 15, percentage: 50 },
  { kind: "INSTALLMENT", days: 30, percentage: 50 },
];

export const endOfMonthScheduleLines: PaymentTermScheduleLineInput[] = [
  { kind: "END_OF_MONTH", days: 0 },
];

export const basePaymentTerm = {
  id: "payment-term-1",
  companyId: baseCompany.id,
  name: "Net 30",
  code: "NET30",
  status: "ACTIVE",
  scheduleLines: encodeJson(baseScheduleLines),
  notes: null,
  createdAt,
  updatedAt: null,
} as const satisfies SalesPaymentTerm<Schema>;

export const draftPaymentTerm = {
  ...basePaymentTerm,
  id: "payment-term-2",
  status: "DRAFT",
} as const satisfies SalesPaymentTerm<Schema>;

export const inactivePaymentTerm = {
  ...basePaymentTerm,
  id: "payment-term-3",
  status: "INACTIVE",
} as const satisfies SalesPaymentTerm<Schema>;

export const basePriceList = {
  id: "price-list-1",
  companyId: baseCompany.id,
  customerId: baseCustomer.id,
  channelId: baseChannel.id,
  name: "Retail Price List",
  code: "PL-001",
  priority: 10,
  status: "ACTIVE",
  notes: null,
  createdAt,
  updatedAt: null,
} as const satisfies SalesPriceList<Schema>;

export const draftPriceList = {
  ...basePriceList,
  id: "price-list-2",
  status: "DRAFT",
} as const satisfies SalesPriceList<Schema>;

export const basePriceRule = {
  id: "price-rule-1",
  salesPriceListId: basePriceList.id,
  itemId: baseItem.id,
  customerId: baseCustomer.id,
  channelId: baseChannel.id,
  currencyId: baseCurrency.id,
  unitId: baseUnit.id,
  minimumQuantity: 0,
  unitPrice: 100,
  effectiveFrom: createdAt,
  effectiveTo: null,
  priority: 10,
  status: "ACTIVE",
  notes: null,
  createdAt,
  updatedAt: null,
} as const satisfies SalesPriceRule<Schema>;

export const draftPriceRule = {
  ...basePriceRule,
  id: "price-rule-2",
  status: "DRAFT",
} as const satisfies SalesPriceRule<Schema>;

export const baseListing = {
  id: "listing-1",
  companyId: baseCompany.id,
  channelId: baseChannel.id,
  itemId: baseItem.id,
  sku: "LIST-001",
  externalIdentifier: "AMZ-001",
  title: "Base Listing",
  status: "ACTIVE",
  requiresPriceSync: false,
  salesPriceListId: basePriceList.id,
  createdAt,
  updatedAt: null,
} as const satisfies Listing<Schema>;

export const draftListing = {
  ...baseListing,
  id: "listing-2",
  status: "DRAFT",
} as const satisfies Listing<Schema>;

export const pausedListing = {
  ...baseListing,
  id: "listing-3",
  status: "PAUSED",
} as const satisfies Listing<Schema>;

export const retiredListing = {
  ...baseListing,
  id: "listing-4",
  status: "RETIRED",
} as const satisfies Listing<Schema>;

export const baseOrderLineInput = {
  itemId: baseItem.id,
  quantity: 10,
  unitPrice: 100,
  currencyId: baseCurrency.id,
  unitId: baseUnit.id,
  matchedPriceRuleId: basePriceRule.id,
  billingPolicy: "ORDER",
  requestedShipDate: createdAt,
  requiresPhysicalFulfillment: true,
  priceSnapshot: { unitPrice: 100, ruleId: basePriceRule.id },
  shippedQuantity: 0,
  invoicedQuantity: 0,
} satisfies SalesOrderLineInput;

export const baseSalesOrder = {
  id: "sales-order-1",
  companyId: baseCompany.id,
  customerId: baseCustomer.id,
  channelId: baseChannel.id,
  paymentTermId: basePaymentTerm.id,
  status: "DRAFT",
  orderDate: createdAt,
  requestedShipDate: createdAt,
  shippingAddressSnapshot: encodeJson({ line1: "1 Main St" }),
  billingAddressSnapshot: encodeJson({ line1: "1 Main St" }),
  paymentTermSnapshot: encodeJson({
    id: basePaymentTerm.id,
    name: basePaymentTerm.name,
    lines: baseScheduleLines,
  }),
  rejectionReason: null,
  holdReason: null,
  closeReason: null,
  createdAt,
  updatedAt: null,
} as const satisfies SalesOrder<Schema>;

export const submittedSalesOrder = {
  ...baseSalesOrder,
  id: "sales-order-2",
  status: "SUBMITTED",
} as const satisfies SalesOrder<Schema>;

export const confirmedSalesOrder = {
  ...baseSalesOrder,
  id: "sales-order-3",
  status: "CONFIRMED",
} as const satisfies SalesOrder<Schema>;

export const heldSalesOrder = {
  ...baseSalesOrder,
  id: "sales-order-4",
  status: "CREDIT_HOLD",
  holdReason: "Credit review",
} as const satisfies SalesOrder<Schema>;

export const baseSalesOrderLine = {
  id: "sales-order-line-1",
  salesOrderId: baseSalesOrder.id,
  itemId: baseItem.id,
  description: "Line 1",
  quantity: 10,
  unitPrice: 100,
  currencyId: baseCurrency.id,
  unitId: baseUnit.id,
  matchedPriceRuleId: basePriceRule.id,
  billingPolicy: "ORDER",
  requestedShipDate: createdAt,
  requiresPhysicalFulfillment: true,
  priceSnapshot: encodeJson({ unitPrice: 100 }),
  shippedQuantity: 0,
  invoicedQuantity: 0,
  createdAt,
  updatedAt: null,
} as const satisfies SalesOrderLine<Schema>;

export const baseShipment = {
  id: "shipment-1",
  companyId: baseCompany.id,
  salesOrderId: confirmedSalesOrder.id,
  customerId: baseCustomer.id,
  shipFromSiteId: baseSite.id,
  shipmentDate: createdAt,
  status: "DRAFT",
  trackingNumber: null,
  shippingAddressSnapshot: encodeJson({ line1: "1 Main St" }),
  createdAt,
  updatedAt: null,
} as const satisfies Shipment<Schema>;

export const postedShipment = {
  ...baseShipment,
  id: "shipment-2",
  status: "POSTED",
} as const satisfies Shipment<Schema>;

export const baseShipmentLineInput = {
  salesOrderLineId: baseSalesOrderLine.id,
  quantity: 4,
  unitId: baseUnit.id,
} satisfies ShipmentLineInput;

export const baseShipmentLine = {
  id: "shipment-line-1",
  shipmentId: baseShipment.id,
  salesOrderLineId: baseSalesOrderLine.id,
  quantity: 4,
  unitId: baseUnit.id,
  trackingReference: null,
  createdAt,
  updatedAt: null,
} as const satisfies ShipmentLine<Schema>;

export const baseSalesInvoice = {
  id: "sales-invoice-1",
  companyId: baseCompany.id,
  customerId: baseCustomer.id,
  salesOrderId: confirmedSalesOrder.id,
  paymentTermId: basePaymentTerm.id,
  shipmentId: null,
  status: "DRAFT",
  invoiceNumber: null,
  invoiceDate: createdAt,
  billingPolicy: "ORDER",
  paymentTermSnapshot: encodeJson({
    id: basePaymentTerm.id,
    name: basePaymentTerm.name,
    lines: baseScheduleLines,
  }),
  dueSchedule: null,
  taxIdentitySnapshot: null,
  deliveryMetadata: null,
  arHandoffAccepted: false,
  notes: null,
  createdAt,
  updatedAt: null,
} as const satisfies SalesInvoice<Schema>;

export const issuedSalesInvoice = {
  ...baseSalesInvoice,
  id: "sales-invoice-2",
  status: "ISSUED",
  dueSchedule: encodeJson([{ dueDate: createdAt, amount: 1000 }]),
} as const satisfies SalesInvoice<Schema>;

export const sentSalesInvoice = {
  ...issuedSalesInvoice,
  id: "sales-invoice-3",
  status: "SENT",
  deliveryMetadata: encodeJson({ method: "EMAIL" }),
} as const satisfies SalesInvoice<Schema>;

export const baseInvoiceLineInput = {
  salesOrderLineId: baseSalesOrderLine.id,
  quantity: 5,
  unitPrice: 100,
  billingPolicy: "ORDER",
} satisfies SalesInvoiceLineInput;

export const baseSalesInvoiceLine = {
  id: "sales-invoice-line-1",
  salesInvoiceId: baseSalesInvoice.id,
  salesOrderLineId: baseSalesOrderLine.id,
  shipmentLineId: null,
  quantity: 5,
  unitPrice: 100,
  taxCode: null,
  taxableAmount: 500,
  taxAmount: 0,
  billingPolicy: "ORDER",
  orderPriceSnapshot: encodeJson({ unitPrice: 100 }),
  createdAt,
  updatedAt: null,
} as const satisfies SalesInvoiceLine<Schema>;

export const baseCreditNote = {
  id: "sales-credit-note-1",
  companyId: baseCompany.id,
  customerId: baseCustomer.id,
  salesInvoiceId: issuedSalesInvoice.id,
  status: "DRAFT",
  creditNoteNumber: null,
  creditDate: createdAt,
  reason: "Price correction",
  correctionSnapshot: null,
  createdAt,
  updatedAt: null,
} as const satisfies SalesCreditNote<Schema>;

export const issuedCreditNote = {
  ...baseCreditNote,
  id: "sales-credit-note-2",
  status: "ISSUED",
} as const satisfies SalesCreditNote<Schema>;

export const baseCreditNoteLineInput = {
  salesInvoiceLineId: baseSalesInvoiceLine.id,
  quantity: 1,
  amount: 100,
  reason: "Discount",
  taxAmount: 0,
} satisfies SalesCreditNoteLineInput;

export const baseCreditNoteLine = {
  id: "sales-credit-note-line-1",
  salesCreditNoteId: baseCreditNote.id,
  salesInvoiceLineId: baseSalesInvoiceLine.id,
  quantity: 1,
  amount: 100,
  reason: "Discount",
  taxAmount: 0,
  createdAt,
  updatedAt: null,
} as const satisfies SalesCreditNoteLine<Schema>;

export const baseSyncJob = {
  id: "sync-job-1",
  companyId: baseCompany.id,
  channelId: baseChannel.id,
  direction: "IMPORT",
  status: "RUNNING",
  startedAt: createdAt,
  finishedAt: null,
  processedCount: 0,
  successCount: 0,
  errorCount: 0,
  errorSummary: null,
  retryOfSyncJobId: null,
  context: encodeJson({ source: "api" }),
  createdAt,
  updatedAt: null,
} as const satisfies SyncJob<Schema>;

export const failedSyncJob = {
  ...baseSyncJob,
  id: "sync-job-2",
  status: "FAILED",
  finishedAt: createdAt,
  errorCount: 1,
  errorSummary: "Timeout",
} as const satisfies SyncJob<Schema>;

export const baseChannelOrder = {
  id: "channel-order-1",
  companyId: baseCompany.id,
  channelId: baseChannel.id,
  externalOrderId: "EXT-001",
  externalCustomerId: "buyer-1",
  customerId: baseCustomer.id,
  salesOrderId: null,
  status: "PENDING_CONVERSION",
  orderDate: createdAt,
  currencyId: baseCurrency.id,
  rawPayload: encodeJson({ orderId: "EXT-001" }),
  normalizedPayload: encodeJson({
    customerId: baseCustomer.id,
    lines: [
      {
        listingId: baseListing.id,
        itemId: baseItem.id,
        quantity: 1,
        unitPrice: 100,
        currencyId: baseCurrency.id,
        unitId: baseUnit.id,
      },
    ],
  }),
  errorSummary: null,
  retryContext: null,
  syncJobId: baseSyncJob.id,
  createdAt,
  updatedAt: null,
} as const satisfies ChannelOrder<Schema>;
