import type { Transaction } from "../generated/kysely-tailordb";
import {
  PartnerNotFoundError,
  PartnerNotOrganizationError,
  InvalidFirstNameError,
  InvalidLastNameError,
  MissingCommunicationChannelError,
  InvalidEmailFormatError,
} from "../lib/errors.generated";
import { ok, err } from "@tailor-platform/erp-kit/module";

export interface CreateContactPersonInput {
  partnerId: string;
  firstName: string;
  lastName: string;
  email?: string;
  phone?: string;
  jobTitle?: string;
  department?: string;
}

/**
 * Function: createContactPerson
 *
 * Creates a new contact person for an ORGANIZATION partner. Validates that
 * at least one communication channel (email or phone) is provided, and that
 * email format is valid if supplied. Created with status=ACTIVE, isPrimary=false.
 */
export async function run<CF extends Record<string, unknown>>(
  db: Transaction,
  input: CreateContactPersonInput & CF,
) {
  const { partnerId, firstName, lastName, email, phone, jobTitle, department, ...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. Check partner type is ORGANIZATION
  if (partner.type !== "ORGANIZATION") {
    return err(new PartnerNotOrganizationError(partnerId));
  }

  // 3. Validate firstName non-empty
  if (!firstName?.trim()) {
    return err(new InvalidFirstNameError(partnerId));
  }

  // 4. Validate lastName non-empty
  if (!lastName?.trim()) {
    return err(new InvalidLastNameError(partnerId));
  }

  // 5. At least one of email or phone required (whitespace-only values don't count)
  const trimmedEmail = email?.trim() ?? undefined;
  const trimmedPhone = phone?.trim() ?? undefined;
  if (!trimmedEmail && !trimmedPhone) {
    return err(new MissingCommunicationChannelError(partnerId));
  }

  // 6. Validate email format if provided
  if (trimmedEmail) {
    const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
    if (!emailRegex.test(trimmedEmail)) {
      return err(new InvalidEmailFormatError(trimmedEmail));
    }
  }

  // 7. Create contact person
  const contact = await db
    .insertInto("ContactPerson")
    .values({
      ...(customFields as Record<string, unknown>),
      partnerId,
      firstName,
      lastName,
      email: email ?? null,
      phone: phone ?? null,
      jobTitle: jobTitle ?? null,
      department: department ?? null,
      isPrimary: false,
      status: "ACTIVE",
      createdAt: new Date(),
      updatedAt: null,
    })
    .returningAll()
    .executeTakeFirst();

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