// AI 整理公司研究為固定 JSON 結構（產業鏈、簡介、管理層動態、新聞摘要）
import { callAI, extractJSONObject } from './ai-client.js';
import { getCompanyIntelEnriched, saveCompanyIntelEnriched } from './db.js';
import { computeNextPublicRefresh, shouldRunIntelSync, intelRefreshPolicy } from './companyintel-refresh.js';
import { localizeOfficer, sanitizeOfficers } from './companyintel-i18n.js';
import {
  mergeNewsIntoChain, finalizeIndustryChain, mergeEnrichedChain, layoutPeersIntoGrid, ensureDownstreamBuyers,
} from './companyintel-chain.js';

const ENRICH_SCHEMA = `{
  "profileZh": {
    "description": "80-220字繁體中文公司簡介",
    "businessModel": "一句話商業模式"
  },
  "industryChain": {
    "upstream": [{ "label": "環節名稱", "entities": ["供應商公司名或代號"], "note": "15字內；標 10-K、新聞、AI" }],
    "downstream": [{ "label": "客戶類型", "entities": ["購買標的公司產品／服務的公司名或代號"], "note": "15字內；說明為何是客戶" }],
    "peers": ["同業代號大寫；台股如2330.TW"]
  },
  "managementBrief": [
    { "date": "YYYY-MM-DD", "headline": "標題", "summary": "2-3句繁中", "impact": "positive|neutral|negative", "source": "來源名" }
  ],
  "newsHighlights": [
    { "region": "tw|global", "titleZh": "繁中標題", "summaryZh": "一句摘要", "url": "原文連結", "publisher": "媒體" }
  ]
}`;

function heuristicChain(symbol, bundle, profile = {}) {
  const hints = bundle.hints || {};
  const ext = bundle.profileExt || {};
  const industry = `${ext.industry || ''} ${ext.sector || profile.industry || ''}`.toLowerCase();
  const upstream = (hints.suppliers || []).slice(0, 12).map(s => ({ label: '供應商', entities: [s], note: '10-K' }));
  const downstream = (hints.customers || []).slice(0, 12).map(s => ({ label: '購買方（10-K）', entities: [s], note: 'SEC 10-K' }));
  const peers = [...new Set([...(ext.peers || []), ...(hints.competitors || [])])].filter(p => p !== symbol).slice(0, 10);
  if (!upstream.length) {
    if (/semiconductor|chip/i.test(industry)) {
      upstream.push(
        { label: 'EDA／IP', entities: ['Synopsys', 'Cadence'], note: '' },
        { label: '晶圓代工', entities: ['TSMC', 'Samsung'], note: '' },
        { label: '封裝測試', entities: ['ASE', 'Amkor'], note: '' },
      );
    }
  }
  if (!downstream.length && !/semiconductor|chip/i.test(industry)) {
    /* 非半導體不填泛稱下游 */
  }
  let chain = {
    upstream: upstream.length ? upstream : [{ label: '上游供應', entities: ['原物料／設備／服務商'], note: '待查證' }],
    downstream: downstream.length ? downstream : [{ label: '下游客戶', entities: ['待查證'], note: '按強制更新由 AI 整理' }],
    peers,
  };
  const news = [...(bundle.newsTw || []), ...(bundle.newsGlobal || [])];
  chain = mergeNewsIntoChain(chain, news, symbol);
  return ensureDownstreamBuyers(finalizeIndustryChain(chain, symbol), symbol, profile);
}

function fallbackManagementBrief(bundle) {
  return (bundle.managementNewsRaw || []).slice(0, 6).map(n => ({
    date: n.created || null,
    headline: n.titleZh || n.title || '',
    summary: (n.descriptionZh || n.description || '').slice(0, 180),
    impact: 'neutral',
    source: n.publisher || n.source || '',
    url: n.url || null,
  }));
}

function normalizeEnriched(parsed, symbol, bundle, profile) {
  const chain = parsed?.industryChain || heuristicChain(symbol, bundle, profile);
  const upDetail = (chain.upstream || []).some(g => g?.entities)
    ? chain.upstream
    : (chain.upstreamDetail || []);
  const downDetail = (chain.downstream || []).some(g => g?.entities)
    ? chain.downstream
    : (chain.downstreamDetail || []);
  const flatUpstream = upDetail.flatMap(u => (u.entities || []).map(e => String(typeof e === 'object' ? e.name : e)));
  const flatDownstream = downDetail.flatMap(d => (d.entities || []).map(e => String(typeof e === 'object' ? e.name : e)));
  const mgmt = (parsed?.managementBrief || []).length ? parsed.managementBrief : fallbackManagementBrief(bundle);
  return {
    profileZh: parsed?.profileZh || {
      description: bundle.profileExt?.longBusinessSummary?.slice(0, 400) || bundle.hints?.excerpt?.slice(0, 400) || '',
      businessModel: bundle.profileExt?.industry || '',
    },
    industryChain: finalizeIndustryChain({
      upstream: flatUpstream.slice(0, 12),
      downstream: flatDownstream.slice(0, 12),
      peers: (chain.peers || []).map(s => String(s).toUpperCase()).filter(Boolean).slice(0, 12),
      upstreamFlat: flatUpstream.slice(0, 12),
      downstreamFlat: flatDownstream.slice(0, 12),
      upstreamDetail: upDetail,
      downstreamDetail: downDetail,
    }, symbol),
    managementBrief: mgmt.slice(0, 8).map(m => ({
      date: m.date || null,
      headline: m.headline || '',
      summary: m.summary || '',
      impact: m.impact || 'neutral',
      source: m.source || '',
      url: m.url || null,
    })),
    newsHighlights: (parsed?.newsHighlights || []).slice(0, 16),
    enrichedAt: new Date().toISOString(),
    aiUsed: !!parsed?._aiUsed,
    provider: parsed?._provider || null,
  };
}

function buildForceEnrichPrompt(symbol, profile = {}) {
  const name = profile.name || profile.companyName || symbol;
  const industry = profile.industry || profile.sector || '';
  return [
    `【強制更新】標的：${symbol}（${name}）${industry ? `，產業：${industry}` : ''}`,
    '請依固定 JSON 結構輸出（不要 midstream；頁面只顯示上游、下游兩欄）。',
    `upstream：2～5 組供應商；每組 entities 為 2～6 個具體公司名或股票代號（美股 1-5 字大寫；台股 2330.TW）。`,
    `downstream：2～4 組「誰購買 ${symbol} 的產品或服務」；必須具名客戶（公司名或代號），禁止只寫終端客戶、企業客戶、通路等泛稱；優先採用 10-K customers 與新聞中的買方。`,
    /NVDA|AMD/i.test(symbol)
      ? 'GPU 範例下游：DELL、HPE、SMCI（AI 伺服器 OEM，採購 GPU 組裝再銷售）、MSFT、AMZN、GOOGL、META（雲端部署）；同業 AMD 放 peers 勿放 downstream。'
      : null,
    'peers：3～8 個同業代號。',
    '每個 downstream 的 note 用 15 字內說明客戶與標的公司的關係（如雲端採購 GPU、OEM 採購晶片）。',
    '資料僅能來自提供的原始摘要；沒有依據則該組 entities 填「待查證」。',
  ].join('\n');
}

export async function enrichWithAI(symbol, bundle, profile = {}, { force = false } = {}) {
  const compact = {
    symbol,
    sector: bundle.profileExt?.sector,
    industry: bundle.profileExt?.industry,
    summary: bundle.profileExt?.longBusinessSummary?.slice(0, 1200),
    tenK: {
      excerpt: bundle.hints?.excerpt?.slice(0, 1500),
      customers: bundle.hints?.customers,
      suppliers: bundle.hints?.suppliers,
      competitors: bundle.hints?.competitors,
    },
    headlines8k: (bundle.headlines8k || []).slice(0, 6),
    managementNews: (bundle.managementNewsRaw || []).slice(0, 8).map(n => ({
      title: n.title, publisher: n.publisher, created: n.created, url: n.url,
    })),
    newsTw: (bundle.newsTw || []).slice(0, 10).map(n => ({
      title: n.title, publisher: n.publisher, url: n.url,
      summary: (n.description || n.descriptionZh || '').slice(0, 200),
    })),
    newsGlobal: (bundle.newsGlobal || []).slice(0, 10).map(n => ({
      title: n.title, publisher: n.publisher, url: n.url,
      summary: (n.description || n.descriptionZh || '').slice(0, 200),
    })),
  };

  const system = force
    ? [
      '你是股票研究資料編輯。只輸出一段合法 JSON，不要 markdown，不要解釋。',
      '產業鏈僅 upstream（供應商）與 downstream（購買標的公司產品／服務的客戶），不要 midstream。',
      'downstream 是本次重點：具名買方公司或代號，結構穩定以利網頁兩欄顯示。',
      'managementBrief 3-6 則；newsHighlights 6-10 則，region 為 tw 或 global。',
    ].join('\n')
    : [
      '你是股票研究資料編輯。只輸出一段合法 JSON，不要 markdown，不要解釋。',
      '資料來自公開來源摘要，不可捏造未出現的公司名；不確定處用「待查證」。',
      'upstream＝供應商；downstream＝購買標的公司產品／服務的客戶；不可只寫泛稱。',
      '不要輸出 midstream。entities 盡量用可交易代號；note 標 10-K、新聞、AI。',
      'managementBrief 只收經營層、治理、策略、併購、指引相關 3-6 則。',
      'newsHighlights 從新聞挑選 6-10 則，region 為 tw 或 global。',
    ].join('\n');

  const task = force ? buildForceEnrichPrompt(symbol, { ...profile, ...bundle.profileExt }) : `股票代號 ${symbol}。請整理產業鏈與新聞。`;
  const user = `${task}\n\nJSON 結構：\n${ENRICH_SCHEMA}\n\n原始資料：\n${JSON.stringify(compact, null, 2)}`;

  const ai = await callAI({ system, user, temperature: 0.1 });
  if (!ai.ok) {
    return { data: normalizeEnriched(null, symbol, bundle, profile), aiError: ai.error };
  }
  const parsed = extractJSONObject(ai.text);
  if (!parsed) {
    return { data: normalizeEnriched(null, symbol, bundle, profile), aiError: 'json_parse_failed' };
  }
  parsed._aiUsed = true;
  parsed._provider = ai.providerId;
  return { data: normalizeEnriched(parsed, symbol, bundle, profile), aiError: null };
}

export async function syncCompanyIntelEnriched(symbol, profile = {}, { force = false, useAI = true, management = null } = {}) {
  symbol = String(symbol || '').trim().toUpperCase();
  const existing = getCompanyIntelEnriched(symbol);
  const gate = shouldRunIntelSync(existing, { force });
  if (!gate.run) {
    return {
      symbol,
      skipped: true,
      enriched: existing?.data,
      sources: existing?.sources || [],
      skipReason: gate.skipReason,
      nextRefreshAfter: gate.nextRefreshAfter,
    };
  }

  const { gatherIntelSources } = await import('./companyintel-sources.js');
  const bundle = await gatherIntelSources(symbol, profile);
  const sources = ['Yahoo', 'SEC 10-K', 'Google 新聞 TW', 'Google 新聞 EN', 'Nasdaq', 'Yahoo Finance'];

  let enriched;
  let aiError = null;
  if (useAI) {
    const r = await enrichWithAI(symbol, bundle, profile, { force });
    enriched = r.data;
    aiError = r.aiError;
    if (aiError) sources.push(`AI 略過（${aiError}）`);
    else sources.push(`AI ${enriched.provider || 'active'}`);
  } else {
    enriched = normalizeEnriched(null, symbol, bundle, profile);
  }

  const pub = await computeNextPublicRefresh(symbol);
  enriched.rawBundleAt = bundle.gatheredAt;
  enriched.sources = sources;
  enriched.enrichedAt = new Date().toISOString();
  enriched.lastSyncAt = Date.now();
  enriched.chainLayout = 'upstream_downstream_v2';
  if (force) enriched.forceRefreshAt = enriched.enrichedAt;
  enriched.nextRefreshAfter = pub.nextRefreshAfter;
  enriched.nextPublicLabel = pub.nextPublicLabel;
  enriched.nextPublicDate = pub.nextPublicDate;
  if (management?.officers?.length) {
    enriched.officers = management.officers;
    enriched.managementSource = management.source || null;
  }
  const newsAll = [...(bundle.newsTw || []), ...(bundle.newsGlobal || [])];
  enriched.industryChain = ensureDownstreamBuyers(
    layoutPeersIntoGrid(
      mergeNewsIntoChain(
        finalizeIndustryChain(enriched.industryChain || {}, symbol),
        newsAll,
        symbol,
      ),
      symbol,
    ),
    symbol,
    profile,
  );
  saveCompanyIntelEnriched(symbol, enriched, sources);
  return {
    symbol, skipped: false, enriched, bundle, sources, aiError,
    nextRefreshAfter: pub.nextRefreshAfter,
    nextPublicLabel: pub.nextPublicLabel,
  };
}

export function applyEnrichedToIntel(intel, enriched) {
  if (!enriched) return intel;
  const chain = enriched.industryChain || {};
  const newsTw = (intel.newsTw || []).length ? intel.newsTw : (intel.news || []).filter(n => n.region === 'tw');
  const newsGlobal = (intel.newsGlobal || []).length ? intel.newsGlobal : (intel.news || []).filter(n => n.region === 'global');

  const highlights = enriched.newsHighlights || [];
  const hlTw = highlights.filter(h => h.region === 'tw').map(h => ({
    title: h.titleZh, titleZh: h.titleZh, descriptionZh: h.summaryZh, description: h.summaryZh,
    url: h.url, publisher: h.publisher, region: 'tw', source: 'AI 精選',
  }));
  const hlGl = highlights.filter(h => h.region === 'global').map(h => ({
    title: h.titleZh, titleZh: h.titleZh, descriptionZh: h.summaryZh, description: h.summaryZh,
    url: h.url, publisher: h.publisher, region: 'global', source: 'AI 精選',
  }));

  return {
    ...intel,
    profileZh: enriched.profileZh || intel.profileZh,
    industryChain: ensureDownstreamBuyers(
      mergeNewsIntoChain(
        mergeEnrichedChain(intel.industryChain, enriched.industryChain, intel.symbol),
        [...newsTw, ...newsGlobal],
        intel.symbol,
      ),
      intel.symbol,
      intel.profile || {},
    ),
    managementBrief: enriched.managementBrief || [],
    management: (() => {
      const off = sanitizeOfficers(enriched.officers);
      if (!off.length) return intel.management;
      return {
        ...(intel.management || {}),
        officers: off.map(localizeOfficer),
        source: enriched.managementSource || intel.management?.source,
      };
    })(),
    newsTw: [...hlTw, ...newsTw].slice(0, 14),
    newsGlobal: [...hlGl, ...newsGlobal].slice(0, 14),
    news: [...newsTw, ...newsGlobal].slice(0, 20),
    enrichedAt: enriched.enrichedAt || (enriched.lastSyncAt ? new Date(enriched.lastSyncAt).toISOString() : null),
    enrichSources: enriched.sources || [],
    aiEnriched: !!enriched.aiUsed,
    chainLayout: enriched.chainLayout || 'upstream_downstream_v2',
    nextRefreshAfter: enriched.nextRefreshAfter || null,
    nextPublicLabel: enriched.nextPublicLabel || null,
    needsSync: false,
  };
}

export function attachIntelSyncStatus(intel, symbol) {
  const row = getCompanyIntelEnriched(symbol);
  const gate = intelRefreshPolicy(row);
  return {
    ...intel,
    needsSync: gate.needsSync,
    nextRefreshAfter: gate.nextRefreshAfter || intel.nextRefreshAfter,
    nextPublicLabel: gate.nextPublicLabel || intel.nextPublicLabel,
    syncSkipReason: gate.skipReason,
    lastSyncAt: gate.lastSyncAt || intel.enrichedAt,
  };
}

