import { ok, err, type CommandContext } from "@tailor-platform/erp-kit/core";
import type { Transaction } from "../generated/kysely-tailordb";
import { InvalidLegalNameError, CurrencyNotFoundError } from "../lib/errors.generated";
import type { PrimitivesQueries } from "../module";

export interface CreateCompanyInput {
  legalName: string;
  baseCurrencyId?: string;
  taxId?: string;
  registrationNumber?: string;
  street?: string;
  city?: string;
  state?: string;
  postalCode?: string;
  country?: string;
}

/**
 * Function: createCompany
 *
 * Establishes a new legal entity in the system in DRAFT status. Accepts the
 * company's legal name, and optionally tax identification, registration number,
 * base currency, and registered address fields.
 */
export async function run<CF extends Record<string, unknown>>(
  db: Transaction,
  input: CreateCompanyInput & CF,
  ctx: CommandContext,
  primitivesQueries?: Pick<PrimitivesQueries, "getCurrency">,
) {
  const {
    legalName,
    baseCurrencyId,
    taxId,
    registrationNumber,
    street,
    city,
    state,
    postalCode,
    country,
    ...customFields
  } = input;

  // 1. Validate legalName non-empty
  if (!legalName || legalName.trim() === "") {
    return err(new InvalidLegalNameError(String(legalName)));
  }

  // 2. If baseCurrencyId provided, validate currency exists and is active
  if (baseCurrencyId && primitivesQueries) {
    const { currency } = (await primitivesQueries.getCurrency(db, { id: baseCurrencyId }, ctx))
      .value;
    if (currency?.status !== "ACTIVE") {
      return err(new CurrencyNotFoundError(baseCurrencyId));
    }
  }

  // 3. Insert with status DRAFT
  const company = await db
    .insertInto("Company")
    .values({
      ...(customFields as Record<string, unknown>),
      legalName,
      baseCurrencyId: baseCurrencyId ?? null,
      taxId: taxId ?? null,
      registrationNumber: registrationNumber ?? null,
      street: street ?? null,
      city: city ?? null,
      state: state ?? null,
      postalCode: postalCode ?? null,
      country: country ?? null,
      status: "DRAFT",
    })
    .returningAll()
    .executeTakeFirstOrThrow();

  return ok({ company });
}
