/**
 * 통합 알림 메시지 파싱
 * 형식: "🎯 알림 조건 충족 (N개)\n종목명 × 전략명\n..."
 * 한 알림에 여러 종목이 포함될 수 있음
 */

/**
 * 메시지에서 조건 충족한 투자전략명 목록 추출
 * "종목명 × 전략명" 형식의 각 라인에서 전략명 부분만 추출
 */
export function extractStrategyNames(message: string): string[] | null {
  if (!message || !message.includes('알림 조건 충족') || !message.includes('개)')) return null;
  const lines = message.split('\n').map((s) => s.trim()).filter(Boolean);
  const strategyNames: string[] = [];
  const SEPARATORS = [' × ', ' X '];
  for (let i = 1; i < lines.length; i++) {
    let idx = -1;
    for (const sep of SEPARATORS) {
      idx = lines[i].indexOf(sep);
      if (idx >= 0) break;
    }
    if (idx >= 0) {
      const name = lines[i].substring(idx + 3).trim();
      if (name) strategyNames.push(name);
    }
  }
  return strategyNames.length > 0 ? Array.from(new Set(strategyNames)) : null;
}

/**
 * 메시지에서 조건 충족한 종목명(한글) 목록 추출
 * "종목명 × 전략명" 형식의 각 라인에서 종목명 부분만 추출
 */
export function extractAssetNamesFromMessage(message: string): string[] | null {
  if (!message || !message.includes('알림 조건 충족') || !message.includes('개)')) return null;
  const lines = message.split('\n').map((s) => s.trim()).filter(Boolean);
  const names: string[] = [];
  const SEPARATORS = [' × ', ' X ']; // ×(유니코드), X(라틴) 모두 지원
  for (let i = 1; i < lines.length; i++) {
    let idx = -1;
    for (const sep of SEPARATORS) {
      idx = lines[i].indexOf(sep);
      if (idx >= 0) break;
    }
    if (idx >= 0) {
      const koreanName = lines[i].substring(0, idx).trim();
      if (koreanName) names.push(koreanName);
    }
  }
  return names.length > 0 ? Array.from(new Set(names)) : null;
}

/**
 * 메시지에서 "종목명 × 전략명" 라인별 항목 추출 (종목+전략 쌍)
 */
export function extractStockStrategyPairs(message: string): Array<{ koreanName: string; strategyName: string }> | null {
  if (!message || !message.includes('알림 조건 충족') || !message.includes('개)')) return null;
  const lines = message.split('\n').map((s) => s.trim()).filter(Boolean);
  const pairs: Array<{ koreanName: string; strategyName: string }> = [];
  const SEPARATORS = [' × ', ' X '];
  for (let i = 1; i < lines.length; i++) {
    let idx = -1;
    for (const sep of SEPARATORS) {
      idx = lines[i].indexOf(sep);
      if (idx >= 0) break;
    }
    if (idx >= 0) {
      const koreanName = lines[i].substring(0, idx).trim();
      const strategyName = lines[i].substring(idx + 3).trim();
      if (koreanName) pairs.push({ koreanName, strategyName: strategyName || '' });
    }
  }
  return pairs.length > 0 ? pairs : null;
}

/**
 * 알림 목록에서 symbol → 전략명[] 매핑 추출
 * 최신순 정렬된 알림에서, 각 종목별로 매칭된 전략명 수집 (중복 제거)
 */
export function extractSymbolToStrategyNames(
  notifications: Array<{ message?: string; symbol?: string; koreanName?: string; triggeredAt?: string }>,
  koreanToSymbol: Map<string, string>
): Record<string, string[]> {
  const symbolToStrategies = new Map<string, Set<string>>();
  const sorted = [...notifications].sort((a, b) => {
    const at = a.triggeredAt ? new Date(a.triggeredAt).getTime() : 0;
    const bt = b.triggeredAt ? new Date(b.triggeredAt).getTime() : 0;
    return bt - at;
  });

  for (const n of sorted) {
    const pairs = extractStockStrategyPairs(n.message || '');
    if (pairs && pairs.length > 0) {
      for (const { koreanName, strategyName } of pairs) {
        if (!strategyName?.trim()) continue;
        const row = resolveStockStrategyPairRow({ koreanName, strategyName }, koreanToSymbol);
        const s = row.navSymbol;
        if (s) {
          if (!symbolToStrategies.has(s)) symbolToStrategies.set(s, new Set());
          symbolToStrategies.get(s)!.add(strategyName.trim());
        }
      }
    } else if (n.symbol && n.koreanName) {
      // 단일 알림: 전략명은 메시지 첫 줄에서 추출
      const firstLine = (n.message || '').split('\n')[0]?.trim() || '';
      const strategyName = firstLine.replace(/^[\s🧪🎯✅]*/, '').trim();
      if (strategyName) {
        if (!symbolToStrategies.has(n.symbol)) symbolToStrategies.set(n.symbol, new Set());
        symbolToStrategies.get(n.symbol)!.add(strategyName);
      }
    }
  }

  const result: Record<string, string[]> = {};
  symbolToStrategies.forEach((strategies, symbol) => {
    result[symbol] = Array.from(strategies);
  });
  return result;
}

/** 통합 알림 한 줄의 왼쪽이 마켓코드(KRW-BTC)인 경우 — cryptoMap 키는 한글명이라 resolveSymbols만으로는 매칭 안 됨 */
const UPBIT_MARKET_CODE_RE = /^(KRW|USDT|BTC)-[A-Z0-9]+$/i;

function koreanNameForMarketSymbol(symbol: string, cryptoMap: Map<string, string>, fallback: string): string {
  const s = symbol.trim().toUpperCase();
  const entries = Array.from(cryptoMap.entries());
  for (let i = 0; i < entries.length; i++) {
    const [koreanName, sym] = entries[i];
    if (sym.toUpperCase() === s) return koreanName;
  }
  return fallback;
}

/**
 * 통합 알림 종목 행 표시용: 한글명·심볼·업비트 URL용 navSymbol 정리
 * - 메시지가 "KRW-BTC × CCI 1"처럼 마켓코드만 있으면 navSymbol을 채우고 한글 종목명으로 바꿉니다.
 */
export function resolveStockStrategyPairRow(
  pair: { koreanName: string; strategyName: string; symbol?: string },
  cryptoMap: Map<string, string>
): { koreanName: string; strategyName: string; symbol?: string; displaySymbol: string; navSymbol?: string } {
  if (pair.symbol?.trim()) {
    const navSymbol = pair.symbol.trim().toUpperCase();
    const left = pair.koreanName?.trim() || '';
    const koreanName =
      left && !UPBIT_MARKET_CODE_RE.test(left) ? pair.koreanName : koreanNameForMarketSymbol(navSymbol, cryptoMap, left || navSymbol);
    return { ...pair, koreanName, displaySymbol: navSymbol, navSymbol };
  }
  const raw = pair.koreanName?.trim() || '';
  if (UPBIT_MARKET_CODE_RE.test(raw)) {
    const navSymbol = raw.toUpperCase();
    const koreanName = koreanNameForMarketSymbol(navSymbol, cryptoMap, raw);
    return { ...pair, koreanName, displaySymbol: navSymbol, navSymbol };
  }
  const resolved = resolveSymbols([pair.koreanName], cryptoMap);
  return {
    ...pair,
    displaySymbol: resolved[0]?.symbol ?? pair.strategyName,
    navSymbol: resolved[0]?.symbol,
  };
}

/**
 * koreanName → symbol 매핑 (getActiveCryptos 결과 활용)
 * 공백 정규화 및 부분 일치로 한글명 표기 차이 보정
 */
export function resolveSymbols(
  koreanNames: string[],
  cryptoMap: Map<string, string>
): Array<{ symbol: string; koreanName: string }> {
  const normalize = (s: string) => s.replace(/\s+/g, ' ').trim();
  const entries = Array.from(cryptoMap.entries());

  const result: Array<{ symbol: string; koreanName: string }> = [];
  for (const kn of koreanNames) {
    const n = normalize(kn);
    let matched = entries.find(([k]) => normalize(k) === n || k === kn);
    if (!matched) {
      matched = entries.find(([k]) => normalize(k).includes(n) || n.includes(normalize(k)));
    }
    if (matched) result.push({ symbol: matched[1], koreanName: matched[0] });
  }
  return result;
}
