/**
 * 한국어 스마트 검색 유틸리티
 * - 초성 추출 및 매칭
 * - 별칭(alias) 매칭
 * - 인메모리 캐시 (5분 TTL)
 */
const { getDb } = require('../dbPool');

// 초성 목록 (19개)
const CHOSUNG = [
  'ㄱ','ㄲ','ㄴ','ㄷ','ㄸ','ㄹ','ㅁ','ㅂ','ㅃ','ㅅ',
  'ㅆ','ㅇ','ㅈ','ㅉ','ㅊ','ㅋ','ㅌ','ㅍ','ㅎ'
];

// 자음 문자 집합 (초성 판별용)
const JAMO_SET = new Set([
  'ㄱ','ㄲ','ㄴ','ㄷ','ㄸ','ㄹ','ㅁ','ㅂ','ㅃ','ㅅ',
  'ㅆ','ㅇ','ㅈ','ㅉ','ㅊ','ㅋ','ㅌ','ㅍ','ㅎ'
]);

// 캐시
let cache = null;
let cacheTime = 0;
const CACHE_TTL = 5 * 60 * 1000; // 5분

/**
 * 한글 완성형 문자에서 초성 추출
 * @param {string} str
 * @returns {string} 초성 문자열
 */
function extractChosung(str) {
  let result = '';
  for (const ch of str) {
    const code = ch.charCodeAt(0);
    if (code >= 0xAC00 && code <= 0xD7A3) {
      const idx = Math.floor((code - 0xAC00) / (21 * 28));
      result += CHOSUNG[idx];
    } else {
      result += ch;
    }
  }
  return result;
}

/**
 * 검색어가 모두 자음(초성)인지 판별
 * @param {string} query
 * @returns {boolean}
 */
function isChosungOnly(query) {
  if (query.length < 2) return false;
  for (const ch of query) {
    if (!JAMO_SET.has(ch)) return false;
  }
  return true;
}

/**
 * 캐시 로드 (consumable_items + item_aliases)
 */
async function loadCache() {
  if (cache && (Date.now() - cacheTime < CACHE_TTL)) return cache;

  const db = await getDb();
  const [items] = await db.query(
    `SELECT item_id, item_name, spec, maker, category, base_price, unit, photo_path
     FROM consumable_items WHERE is_active = 1`
  );
  const [aliases] = await db.query(
    `SELECT alias_id, item_id, alias_name FROM item_aliases`
  );

  // 아이템별 별칭 맵 생성
  const aliasMap = {};
  for (const a of aliases) {
    if (!aliasMap[a.item_id]) aliasMap[a.item_id] = [];
    aliasMap[a.item_id].push(a.alias_name);
  }

  // 초성 미리 계산
  const enriched = items.map(item => ({
    ...item,
    aliases: aliasMap[item.item_id] || [],
    chosung_name: extractChosung(item.item_name),
    chosung_aliases: (aliasMap[item.item_id] || []).map(a => extractChosung(a))
  }));

  cache = enriched;
  cacheTime = Date.now();
  return cache;
}

/**
 * 캐시 무효화
 */
function clearCache() {
  cache = null;
  cacheTime = 0;
}

/**
 * 스마트 검색
 * @param {string} query - 검색어
 * @returns {Promise<Array>} 스코어 기준 상위 20건
 */
async function search(query) {
  if (!query || query.trim().length === 0) return [];
  const items = await loadCache();
  const q = query.trim().toLowerCase();
  const qChosung = isChosungOnly(q) ? q : null;

  const scored = [];
  for (const item of items) {
    let score = 0;
    let matchType = '';

    const nameLower = item.item_name.toLowerCase();
    const specLower = (item.spec || '').toLowerCase();
    const makerLower = (item.maker || '').toLowerCase();

    // exact match (이름 완전 일치)
    if (nameLower === q) {
      score = 100; matchType = 'exact';
    }
    // substring match (이름)
    else if (nameLower.includes(q)) {
      score = 80; matchType = 'name';
    }
    // alias match
    else if (item.aliases.some(a => a.toLowerCase().includes(q))) {
      score = 75; matchType = 'alias';
    }
    // spec/maker match
    else if (specLower.includes(q) || makerLower.includes(q)) {
      score = 70; matchType = 'spec';
    }
    // 초성 매칭 (이름)
    else if (qChosung && item.chosung_name.includes(qChosung)) {
      score = 50; matchType = 'chosung';
    }
    // 초성 매칭 (별칭)
    else if (qChosung && item.chosung_aliases.some(ca => ca.includes(qChosung))) {
      score = 40; matchType = 'chosung_alias';
    }

    if (score > 0) {
      scored.push({ ...item, _score: score, _matchType: matchType });
    }
  }

  // 점수 높은 순, 같은 점수면 이름 짧은 순 (더 구체적)
  scored.sort((a, b) => b._score - a._score || a.item_name.length - b.item_name.length);
  return scored.slice(0, 20);
}

module.exports = { search, clearCache, extractChosung, isChosungOnly };
