/** US states + DC only. Mortgage protection in this app is United States. */

export const US_STATES: Record<string, string> = {
  alabama: "AL",
  alaska: "AK",
  arizona: "AZ",
  arkansas: "AR",
  california: "CA",
  colorado: "CO",
  connecticut: "CT",
  delaware: "DE",
  florida: "FL",
  georgia: "GA",
  hawaii: "HI",
  idaho: "ID",
  illinois: "IL",
  indiana: "IN",
  iowa: "IA",
  kansas: "KS",
  kentucky: "KY",
  louisiana: "LA",
  maine: "ME",
  maryland: "MD",
  massachusetts: "MA",
  michigan: "MI",
  minnesota: "MN",
  mississippi: "MS",
  missouri: "MO",
  montana: "MT",
  nebraska: "NE",
  nevada: "NV",
  "new hampshire": "NH",
  "new jersey": "NJ",
  "new mexico": "NM",
  "new york": "NY",
  "north carolina": "NC",
  "north dakota": "ND",
  ohio: "OH",
  oklahoma: "OK",
  oregon: "OR",
  pennsylvania: "PA",
  "rhode island": "RI",
  "south carolina": "SC",
  "south dakota": "SD",
  tennessee: "TN",
  texas: "TX",
  utah: "UT",
  vermont: "VT",
  virginia: "VA",
  washington: "WA",
  "west virginia": "WV",
  wisconsin: "WI",
  wyoming: "WY",
  "district of columbia": "DC",
  dc: "DC",
};

const ABBR = new Set(Object.values(US_STATES));

const NON_US = [
  "india",
  "bharat",
  "rajasthan",
  "rajsthan",
  "rajastan",
  "hanumangarh",
  "delhi",
  "mumbai",
  "pakistan",
  "uk",
  "england",
  "canada",
  "ontario",
  "mexico",
  "australia",
];

/** Greetings must never be treated as identity or a U.S. state (Hi ≠ Hawaii). */
export function isGreetingOnly(message: string): boolean {
  return /^(hi|hii+|hello|hey|yo|sup|thanks|thank you|good morning|good afternoon|good evening)[!.,\s]*$/i.test(
    message.trim()
  );
}

const AMBIGUOUS_ABBR = new Set(["HI", "IN", "OR", "ME", "OK"]);

export function parseUsState(text: string): string | null {
  const raw = text.trim();
  if (!raw || isGreetingOnly(raw)) return null;
  const lower = raw.toLowerCase().replace(/\./g, "");
  if (US_STATES[lower]) return US_STATES[lower];
  const compact = lower.replace(/\s+/g, " ");
  if (US_STATES[compact]) return US_STATES[compact];

  const propertyClause = compact.match(
    /(?:property|mortgage|home loan|the loan)\s+(?:is\s+)?(?:in|for)\s+([a-z ]{2,30})/
  );
  if (propertyClause) {
    const fromProperty = parseUsState(propertyClause[1].trim());
    if (fromProperty) return fromProperty;
  }

  const words = compact.replace(/[^a-z\s]/g, " ").split(/\s+/).filter(Boolean);
  for (let n = 3; n >= 1; n--) {
    for (let i = 0; i + n <= words.length; i++) {
      const chunk = words.slice(i, i + n).join(" ");
      if (chunk === "hi" || chunk === "ok" || chunk === "me" || chunk === "or" || chunk === "in") continue;
      if (US_STATES[chunk]) return US_STATES[chunk];
    }
  }

  const abbr = raw.toUpperCase().match(/\b([A-Z]{2})\b/g) || [];
  const hasStateCue = /\b(state|hawaii|texas|florida|california)\b/i.test(text);
  for (const a of abbr) {
    if (!ABBR.has(a)) continue;
    if (AMBIGUOUS_ABBR.has(a) && !hasStateCue && raw.trim().length <= 3) continue;
    if (AMBIGUOUS_ABBR.has(a) && !hasStateCue) continue;
    return a;
  }
  if (/^(tx|fl|ca|ny|il|pa|oh|ga|nc|mi|nj|va|wa|az|ma|tn|in|mo|md|wi|co|mn|sc|al|la|ky|or|ok|ct|ut|ia|nv|ar|ms|ks|nm|ne|id|wv|hi|nh|me|ri|mt|de|sd|nd|ak|vt|wy|dc)$/i.test(raw) && !isGreetingOnly(raw)) {
    if (AMBIGUOUS_ABBR.has(raw.toUpperCase())) return null;
    return raw.toUpperCase();
  }
  return null;
}

export function isNonUsLocation(text: string): boolean {
  const t = text.toLowerCase();
  return NON_US.some((w) => t.includes(w));
}

const NAME_STOP = new Set([
  "in",
  "from",
  "at",
  "live",
  "lives",
  "living",
  "leave",
  "lived",
  "the",
  "a",
  "an",
  "and",
  "or",
  "hi",
  "hello",
  "hey",
  "looking",
  "calling",
  "interested",
  "only",
  "cigar",
  "smoker",
  "regular",
  "diabetic",
  "diabtic",
  "condition",
  "kindly",
  "note",
  "health",
  "not",
  "using",
  "tobacco",
  "nicotine",
  "things",
  "fictional",
  "healthy",
  "fit",
  "texas",
  "california",
  "florida",
  "arizona",
  "ohio",
  "nevada",
  "hawaii",
  "washington",
  ...Object.keys(US_STATES),
  ...Object.values(US_STATES).map((a) => a.toLowerCase()),
]);

function clipNameTokens(raw: string): string | null {
  const words: string[] = [];
  for (const token of raw.split(/\s+/)) {
    const w = token.replace(/[^A-Za-z'-]/g, "");
    if (!w) continue;
    if (NAME_STOP.has(w.toLowerCase())) break;
    if (/^(years?|old|from)$/i.test(w)) break;
    words.push(w);
    if (words.length >= 4) break;
  }
  if (words.length === 0) return null;
  if (words.length === 1 && words[0].length < 2) return null;
  return words.join(" ");
}

export function extractPersonName(message: string): string | null {
  if (!/(?:my name is|this is)\s+/i.test(message) && /^(hi|hello|hey)/i.test(message.trim())) {
    /* fall through if "Hi I am Jane" */
  }
  if (/\bi am (only|just|a |an |regular|also|not)\b/i.test(message) && !/my name is/i.test(message)) {
    return null;
  }
  const self = message.match(/\bmy selft?\s+([A-Z][a-z]+(?:\s+[A-Z][a-z]+)?)/i);
  if (self && !/fictional/i.test(self[1])) {
    return self[1];
  }
  const namedExplicit = message.match(/my name is\s+([A-Za-z][A-Za-z'-]+(?:\s+[A-Za-z][A-Za-z'-]+){0,3})/i);
  if (namedExplicit) {
    const clipped = clipNameTokens(namedExplicit[1]);
    if (clipped && isPlausibleName(clipped)) return clipped;
  }
  const clause = message.split(/[.!?]/)[0];
  const m = clause.match(/(?:this is|i['’]m|i am)\s+(.+)/i);
  if (!m) return null;
  return clipNameTokens(m[1]);
}

export function isPlausibleName(name: string): boolean {
  const parts = name.trim().split(/\s+/);
  if (parts.length === 0) return false;
  if (parts.some((p) => NAME_STOP.has(p.toLowerCase()))) return false;
  return /^[A-Za-z][A-Za-z'-]*(?:\s+[A-Za-z][A-Za-z'-]*){0,3}$/.test(name.trim());
}
