export const SPONSORSHIP_GREEN_FLAG_IDS = [
  "tn_eligible",
  "will_sponsor",
  "authorized_to_work",
  "no_citizenship_block",
  "ca_us_presence",
] as const;

export const SPONSORSHIP_RED_FLAG_IDS = [
  "citizenship_required",
  "clearance_required",
  "unrestricted_work_auth",
] as const;

export const SPONSORSHIP_YELLOW_FLAG_IDS = ["no_sponsorship_stated"] as const;

/** @deprecated Use SPONSORSHIP_GREEN_FLAG_IDS */
export const SPONSORSHIP_POSITIVE_SIGNAL_IDS = SPONSORSHIP_GREEN_FLAG_IDS;

export const SPONSORSHIP_BLOCKER_SIGNAL_IDS = [
  ...SPONSORSHIP_RED_FLAG_IDS,
  ...SPONSORSHIP_YELLOW_FLAG_IDS,
] as const;

export const SPONSORSHIP_SIGNAL_IDS = [
  ...SPONSORSHIP_GREEN_FLAG_IDS,
  ...SPONSORSHIP_BLOCKER_SIGNAL_IDS,
] as const;

export type SponsorshipGreenFlagId =
  (typeof SPONSORSHIP_GREEN_FLAG_IDS)[number];
export type SponsorshipRedFlagId = (typeof SPONSORSHIP_RED_FLAG_IDS)[number];
export type SponsorshipYellowFlagId =
  (typeof SPONSORSHIP_YELLOW_FLAG_IDS)[number];
/** @deprecated Use SponsorshipGreenFlagId */
export type SponsorshipPositiveSignalId = SponsorshipGreenFlagId;
export type SponsorshipBlockerSignalId =
  (typeof SPONSORSHIP_BLOCKER_SIGNAL_IDS)[number];
export type SponsorshipSignalId = (typeof SPONSORSHIP_SIGNAL_IDS)[number];

export type SponsorshipFlagTier = "green" | "yellow" | "red";

export interface SponsorshipSignalMeta {
  id: SponsorshipSignalId;
  label: string;
  shortLabel: string;
  description: string;
  polarity: "positive" | "blocker";
  flagTier: SponsorshipFlagTier;
  strength: "strong" | "moderate" | "weak" | "hard" | "soft";
}

export const SPONSORSHIP_SIGNAL_META: Record<
  SponsorshipSignalId,
  SponsorshipSignalMeta
> = {
  tn_eligible: {
    id: "tn_eligible",
    label: "TN / USMCA eligible",
    shortLabel: "TN",
    description:
      'Green flag — listing mentions TN visa or USMCA eligibility (e.g. "open to TN").',
    polarity: "positive",
    flagTier: "green",
    strength: "strong",
  },
  will_sponsor: {
    id: "will_sponsor",
    label: "Will sponsor",
    shortLabel: "Sponsor",
    description:
      "Green flag — explicit visa sponsorship (often H-1B; ask if TN is supported).",
    polarity: "positive",
    flagTier: "green",
    strength: "strong",
  },
  authorized_to_work: {
    id: "authorized_to_work",
    label: "Authorized to work",
    shortLabel: "Auth",
    description:
      "Green flag — requires U.S. work authorization without naming citizenship. Clarify TN with recruiter.",
    polarity: "positive",
    flagTier: "green",
    strength: "moderate",
  },
  no_citizenship_block: {
    id: "no_citizenship_block",
    label: "No citizenship requirement",
    shortLabel: "No citizen req",
    description:
      "Green flag (weak) — no citizenship, clearance, or no-sponsorship language in a U.S.-context posting.",
    polarity: "positive",
    flagTier: "green",
    strength: "weak",
  },
  ca_us_presence: {
    id: "ca_us_presence",
    label: "Canada + U.S. offices",
    shortLabel: "CA+US",
    description:
      "Green flag — company in both Canada and the U.S. (possible L-1 transfer path).",
    polarity: "positive",
    flagTier: "green",
    strength: "moderate",
  },
  citizenship_required: {
    id: "citizenship_required",
    label: "Citizenship / GC / EAD only",
    shortLabel: "Citizen/GC",
    description:
      'Red flag — e.g. "U.S. citizen", "GC", or "EAD only" unless you already hold that status.',
    polarity: "blocker",
    flagTier: "red",
    strength: "hard",
  },
  clearance_required: {
    id: "clearance_required",
    label: "Security clearance required",
    shortLabel: "Clearance",
    description:
      "Red flag — active or required security clearance (usually U.S. citizen/GC only).",
    polarity: "blocker",
    flagTier: "red",
    strength: "hard",
  },
  unrestricted_work_auth: {
    id: "unrestricted_work_auth",
    label: "Unrestricted work auth",
    shortLabel: "Unrestricted",
    description:
      'Red flag — "unrestricted work authorization" often means citizen or green card, not TN.',
    polarity: "blocker",
    flagTier: "red",
    strength: "hard",
  },
  no_sponsorship_stated: {
    id: "no_sponsorship_stated",
    label: "No sponsorship stated",
    shortLabel: "No sponsor",
    description:
      'Yellow flag — says no visa sponsorship. Some employers still support TN. Ask: "Will you provide a TN support letter?"',
    polarity: "blocker",
    flagTier: "yellow",
    strength: "soft",
  },
};

export const SPONSORSHIP_SIGNAL_SEARCH_ALIASES: Record<
  SponsorshipSignalId,
  readonly string[]
> = {
  tn_eligible: [
    "tn",
    "usmca",
    "nafta",
    "tn visa",
    "open to tn",
    "tn friendly",
    "tn-friendly",
  ],
  will_sponsor: [
    "sponsor",
    "sponsorship",
    "visa sponsorship",
    "h-1b",
    "h1b",
    "will sponsor",
  ],
  authorized_to_work: [
    "authorized to work",
    "work authorization",
    "eligible to work",
  ],
  no_citizenship_block: [
    "no citizenship",
    "no citizen requirement",
    "no green card",
  ],
  ca_us_presence: ["canada us", "ca us", "l-1", "l1 transfer"],
  citizenship_required: [
    "citizen only",
    "gc only",
    "ead only",
    "us citizen",
    "green card",
    "citizenship required",
  ],
  clearance_required: [
    "clearance",
    "security clearance",
    "secret clearance",
    "top secret",
  ],
  unrestricted_work_auth: [
    "unrestricted work authorization",
    "unrestricted work auth",
  ],
  no_sponsorship_stated: [
    "no sponsorship",
    "no sponsor",
    "will not sponsor",
    "unable to sponsor",
  ],
};

const TN_PATTERNS = [
  /\bopen\s+to\s+tn\b/i,
  /\busmca[\s-]*eligible\b/i,
  /\btn[\s-]*eligible\b/i,
  /\btn[\s-]*friendly\b/i,
  /\btn\s+visa\b/i,
  /\btn\s+status\b/i,
  /\bnafta\s+professional\b/i,
  /\bopen\s+to\s+canadian\s+citizens?\b/i,
  /\bcanadian\s+citizens?\s+(?:welcome|eligible)\b/i,
];

const WILL_SPONSOR_PATTERNS = [
  /\bwill\s+sponsor\b/i,
  /\bvisa\s+sponsorship\s+(?:is\s+)?(?:available|provided|offered)\b/i,
  /\bh[\s-]?1b\s+sponsorship\b/i,
  /\bsponsor(?:s|ing)?\s+(?:work\s+)?visas?\b/i,
  /\bwork\s+visa\s+sponsorship\b/i,
  /\boffers?\s+visa\s+sponsorship\b/i,
];

const AUTHORIZED_PATTERNS = [
  /\b(?:legally\s+)?authorized\s+to\s+work\s+in\s+(?:the\s+)?u\.?s\.?\b/i,
  /\beligible\s+to\s+work\s+in\s+(?:the\s+)?u\.?s\.?\b/i,
  /\bwork\s+authorization\s+required\b/i,
  /\bmust\s+be\s+authorized\s+to\s+work\b/i,
  /\bwithout\s+sponsorship\s+for\s+work\s+authorization\b/i,
];

const CITIZENSHIP_REQUIRED_PATTERNS = [
  /\b(?:u\.?s\.?\s+)?citizen(?:ship)?\s+required\b/i,
  /\bmust\s+be\s+(?:a\s+)?u\.?s\.?\s+citizen\b/i,
  /\bonly\s+u\.?s\.?\s+citizens?\b/i,
  /\bgreen\s+card\s+required\b/i,
  /\bpermanent\s+resident(?:\s+status)?\s+required\b/i,
  /\b(?:u\.?s\.?\s+)?citizen(?:ship)?\s*,\s*g(?:reen\s+)?c(?:ard)?\b/i,
  /\b(?:u\.?s\.?\s+)?citizen(?:ship)?\s*,\s*g(?:reen\s+)?c(?:ard)?\s*,\s*e(?:mployment\s+)?a(?:uthorization\s+)?d\b/i,
  /\b(?:citizen(?:ship)?|g(?:reen\s+)?c|e(?:mployment\s+)?a(?:uthorization\s+)?d)\s+only\b/i,
  /\bcitizen\s*\/\s*gc\s*\/\s*ead\b/i,
  /\bu\.?s\.?\s+citizen\s*\/\s*g(?:reen\s+)?c\b/i,
  /\bgc\s*\/\s*ead\s+only\b/i,
  /\bead\s+only\b/i,
];

const CLEARANCE_REQUIRED_PATTERNS = [
  /\b(?:active\s+)?(?:secret|top[\s-]secret)\s+clearance\b/i,
  /\bsecurity\s+clearance\s+required\b/i,
  /\bclearance\s+required\b/i,
  /\bmust\s+(?:be\s+)?(?:able\s+to\s+)?obtain\s+(?:a\s+)?(?:security\s+)?clearance\b/i,
  /\beligible\s+for\s+(?:a\s+)?(?:u\.?s\.?\s+)?security\s+clearance\b/i,
  /\brequires?\s+(?:an?\s+)?active\s+clearance\b/i,
];

const UNRESTRICTED_WORK_AUTH_PATTERNS = [
  /\bunrestricted\s+work\s+authorization\s+only\b/i,
  /\bmust\s+have\s+unrestricted\s+work\s+(?:authorization|auth)\b/i,
  /\brequires?\s+unrestricted\s+work\s+(?:authorization|auth)\b/i,
  /\bunrestricted\s+work\s+authorization\s+required\b/i,
];

const NO_SPONSORSHIP_PATTERNS = [
  /\bno\s+visa\s+sponsorship\b/i,
  /\bno\s+sponsorship\b/i,
  /\bunable\s+to\s+sponsor\b/i,
  /\bwill\s+not\s+sponsor\b/i,
  /\bnot\s+(?:able|eligible)\s+to\s+sponsor\b/i,
  /\bno\s+sponsorship\s+(?:available|provided|offered)\b/i,
  /\bsponsorship\s+not\s+available\b/i,
  /\bdoes\s+not\s+sponsor\b/i,
  /\bcannot\s+sponsor\b/i,
  /\bnot\s+open\s+to\s+sponsorship\b/i,
];

const CANADA_PATTERNS = [
  /\bcanada\b/i,
  /\bcanadian\b/i,
  /\btoronto\b/i,
  /\bvancouver\b/i,
  /\bmontreal\b/i,
  /\bottawa\b/i,
  /\bcalgary\b/i,
  /\bontario\b/i,
  /\bquebec\b/i,
  /\bbritish\s+columbia\b/i,
  /\balberta\b/i,
];

const US_PATTERNS = [
  /\bu\.?s\.?\b/i,
  /\bunited\s+states\b/i,
  /\busa\b/i,
  /\bnew\s+york\b/i,
  /\bcalifornia\b/i,
  /\btexas\b/i,
  /\bflorida\b/i,
  /\bwashington\b/i,
  /\bchicago\b/i,
  /\bboston\b/i,
  /\bseattle\b/i,
  /\baustin\b/i,
];

export interface JobSponsorshipInput {
  jobDescription?: string | null;
  location?: string | null;
  companyAddresses?: string | null;
  companyDescription?: string | null;
}

function matchesAny(text: string, patterns: readonly RegExp[]): boolean {
  return patterns.some((pattern) => pattern.test(text));
}

function mentionsCanada(text: string): boolean {
  return matchesAny(text, CANADA_PATTERNS);
}

function mentionsUs(text: string): boolean {
  return matchesAny(text, US_PATTERNS);
}

function hasUsContext(input: JobSponsorshipInput, corpus: string): boolean {
  return (
    mentionsUs(corpus) ||
    Boolean(input.location && mentionsUs(input.location)) ||
    matchesAny(corpus, AUTHORIZED_PATTERNS) ||
    matchesAny(corpus, WILL_SPONSOR_PATTERNS) ||
    matchesAny(corpus, TN_PATTERNS)
  );
}

function hasRedFlagLanguage(text: string): boolean {
  return (
    matchesAny(text, CITIZENSHIP_REQUIRED_PATTERNS) ||
    matchesAny(text, CLEARANCE_REQUIRED_PATTERNS) ||
    matchesAny(text, UNRESTRICTED_WORK_AUTH_PATTERNS)
  );
}

function hasBlockerLanguage(text: string): boolean {
  return hasRedFlagLanguage(text) || matchesAny(text, NO_SPONSORSHIP_PATTERNS);
}

export function detectSponsorshipSignals(
  input: JobSponsorshipInput,
): SponsorshipSignalId[] {
  const parts = [
    input.jobDescription,
    input.location,
    input.companyAddresses,
    input.companyDescription,
  ].filter((part): part is string => Boolean(part?.trim()));

  if (parts.length === 0) return [];

  const corpus = parts.join("\n");
  const description = input.jobDescription?.trim() ?? "";
  const descriptionOrCorpus = description || corpus;
  const signals: SponsorshipSignalId[] = [];

  const citizenshipRequired = matchesAny(
    descriptionOrCorpus,
    CITIZENSHIP_REQUIRED_PATTERNS,
  );
  const clearanceRequired = matchesAny(
    descriptionOrCorpus,
    CLEARANCE_REQUIRED_PATTERNS,
  );
  const unrestrictedWorkAuth = matchesAny(
    descriptionOrCorpus,
    UNRESTRICTED_WORK_AUTH_PATTERNS,
  );
  const hasRedFlags =
    citizenshipRequired || clearanceRequired || unrestrictedWorkAuth;
  const noSponsorshipStated =
    !hasRedFlags && matchesAny(descriptionOrCorpus, NO_SPONSORSHIP_PATTERNS);
  const hasBlockers = hasRedFlags || noSponsorshipStated;

  if (citizenshipRequired) signals.push("citizenship_required");
  if (clearanceRequired) signals.push("clearance_required");
  if (unrestrictedWorkAuth) signals.push("unrestricted_work_auth");
  if (noSponsorshipStated) signals.push("no_sponsorship_stated");

  if (matchesAny(descriptionOrCorpus, TN_PATTERNS)) {
    signals.push("tn_eligible");
  }

  if (!hasBlockers && matchesAny(descriptionOrCorpus, WILL_SPONSOR_PATTERNS)) {
    signals.push("will_sponsor");
  }

  if (!hasBlockers && matchesAny(descriptionOrCorpus, AUTHORIZED_PATTERNS)) {
    signals.push("authorized_to_work");
  }

  if (
    descriptionOrCorpus.length >= 40 &&
    !hasBlockerLanguage(descriptionOrCorpus) &&
    hasUsContext(input, corpus)
  ) {
    signals.push("no_citizenship_block");
  }

  if (mentionsCanada(corpus) && mentionsUs(corpus)) {
    signals.push("ca_us_presence");
  }

  return signals;
}

export function parseSponsorshipSignals(
  json: string | null | undefined,
): SponsorshipSignalId[] {
  if (!json?.trim()) return [];
  try {
    const parsed: unknown = JSON.parse(json);
    if (!Array.isArray(parsed)) return [];
    return parsed.filter(
      (value): value is SponsorshipSignalId =>
        typeof value === "string" &&
        (SPONSORSHIP_SIGNAL_IDS as readonly string[]).includes(value),
    );
  } catch {
    return [];
  }
}

export function serializeSponsorshipSignals(
  signals: readonly SponsorshipSignalId[],
): string | null {
  const unique = [
    ...new Set(
      signals.filter((signal) =>
        (SPONSORSHIP_SIGNAL_IDS as readonly string[]).includes(signal),
      ),
    ),
  ];
  if (unique.length === 0) return null;
  return JSON.stringify(unique);
}

export function jobHasAnySponsorshipSignal(
  signalsJson: string | null | undefined,
  required: readonly SponsorshipSignalId[],
): boolean {
  if (required.length === 0) return true;
  const present = new Set(parseSponsorshipSignals(signalsJson));
  return required.some((signal) => present.has(signal));
}

export function jobHasSponsorshipBlocker(
  signalsJson: string | null | undefined,
): boolean {
  const present = new Set(parseSponsorshipSignals(signalsJson));
  return SPONSORSHIP_BLOCKER_SIGNAL_IDS.some((signal) => present.has(signal));
}

export function jobHasRedSponsorshipFlag(
  signalsJson: string | null | undefined,
): boolean {
  const present = new Set(parseSponsorshipSignals(signalsJson));
  return SPONSORSHIP_RED_FLAG_IDS.some((signal) => present.has(signal));
}

export function jobHasGreenSponsorshipFlag(
  signalsJson: string | null | undefined,
): boolean {
  const present = new Set(parseSponsorshipSignals(signalsJson));
  return SPONSORSHIP_GREEN_FLAG_IDS.some((signal) => present.has(signal));
}

export function sponsorshipSignalSearchHaystack(
  signalsJson: string | null | undefined,
): string {
  const signals = parseSponsorshipSignals(signalsJson);
  const parts: string[] = [];
  for (const signal of signals) {
    const meta = SPONSORSHIP_SIGNAL_META[signal];
    parts.push(meta.label, meta.shortLabel, meta.description);
    parts.push(...SPONSORSHIP_SIGNAL_SEARCH_ALIASES[signal]);
  }
  return parts.join(" ").toLowerCase();
}
