import type { DiscountType, Job, JobQuestion, JobType, Offer, PayPer } from "@/lib/types";

/**
 * The bits of Jobs and Offers that both the routes and the forms need.
 *
 * Kept in one place because the alternative — a list of job types written
 * out in the API route, and again in the create form, and again in the
 * filter bar — is three lists that drift until one of them rejects what
 * another one offers.
 */

export const JOB_TYPES: { value: JobType; label: string }[] = [
  { value: "full_time", label: "Full time" },
  { value: "part_time", label: "Part time" },
  { value: "contract", label: "Contract" },
  { value: "internship", label: "Internship" },
  { value: "volunteer", label: "Volunteer" },
];

export const PAY_PER: { value: PayPer; label: string; short: string }[] = [
  { value: "per_hour", label: "Per hour", short: "hr" },
  { value: "per_day", label: "Per day", short: "day" },
  { value: "per_week", label: "Per week", short: "wk" },
  { value: "per_month", label: "Per month", short: "mo" },
  { value: "per_year", label: "Per year", short: "yr" },
];

export const DISCOUNT_TYPES: { value: DiscountType; label: string }[] = [
  { value: "percent", label: "Percent off" },
  { value: "amount", label: "Money off" },
  { value: "buy_x_get_y", label: "Buy X get Y free" },
  { value: "spend_x_get_y", label: "Spend X get Y off" },
];

export const isJobType = (v: unknown): v is JobType =>
  JOB_TYPES.some((t) => t.value === v);
export const isPayPer = (v: unknown): v is PayPer =>
  PAY_PER.some((p) => p.value === v);
export const isDiscountType = (v: unknown): v is DiscountType =>
  DISCOUNT_TYPES.some((d) => d.value === v);

/** How a job's pay reads on a card: "£18–22 an hour", or nothing at all. */
export function salaryLine(job: Job, money: (n: number) => string): string {
  const { salaryMin: min, salaryMax: max } = job;
  if (!min && !max) return "";
  const per = PAY_PER.find((p) => p.value === job.payPer);
  const suffix = per ? " an " + per.short.replace("hr", "hour").replace("wk", "week")
    .replace("mo", "month").replace("yr", "year") : "";
  if (min && max && min !== max) return `${money(min)}–${money(max)}${suffix}`;
  return money((min || max) as number) + suffix;
}

/** What an offer actually gives you, in words. */
export function discountLine(offer: Offer, money: (n: number) => string): string {
  switch (offer.discountType) {
    case "percent":
      return offer.discountPercent ? `${offer.discountPercent}% off` : "Discount";
    case "amount":
      return offer.discountAmount ? `${money(offer.discountAmount)} off` : "Discount";
    case "buy_x_get_y":
      return offer.buyX && offer.getY
        ? `Buy ${offer.buyX}, get ${offer.getY} free`
        : "Buy one get one";
    case "spend_x_get_y":
      return offer.spendX && offer.amountY
        ? `Spend ${money(offer.spendX)}, get ${money(offer.amountY)} off`
        : "Spend and save";
  }
}

/** An offer past its end date is shown, greyed, rather than hidden. */
export const hasExpired = (offer: Offer) =>
  !!offer.endsAt && +new Date(offer.endsAt) < Date.now();

/**
 * Screening questions, cleaned up.
 *
 * A question with no title is one the poster started and abandoned, so it
 * is dropped rather than shown to applicants as a blank. Three is the cap.
 */
export function cleanQuestions(raw: unknown): JobQuestion[] | undefined {
  if (!Array.isArray(raw)) return undefined;
  const out: JobQuestion[] = [];
  for (const q of raw.slice(0, 3)) {
    const title = String((q as JobQuestion)?.title ?? "").trim().slice(0, 256);
    if (!title) continue;
    const multi = (q as JobQuestion)?.type === "multiple_choice";
    const choices = multi
      ? (Array.isArray((q as JobQuestion).choices) ? (q as JobQuestion).choices! : [])
          .map((c) => String(c).trim().slice(0, 100))
          .filter(Boolean)
          .slice(0, 10)
      : undefined;
    // A multiple choice with nothing to choose from is a text question.
    out.push(
      multi && choices && choices.length
        ? { type: "multiple_choice", title, choices }
        : { type: "text", title }
    );
  }
  return out.length ? out : undefined;
}
