import type {
  IntelligenceServiceHandler,
  ServerContext,
  ListMarketImplicationsRequest,
  ListMarketImplicationsResponse,
  MarketImplicationCard,
} from '../../../../src/generated/server/worldmonitor/intelligence/v1/service_server';
import { getCachedJson } from '../../../_shared/redis';

const BASE_KEY = 'intelligence:market-implications:v1';
// Allowed framework IDs — prevents arbitrary Redis key injection
const ALLOWED_FRAMEWORK_IDS = new Set([
  'dalio-macro', 'buffett-value', 'pmesii-pt', 'doomsday-prepper',
]);

interface CachedTransmissionNode {
  node?: string;
  impact_type?: string;
  logic?: string;
}

interface CachedMarketImplication {
  ticker?: string;
  name?: string;
  direction?: string;
  timeframe?: string;
  confidence?: string;
  title?: string;
  narrative?: string;
  risk_caveat?: string;
  driver?: string;
  transmission_chain?: CachedTransmissionNode[];
}

interface CachedMarketImplicationsData {
  cards?: CachedMarketImplication[];
  generatedAt?: string;
}

function toCard(raw: CachedMarketImplication): MarketImplicationCard {
  return {
    ticker: raw.ticker ?? '',
    name: raw.name ?? '',
    direction: raw.direction ?? '',
    timeframe: raw.timeframe ?? '',
    confidence: raw.confidence ?? '',
    title: raw.title ?? '',
    narrative: raw.narrative ?? '',
    riskCaveat: raw.risk_caveat ?? '',
    driver: raw.driver ?? '',
    transmissionChain: Array.isArray(raw.transmission_chain)
      ? raw.transmission_chain.map(n => ({
          node: n.node ?? '',
          impactType: n.impact_type ?? '',
          logic: n.logic ?? '',
        }))
      : [],
  };
}

export const listMarketImplications: IntelligenceServiceHandler['listMarketImplications'] = async (
  _ctx: ServerContext,
  req: ListMarketImplicationsRequest,
): Promise<ListMarketImplicationsResponse> => {
  const fwId = req.frameworkId && ALLOWED_FRAMEWORK_IDS.has(req.frameworkId) ? req.frameworkId : null;
  const redisKey = fwId ? `${BASE_KEY}:${fwId}` : BASE_KEY;
  // If framework-specific key misses, fall back to default (generated by cron)
  const data = (await getCachedJson(redisKey, true).catch(() => null) ??
    (fwId ? await getCachedJson(BASE_KEY, true).catch(() => null) : null)) as CachedMarketImplicationsData | null;

  if (!data || !Array.isArray(data.cards) || data.cards.length === 0) {
    return {
      cards: [],
      degraded: true,
      emptyReason: data ? 'no_cards' : 'data_unavailable',
      generatedAt: '',
    };
  }

  return {
    cards: data.cards.map(toCard),
    degraded: false,
    emptyReason: '',
    generatedAt: data.generatedAt ?? '',
  };
};
