import { domainFromInput } from "@/lib/domains/name";

// Shared by the browser form and the server actions — keep it free of server-only imports.

const DATE_PATTERN = /^(\d{4})-(\d{2})-(\d{2})$/;

export type ManualExpiryResult = { ok: true; date: Date | null } | { ok: false; error: string };

/**
 * A hand-entered expiry date ("YYYY-MM-DD", as <input type="date"> sends it);
 * empty clears it. Stored at 12:00 UTC so it renders as the same calendar day in
 * any display timezone from UTC−12 to UTC+11 (which covers Asia/Kolkata and UTC).
 */
export function parseManualExpiry(value: unknown): ManualExpiryResult {
  if (typeof value !== "string") return { ok: false, error: "Enter a date." };
  const trimmed = value.trim();
  if (trimmed === "") return { ok: true, date: null };

  const match = DATE_PATTERN.exec(trimmed);
  if (!match) return { ok: false, error: "Enter the date as YYYY-MM-DD." };
  const [year, month, day] = [Number(match[1]), Number(match[2]), Number(match[3])];
  const date = new Date(Date.UTC(year, month - 1, day, 12));
  if (date.getUTCFullYear() !== year || date.getUTCMonth() !== month - 1 || date.getUTCDate() !== day) {
    return { ok: false, error: "That date does not exist." };
  }
  if (year < 2000 || year > 2100) return { ok: false, error: "Enter a year between 2000 and 2100." };
  return { ok: true, date };
}

/** The <input type="date"> value for a stored manual date (kept at 12:00 UTC). */
export function manualExpiryInputValue(date: Date | null): string {
  return date ? date.toISOString().slice(0, 10) : "";
}

export const REGISTRAR_MAX_LENGTH = 150;

export type DomainFormValues = { name: string; registrar: string; manualExpiresOn: string };
export type DomainField = keyof DomainFormValues;
export type DomainFieldErrors = Partial<Record<DomainField, string>>;
export type DomainInput = { name: string; registrar: string | null; manualExpiresAt: Date | null };

export function domainFormValues(formData: FormData): DomainFormValues {
  const text = (name: string) => String(formData.get(name) ?? "");
  return { name: text("name"), registrar: text("registrar"), manualExpiresOn: text("manualExpiresOn") };
}

/**
 * Validates the Add / Edit Domain form. `requireName` is false on Edit, where the
 * name is fixed (a different domain is a different row).
 */
export function validateDomain(
  values: DomainFormValues,
  { requireName }: { requireName: boolean },
): { ok: true; data: DomainInput } | { ok: false; fieldErrors: DomainFieldErrors } {
  const fieldErrors: DomainFieldErrors = {};

  let name = "";
  if (requireName) {
    if (values.name.trim() === "") fieldErrors.name = "Domain is required";
    else {
      const domain = domainFromInput(values.name);
      if (!domain) fieldErrors.name = "Enter a domain name such as example.com";
      else name = domain;
    }
  }

  const registrar = values.registrar.trim();
  if (registrar.length > REGISTRAR_MAX_LENGTH) fieldErrors.registrar = `Registrar must be ${REGISTRAR_MAX_LENGTH} characters or fewer`;

  const expiry = parseManualExpiry(values.manualExpiresOn);
  if (!expiry.ok) fieldErrors.manualExpiresOn = expiry.error;

  if (Object.keys(fieldErrors).length > 0 || !expiry.ok) return { ok: false, fieldErrors };
  return { ok: true, data: { name, registrar: registrar === "" ? null : registrar, manualExpiresAt: expiry.date } };
}
