import { z } from "zod";

export const EXTRACTOR_SOURCE_IDS = [
  "gradcracker",
  "indeed",
  "linkedin",
  "glassdoor",
  "ukvisajobs",
  "adzuna",
  "hiringcafe",
  "startupjobs",
  // --- Public APIs / feeds ---
  "usajobs",
  "jobicy",
  "themuse",
  "jooble",
  "careerjet",
  "reed",
  "remoteok",
  "remotive",
  "arbeitnow",
  "himalayas",
  "weworkremotely",
  "workingnomads",
  "fourdayweek",
  "testdevjobs",
  "wellfound",
  "builtin",
  "google-jobs",
  // --- Public ATS / career-page sources ---
  "ashby",
  "lever",
  "greenhouse",
  "workday",
  "smartrecruiters",
  "teamtailor",
  "huntflow",
  "factorial",
  "icims",
  "bctenet",
  "eluta",
  "qajobsboard",
  "arcdev",
  "careerspages",
  "manual",
] as const;

export type ExtractorSourceId = (typeof EXTRACTOR_SOURCE_IDS)[number];

export interface ExtractorSourceMetadata {
  label: string;
  order: number;
  category: "pipeline" | "manual";
  requiresCredentials?: boolean;
  ukOnly?: boolean;
  /** Country gating: when set, only run/show this source for these country keys. */
  countryAllowlist?: readonly string[];
  /** Region tag for grouping / filtering in the UI. */
  region?: "us" | "uk" | "global" | "remote";
}

export const EXTRACTOR_SOURCE_METADATA: Record<
  ExtractorSourceId,
  ExtractorSourceMetadata
> = {
  gradcracker: {
    label: "Gradcracker",
    order: 10,
    category: "pipeline",
    ukOnly: true,
    region: "uk",
  },
  indeed: {
    label: "Indeed",
    order: 20,
    category: "pipeline",
    region: "global",
  },
  linkedin: {
    label: "LinkedIn",
    order: 30,
    category: "pipeline",
    region: "global",
  },
  glassdoor: {
    label: "Glassdoor",
    order: 40,
    category: "pipeline",
    region: "global",
  },
  ukvisajobs: {
    label: "UK Visa Jobs",
    order: 50,
    category: "pipeline",
    requiresCredentials: true,
    ukOnly: true,
    region: "uk",
  },
  adzuna: {
    label: "Adzuna",
    order: 60,
    category: "pipeline",
    requiresCredentials: true,
    region: "global",
  },
  hiringcafe: {
    label: "Hiring Cafe",
    order: 70,
    category: "pipeline",
    region: "global",
  },
  startupjobs: {
    label: "startup.jobs",
    order: 80,
    category: "pipeline",
    region: "global",
  },
  usajobs: {
    label: "USAJOBS",
    order: 110,
    category: "pipeline",
    requiresCredentials: true,
    countryAllowlist: ["united states", "usa", "us"],
    region: "us",
  },
  jobicy: {
    label: "Jobicy (Remote)",
    order: 120,
    category: "pipeline",
    region: "remote",
  },
  themuse: {
    label: "The Muse",
    order: 130,
    category: "pipeline",
    region: "global",
  },
  jooble: {
    label: "Jooble",
    order: 140,
    category: "pipeline",
    requiresCredentials: true,
    region: "global",
  },
  careerjet: {
    label: "Careerjet",
    order: 150,
    category: "pipeline",
    requiresCredentials: true,
    region: "global",
  },
  reed: {
    label: "Reed",
    order: 160,
    category: "pipeline",
    requiresCredentials: true,
    ukOnly: true,
    countryAllowlist: ["united kingdom", "uk", "great britain", "england"],
    region: "uk",
  },
  remoteok: {
    label: "Remote OK",
    order: 170,
    category: "pipeline",
    region: "remote",
  },
  remotive: {
    label: "Remotive",
    order: 175,
    category: "pipeline",
    region: "remote",
  },
  arbeitnow: {
    label: "Arbeitnow",
    order: 180,
    category: "pipeline",
    region: "global",
  },
  himalayas: {
    label: "Himalayas",
    order: 185,
    category: "pipeline",
    region: "remote",
  },
  weworkremotely: {
    label: "We Work Remotely",
    order: 190,
    category: "pipeline",
    region: "remote",
  },
  workingnomads: {
    label: "Working Nomads",
    order: 191,
    category: "pipeline",
    region: "remote",
  },
  fourdayweek: {
    label: "4 Day Week",
    order: 195,
    category: "pipeline",
    region: "remote",
  },
  testdevjobs: {
    label: "TestDevJobs",
    order: 196,
    category: "pipeline",
    region: "remote",
  },
  wellfound: {
    label: "Wellfound",
    order: 197,
    category: "pipeline",
    region: "global",
  },
  builtin: {
    label: "Built In",
    order: 198,
    category: "pipeline",
    region: "global",
  },
  "google-jobs": {
    label: "Google Jobs",
    order: 199,
    category: "pipeline",
    region: "global",
  },
  ashby: {
    label: "Ashby (ATS)",
    order: 210,
    category: "pipeline",
    region: "global",
  },
  lever: {
    label: "Lever (ATS)",
    order: 220,
    category: "pipeline",
    region: "global",
  },
  greenhouse: {
    label: "Greenhouse (ATS)",
    order: 230,
    category: "pipeline",
    region: "global",
  },
  workday: {
    label: "Workday (ATS)",
    order: 240,
    category: "pipeline",
    region: "global",
  },
  smartrecruiters: {
    label: "SmartRecruiters (ATS)",
    order: 245,
    category: "pipeline",
    region: "global",
  },
  teamtailor: {
    label: "Teamtailor (ATS)",
    order: 246,
    category: "pipeline",
    region: "global",
  },
  huntflow: {
    label: "Huntflow (ATS)",
    order: 247,
    category: "pipeline",
    region: "global",
  },
  factorial: {
    label: "Factorial (ATS)",
    order: 248,
    category: "pipeline",
    region: "global",
  },
  icims: {
    label: "iCIMS tenants (HTML)",
    order: 241,
    category: "pipeline",
    region: "global",
  },
  bctenet: {
    label: "BC T-Net (RSS)",
    order: 243,
    category: "pipeline",
    region: "global",
    countryAllowlist: ["canada"],
  },
  eluta: {
    label: "Eluta",
    order: 247,
    category: "pipeline",
    region: "global",
    countryAllowlist: ["canada"],
  },
  qajobsboard: {
    label: "QAJobsBoard",
    order: 248,
    category: "pipeline",
    region: "remote",
  },
  arcdev: {
    label: "Arc.dev",
    order: 249,
    category: "pipeline",
    region: "remote",
  },
  careerspages: {
    label: "Career Pages",
    order: 250,
    category: "pipeline",
    region: "global",
  },
  manual: { label: "Manual", order: 900, category: "manual" },
};

export const PIPELINE_EXTRACTOR_SOURCE_IDS = EXTRACTOR_SOURCE_IDS.filter(
  (source) => EXTRACTOR_SOURCE_METADATA[source].category === "pipeline",
);

const extractorSourceTuple = EXTRACTOR_SOURCE_IDS as unknown as [
  ExtractorSourceId,
  ...ExtractorSourceId[],
];

export const extractorSourceEnum = z.enum(extractorSourceTuple);

export function isExtractorSourceId(value: string): value is ExtractorSourceId {
  return EXTRACTOR_SOURCE_IDS.includes(value as ExtractorSourceId);
}

export function sourceLabel(source: ExtractorSourceId): string {
  return EXTRACTOR_SOURCE_METADATA[source].label;
}

export function sortSources<T extends { source: ExtractorSourceId }>(
  values: T[],
): T[] {
  return [...values].sort(
    (left, right) =>
      EXTRACTOR_SOURCE_METADATA[left.source].order -
      EXTRACTOR_SOURCE_METADATA[right.source].order,
  );
}
