import type { AgentConfig } from "./config.js";
import { analyzeTrends, type TrendDecision } from "./providers/model.js";
import { getTrends, researchTrends, type TrendResearch } from "./providers/xapi.js";

export type PolicyDecision = TrendDecision & {
  eligible: boolean;
  blockedReasons: string[];
  buybackEligible: boolean;
  buybackBlockedReasons: string[];
};

export type ScanResult = {
  observedAt: string;
  decisions: PolicyDecision[];
};

const addressAppearsInResearch = (research: TrendResearch[], address: string) =>
  research.some((candidate) => JSON.stringify(candidate.searchResponse).toLowerCase().includes(address.toLowerCase()));

export const applyDecisionPolicy = (
  config: Pick<AgentConfig, "minLaunchScore" | "minBuybackScore" | "aggressiveLaunchMode">,
  research: TrendResearch[],
  decisions: TrendDecision[],
): PolicyDecision[] => decisions.map((decision) => {
  const candidate = research.find((item) => item.name.toLowerCase() === decision.topic.toLowerCase());
  const aggressive = config.aggressiveLaunchMode;
  const blockedReasons = [
    ...(decision.score < config.minLaunchScore ? [`score below ${config.minLaunchScore}`] : []),
    ...(!aggressive && !decision.recommendLaunch ? ["model did not recommend launch"] : []),
    ...(aggressive
      ? decision.stage === "declining" ? [`topic stage is ${decision.stage}`] : []
      : decision.stage !== "emerging" && decision.stage !== "rising" ? [`topic stage is ${decision.stage}`] : []),
    ...(aggressive
      ? decision.manipulationRisk === "high" ? [`manipulation risk is ${decision.manipulationRisk}`] : []
      : decision.manipulationRisk !== "low" ? [`manipulation risk is ${decision.manipulationRisk}`] : []),
    ...(aggressive
      ? decision.legalRisk === "high" ? [`legal risk is ${decision.legalRisk}`] : []
      : decision.legalRisk !== "low" ? [`legal risk is ${decision.legalRisk}`] : []),
    ...(!decision.token ? ["no token specification"] : []),
    ...(!candidate ? ["topic was not present in the X research candidates"] : []),
  ];
  const buybackBlockedReasons = decision.buybackTarget
    ? [
      ...(decision.buybackTarget.confidence < config.minBuybackScore ? [`buyback confidence below ${config.minBuybackScore}`] : []),
      ...(!addressAppearsInResearch(research, decision.buybackTarget.address) ? ["buyback address was not present in X research data"] : []),
    ]
    : ["model returned no buyback target"];

  return {
    ...decision,
    eligible: blockedReasons.length === 0,
    blockedReasons,
    buybackEligible: buybackBlockedReasons.length === 0,
    buybackBlockedReasons,
  };
});

export const scanOnce = async (config: AgentConfig): Promise<ScanResult> => {
  const trends = await getTrends(config);
  if (trends.length === 0) throw new Error("xAPI returned no recognizable trends");
  const research = await researchTrends(config, trends);
  const decisions = await analyzeTrends(config, research);
  return { observedAt: new Date().toISOString(), decisions: applyDecisionPolicy(config, research, decisions) };
};
