/**
 * Institutional Holders Service
 * Fetches top institutional holders, insider transactions using native fetch and crumb auth
 */

import NodeCache from 'node-cache';
import { yfFetchAuth } from './yahooCrumb.js';

const holdersCache = new NodeCache({ stdTTL: 3600 });
const insidersCache = new NodeCache({ stdTTL: 3600 });

const YF_BASE = 'https://query1.finance.yahoo.com';

/**
 * Fetch top institutional holders for a symbol
 */
export async function fetchInstitutionalHolders(symbol) {
  const cacheKey = `inst_${symbol}`;
  const cached = holdersCache.get(cacheKey);
  if (cached) return cached;

  const url = `${YF_BASE}/v10/finance/quoteSummary/${symbol}?modules=institutionOwnership,majorHoldersBreakdown`;

  try {
    const data = await yfFetchAuth(url);
    const result = data?.quoteSummary?.result?.[0];
    if (!result) return null;

    const io = result.institutionOwnership || {};
    const mhb = result.majorHoldersBreakdown || {};

    const holders = (io.ownershipList || []).map(h => ({
      name: h.organization ?? 'Unknown',
      pct_held: h.pctHeld?.raw ?? null,
      shares: h.position?.raw ?? null,
      value: h.value?.raw ?? null,
      date_reported: h.reportDate?.fmt ?? null,
      shares_change: h.change?.raw ?? null,
      pct_change: h.pctChange?.raw ?? null,
      direction: (h.change?.raw ?? 0) > 0 ? 'INCREASED' : (h.change?.raw ?? 0) < 0 ? 'DECREASED' : 'UNCHANGED',
    }));

    const summary = {
      pct_held_institutions: mhb.institutionsPercentHeld?.raw ?? null,
      pct_held_insiders: mhb.insidersPercentHeld?.raw ?? null,
      pct_float_institutions: mhb.institutionsFloatPercentHeld?.raw ?? null,
      institution_count: mhb.institutionsCount?.raw ?? null,
    };

    const parsedData = { holders, summary };
    holdersCache.set(cacheKey, parsedData);
    return parsedData;
  } catch (err) {
    console.warn(`[institutionalHolders] failed for ${symbol}:`, err.message);
    return null;
  }
}

/**
 * Fetch recent insider transactions
 */
export async function fetchInsiderTransactions(symbol) {
  const cacheKey = `insider_${symbol}`;
  const cached = insidersCache.get(cacheKey);
  if (cached) return cached;

  const url = `${YF_BASE}/v10/finance/quoteSummary/${symbol}?modules=insiderTransactions,insiderHolders`;

  try {
    const data = await yfFetchAuth(url);
    const result = data?.quoteSummary?.result?.[0];
    if (!result) return null;

    const it = result.insiderTransactions || {};
    const ih = result.insiderHolders || {};

    const transactions = (it.transactions || []).slice(0, 20).map(t => {
      const typeText = t.transactionText ?? '';
      const direction =
        /sale|sell/i.test(typeText) ? 'SELL' :
        /purchase|buy|acquisition/i.test(typeText) ? 'BUY' : 'OTHER';

      return {
        insider_name: t.filerName ?? 'Unknown',
        title: t.filerRelation ?? null,
        transaction_type: typeText,
        shares: t.shares?.raw ?? null,
        value: t.value?.raw ?? null,
        start_date: t.startDate?.fmt ?? null,
        ownership_type: t.ownership ?? null,
        direction,
      };
    });

    const now = Date.now();
    const ninetyDaysAgo = now - 90 * 24 * 60 * 60 * 1000;
    const recent = transactions.filter(t => t.start_date && new Date(t.start_date).getTime() > ninetyDaysAgo);
    const buyCount = recent.filter(t => t.direction === 'BUY').length;
    const sellCount = recent.filter(t => t.direction === 'SELL').length;

    const parsedData = {
      transactions,
      insider_summary: {
        buys_90d: buyCount,
        sells_90d: sellCount,
        net_sentiment: buyCount > sellCount ? 'BULLISH' : sellCount > buyCount ? 'BEARISH' : 'NEUTRAL',
      },
      holders: (ih.holders || []).slice(0, 10).map(h => ({
        name: h.name ?? 'Unknown',
        title: h.relation ?? null,
        shares: h.positionDirect?.raw ?? null,
        pct_total: h.pctHeld?.raw ?? null,
        latest_transaction: h.transactionDescription ?? null,
        latest_date: h.latestTransDate?.fmt ?? null,
      })),
    };

    insidersCache.set(cacheKey, parsedData);
    return parsedData;
  } catch (err) {
    console.warn(`[insiderTransactions] failed for ${symbol}:`, err.message);
    return null;
  }
}
