import type { Transaction } from "../generated/kysely-tailordb";
import {
  PartnerNotFoundError,
  InvalidIdentificationTypeError,
  InvalidValueError,
  DuplicateIdentificationError,
  InvalidValidityPeriodError,
} from "../lib/errors.generated";
import { ok, err, type CommandContext } from "@tailor-platform/erp-kit/module";

const VALID_TYPES = ["TAX_ID", "VAT", "DUNS", "COMPANY_REGISTRY", "NATIONAL_ID", "OTHER"] as const;
type IdentificationType = (typeof VALID_TYPES)[number];

export interface CreatePartnerIdentificationInput {
  partnerId: string;
  type: IdentificationType;
  value: string;
  issuingCountry?: string;
  validFrom?: Date;
  validTo?: Date;
}

/**
 * Function: createPartnerIdentification
 *
 * Creates a new identification record for a business partner.
 * Validates partner existence, type enum, non-empty value,
 * (type, value) uniqueness within company scope, and validity period.
 */
export async function run<CF extends Record<string, unknown>>(
  db: Transaction,
  input: CreatePartnerIdentificationInput & CF,
  _ctx: CommandContext,
) {
  const { partnerId, type, value, issuingCountry, validFrom, validTo, ...customFields } = input;

  // 1. Check partner exists
  const partner = await db
    .selectFrom("BusinessPartner")
    .selectAll()
    .where("id", "=", partnerId)
    .executeTakeFirst();

  if (!partner) {
    return err(new PartnerNotFoundError(partnerId));
  }

  // 2. Validate type is valid enum value
  if (!VALID_TYPES.includes(type)) {
    return err(new InvalidIdentificationTypeError(type));
  }

  // 3. Validate value is non-empty
  if (!value || value.trim() === "") {
    return err(new InvalidValueError(value ?? ""));
  }

  // 4. Check (type, value) uniqueness within company scope
  const duplicate = await db
    .selectFrom("PartnerIdentification")
    .innerJoin("BusinessPartner", "BusinessPartner.id", "PartnerIdentification.partnerId")
    .selectAll("PartnerIdentification")
    .where("BusinessPartner.companyId", "=", partner.companyId)
    .where("PartnerIdentification.type", "=", type)
    .where("PartnerIdentification.value", "=", value)
    .executeTakeFirst();

  if (duplicate) {
    return err(new DuplicateIdentificationError(`${type}:${value}`));
  }

  // 5. Validate validity period
  if (validFrom && validTo && validTo < validFrom) {
    return err(
      new InvalidValidityPeriodError(`${validFrom.toISOString()} - ${validTo.toISOString()}`),
    );
  }

  // 6. Create identification record
  const identification = await db
    .insertInto("PartnerIdentification")
    .values({
      ...(customFields as Record<string, unknown>),
      partnerId,
      type,
      value,
      issuingCountry: issuingCountry ?? null,
      validFrom: validFrom ?? null,
      validTo: validTo ?? null,
      createdAt: new Date(),
      updatedAt: null,
    })
    .returningAll()
    .executeTakeFirst();

  return ok({ identification: identification! });
}
