/**
 * classifyUrls — 랜딩 MultiChannelInput 전용 URL 분류 유틸.
 *
 * 사용자가 textarea에 붙여넣은 여러 URL을 7개 채널(holder)로 분류합니다.
 *  - homepage · youtube · instagram · facebook · naverPlace · naverBlog · gangnamUnni · unknown
 *
 * 설계 결정:
 *  1) 결정론적 regex 분류 (AI 추측 없음) — 백엔드의 extractSocialLinks 패턴을 브라우저로 복제.
 *     ⚠️ 백엔드와 프론트 두 곳의 패턴은 **동일하게 유지**되어야 합니다. SNS 플랫폼 URL 구조 변경 시 같이 수정하세요.
 *
 *  2) 우선순위: naverPlace / gangnamUnni (고유 도메인) → YouTube / Instagram / Facebook / naverBlog
 *     → 미매치이면서 `new URL()` 성공한 URL 중 **호스트네임이 SNS 도메인이 아닌 경우만** homepage.
 *     호스트네임이 SNS인데 프로필 패턴 불일치 (예: instagram.com/p/XYZ, youtube.com/watch)는 `unknown`.
 *     ▸ "homepage" 필드가 분석 첫 진입점이라서, 여기에 잘못된 URL이 들어가면 전체 파이프라인이
 *       잘못된 축으로 돌아갑니다. 따라서 방어적으로 분류합니다.
 *
 *  3) 값은 **원본 URL 문자열**을 그대로 보관 — backend `discover-channels`의 `manualChannels`는
 *     URL을 받아서 내부에서 handle을 추출하므로, 프론트에서 미리 handle로 변환하지 않습니다.
 *     (백엔드 discover-channels 워커가 extractHandleFromUrl 처리)
 *
 *  4) 중복 제거 — 공백/줄바꿈/쉼표로 분리 후, 정규화된 URL(소문자 + trailing slash 제거) 기준으로 dedup.
 */

export interface ClassifiedUrls {
  homepage: string[];
  youtube: string[];
  instagram: string[];
  facebook: string[];
  naverPlace: string[];
  naverBlog: string[];
  gangnamUnni: string[];
  /** 파싱 실패 or SNS 도메인이지만 프로필이 아닌 URL (포스트/비디오 등) */
  unknown: string[];
}

/** SNS 호스트네임 집합 — 이들 도메인인데 프로필 패턴에 매치되지 않으면 `unknown`으로 강제. */
const SNS_HOSTNAMES = new Set([
  'instagram.com',
  'www.instagram.com',
  'm.instagram.com',
  'youtube.com',
  'www.youtube.com',
  'm.youtube.com',
  'youtu.be',
  'facebook.com',
  'www.facebook.com',
  'm.facebook.com',
  'fb.com',
  'blog.naver.com',
  'm.blog.naver.com',
  'place.naver.com',
  'm.place.naver.com',
  'map.naver.com',
  'gangnamunni.com',
  'm.gangnamunni.com',
  'www.gangnamunni.com',
]);

/** Instagram 프로필이 아닌 경로 (포스트/릴/스토리 등) */
const IG_SKIP = new Set([
  'p', 'reel', 'reels', 'stories', 'explore', 'accounts',
  'about', 'developer', 'legal', 'privacy', 'terms',
]);

/** Facebook 페이지가 아닌 경로 */
const FB_SKIP = new Set([
  'sharer', 'share', 'login', 'help', 'pages', 'events', 'groups',
  'marketplace', 'watch', 'gaming', 'privacy', 'policies', 'tr',
  'dialog', 'plugins', 'photo', 'video', 'reel',
]);

/** YouTube 프로필 패턴: `@handle`, `channel/UC...`, `c/custom`, `user/...` */
const YT_PROFILE_RE = /youtube\.com\/(?:@[a-zA-Z0-9._-]+|channel\/UC[a-zA-Z0-9_-]+|c\/[a-zA-Z0-9._-]+|user\/[a-zA-Z0-9._-]+)/i;

/** Naver Place: place.naver.com/{cat}/{id}, map.naver.com/p/entry/place/{id}, naver.me/{shortcode} */
const NAVER_PLACE_RE = /(?:m\.)?place\.naver\.com\/[a-z]+\/\d+|map\.naver\.com\/(?:p|v\d+)\/entry\/place\/\d+|naver\.me\/[a-zA-Z0-9]+/i;

/** Naver Blog: blog.naver.com/{id} (또는 m.blog.naver.com) */
const NAVER_BLOG_RE = /(?:m\.)?blog\.naver\.com\/[a-zA-Z0-9_-]+/i;

/** 강남언니: gangnamunni.com/hospitals/{id-or-slug} */
const GANGNAMUNNI_RE = /(?:m\.|www\.)?gangnamunni\.com\/hospitals?\/[a-zA-Z0-9_-]+/i;

/** Instagram 프로필: instagram.com/{handle} — 포스트/릴 등은 아래 IG_SKIP로 걸러냄 */
const IG_RE = /(?:www\.|m\.)?instagram\.com\/([a-zA-Z0-9._]+)\/?/i;

/** Facebook 페이지: facebook.com/{page} */
const FB_RE = /(?:www\.|m\.)?facebook\.com\/([a-zA-Z0-9._-]+)\/?/i;

/**
 * URL 문자열을 정규화해 중복 체크 키로 사용.
 *  - 소문자, trailing slash 제거, scheme 유지
 *  - URL 파싱 실패 시 원본 trim.
 */
function normalizeForDedup(url: string): string {
  try {
    const u = new URL(url);
    const path = u.pathname.replace(/\/+$/, '');
    return `${u.protocol}//${u.hostname.toLowerCase()}${path}${u.search}`.toLowerCase();
  } catch {
    return url.trim().toLowerCase();
  }
}

/**
 * 단일 URL 토큰을 분류해서 어느 버킷에 넣을지 결정.
 * 반환값: [bucketKey, originalUrl] 또는 null (이미 중복).
 */
function classifySingle(
  rawToken: string,
): { bucket: keyof ClassifiedUrls; value: string } | null {
  const token = rawToken.trim();
  if (!token || token.length < 4) return null;

  // URL 파싱 시도 — 실패하면 unknown
  let parsed: URL;
  try {
    // scheme 없는 경우 https:// 추가 (예: "instagram.com/foo")
    const withScheme = /^https?:\/\//i.test(token) ? token : `https://${token}`;
    parsed = new URL(withScheme);
  } catch {
    return { bucket: 'unknown', value: token };
  }

  const hostname = parsed.hostname.toLowerCase();
  const fullUrl = parsed.toString();

  // 1) Naver Place (고유 도메인)
  if (NAVER_PLACE_RE.test(fullUrl)) {
    return { bucket: 'naverPlace', value: fullUrl };
  }

  // 2) 강남언니 (고유 도메인)
  if (GANGNAMUNNI_RE.test(fullUrl)) {
    return { bucket: 'gangnamUnni', value: fullUrl };
  }

  // 3) Naver Blog
  if (NAVER_BLOG_RE.test(fullUrl)) {
    return { bucket: 'naverBlog', value: fullUrl };
  }

  // 4) YouTube — 프로필 패턴만 매치
  if (hostname.endsWith('youtube.com') || hostname === 'youtu.be') {
    if (YT_PROFILE_RE.test(fullUrl)) {
      return { bucket: 'youtube', value: fullUrl };
    }
    // youtube.com 인데 프로필 아님 (watch URL 등) → unknown
    return { bucket: 'unknown', value: fullUrl };
  }

  // 5) Instagram
  if (hostname.endsWith('instagram.com')) {
    const m = fullUrl.match(IG_RE);
    const firstSeg = m?.[1];
    if (firstSeg && !IG_SKIP.has(firstSeg.toLowerCase())) {
      return { bucket: 'instagram', value: fullUrl };
    }
    return { bucket: 'unknown', value: fullUrl };
  }

  // 6) Facebook
  if (hostname.endsWith('facebook.com') || hostname.endsWith('fb.com')) {
    const m = fullUrl.match(FB_RE);
    const firstSeg = m?.[1];
    if (firstSeg && !FB_SKIP.has(firstSeg.toLowerCase())) {
      return { bucket: 'facebook', value: fullUrl };
    }
    return { bucket: 'unknown', value: fullUrl };
  }

  // 7) 남은 케이스: SNS 도메인이면 unknown (프로필 패턴 미매치), 아니면 homepage
  if (SNS_HOSTNAMES.has(hostname)) {
    return { bucket: 'unknown', value: fullUrl };
  }

  return { bucket: 'homepage', value: fullUrl };
}

/**
 * 사용자 textarea 입력 → 7채널 분류 결과.
 * 공백/쉼표/줄바꿈으로 분리된 각 토큰을 개별 URL로 간주합니다.
 */
export function classifyUrls(input: string): ClassifiedUrls {
  const result: ClassifiedUrls = {
    homepage: [],
    youtube: [],
    instagram: [],
    facebook: [],
    naverPlace: [],
    naverBlog: [],
    gangnamUnni: [],
    unknown: [],
  };

  if (!input || typeof input !== 'string') return result;

  // 공백/쉼표/줄바꿈으로 분리
  const tokens = input.split(/[\s,]+/).map((t) => t.trim()).filter(Boolean);

  // 버킷별 중복 체크 — 같은 URL이 textarea에 두 번 나와도 한 번만
  const seen: Record<keyof ClassifiedUrls, Set<string>> = {
    homepage: new Set(),
    youtube: new Set(),
    instagram: new Set(),
    facebook: new Set(),
    naverPlace: new Set(),
    naverBlog: new Set(),
    gangnamUnni: new Set(),
    unknown: new Set(),
  };

  for (const token of tokens) {
    const classified = classifySingle(token);
    if (!classified) continue;

    const key = normalizeForDedup(classified.value);
    if (seen[classified.bucket].has(key)) continue;
    seen[classified.bucket].add(key);
    result[classified.bucket].push(classified.value);
  }

  return result;
}

/**
 * 채널 중 하나라도 분석 대상이 있는지 — 분석 시작 버튼 활성화 조건.
 * homepage·SNS 중 최소 1건이 있으면 true. unknown은 제외.
 */
export function hasAnalyzableChannels(classified: ClassifiedUrls): boolean {
  return (
    classified.homepage.length > 0 ||
    classified.youtube.length > 0 ||
    classified.instagram.length > 0 ||
    classified.facebook.length > 0 ||
    classified.naverPlace.length > 0 ||
    classified.naverBlog.length > 0 ||
    classified.gangnamUnni.length > 0
  );
}

/**
 * 분석 파이프라인의 "primary URL" 결정.
 * 홈페이지가 있으면 최우선, 없으면 검출된 첫 SNS URL 반환.
 * 백엔드 startAnalysis 요청의 `url` 필드 (필수)로 사용됩니다.
 */
export function pickPrimaryUrl(classified: ClassifiedUrls): string | null {
  if (classified.homepage[0]) return classified.homepage[0];
  // 홈페이지 없으면 SNS 중 아무거나 대표값으로
  const fallback =
    classified.naverPlace[0] ||
    classified.instagram[0] ||
    classified.youtube[0] ||
    classified.facebook[0] ||
    classified.naverBlog[0] ||
    classified.gangnamUnni[0];
  return fallback || null;
}
