import type { MothershipAddressCandidate } from "@/modules/address/types";

export type StreetDirection = "N" | "S" | "E" | "W";

const DIRECTION_FULL: Record<StreetDirection, string> = {
  N: "North",
  S: "South",
  E: "East",
  W: "West",
};

/** 解析门牌后方位（单字母或 North/East 全称） */
export function parseStreetDirection(street: string): StreetDirection | null {
  const trimmed = street.trim();
  const letter = trimmed.match(/^\d+\s+([NSEW])\b/i);
  if (letter) {
    return letter[1]!.toUpperCase() as StreetDirection;
  }
  for (const dir of Object.keys(DIRECTION_FULL) as StreetDirection[]) {
    if (new RegExp(`\\b${DIRECTION_FULL[dir]}\\b`, "i").test(trimmed)) {
      return dir;
    }
  }
  return null;
}

/**
 * 将「600 W 7th St」展开为 MotherShip 更常识别的「600 West 7th Street」。
 * 仅处理门牌后单字母方位；无法识别时返回 null。
 */
export function expandDirectionalStreet(street: string): string | null {
  const trimmed = street.trim();
  const match = trimmed.match(/^(\d+)\s+([NSEW])\s+(.+)$/i);
  if (!match) {
    return null;
  }
  const dir = match[2]!.toUpperCase() as StreetDirection;
  const fullDir = DIRECTION_FULL[dir];
  if (!fullDir) {
    return null;
  }
  let rest = match[3]!.trim();
  rest = rest.replace(/\bSt\.?$/i, "Street");
  return `${match[1]} ${fullDir} ${rest}`.replace(/\s+/g, " ").trim();
}

function labelHasDirection(
  label: string,
  dir: StreetDirection,
): boolean {
  const lower = label.toLowerCase();
  const full = DIRECTION_FULL[dir].toLowerCase();
  if (lower.includes(full)) {
    return true;
  }
  return new RegExp(`\\b\\d+\\s+${dir}\\b`, "i").test(label);
}

/** 按用户草稿对 MotherShip 候选打分（方位一致优先，相反方位重罚） */
export function scoreMothershipCandidateForDraft(
  candidate: MothershipAddressCandidate,
  draft: { street: string; city: string; state: string },
): number {
  const label = `${candidate.display_label} ${candidate.street}`.toLowerCase();
  let score = 0;

  const streetNum = draft.street.match(/^\d+/)?.[0];
  if (streetNum && label.includes(streetNum)) {
    score += 12;
  }
  const city = draft.city.trim().toLowerCase();
  if (city && label.includes(city)) {
    score += 6;
  }
  const state = draft.state.trim().toLowerCase();
  if (state && label.includes(state)) {
    score += 3;
  }

  const draftDir = parseStreetDirection(draft.street);
  if (draftDir) {
    const opposite: Record<StreetDirection, StreetDirection> = {
      N: "S",
      S: "N",
      E: "W",
      W: "E",
    };
    if (labelHasDirection(label, draftDir)) {
      score += 18;
    }
    if (labelHasDirection(label, opposite[draftDir])) {
      score -= 28;
    }

    const expanded = expandDirectionalStreet(draft.street);
    if (expanded && label.includes(expanded.toLowerCase())) {
      score += 14;
    }
    if (
      expanded &&
      /\b\d+\s+[nsew]\s+/i.test(draft.street) &&
      label.includes(expanded.toLowerCase()) === false &&
      labelHasDirection(label, draftDir)
    ) {
      score -= 8;
    }
  }

  if (/\bstreet\b/i.test(label)) {
    score += 4;
  }
  if (/\bbridge\b/.test(label) && !/\bbridge\b/i.test(draft.street)) {
    score -= 20;
  }

  return score;
}

export function sortMothershipCandidatesForDraft(
  candidates: MothershipAddressCandidate[],
  draft: { street: string; city: string; state: string },
): MothershipAddressCandidate[] {
  return [...candidates].sort(
    (a, b) =>
      scoreMothershipCandidateForDraft(b, draft) -
      scoreMothershipCandidateForDraft(a, draft),
  );
}
