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

export interface CreatePartnerIdentificationInput {
  partnerId: string;
  type: PartnerIdentificationType;
  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 value is non-empty
  if (!value || value.trim() === "") {
    return err(new InvalidValueError(String(value)));
  }

  // 3. 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}`));
  }

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

  // 5. 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,
    })
    .returningAll()
    .executeTakeFirstOrThrow();

  return ok({ identification });
}
