import * as fs from 'fs';

// Import DevTools trace engine and formatters from chrome-devtools-frontend
// We intentionally use deep imports to match the package structure.
// These modules are ESM and require NodeNext module resolution.
// Types are loosely typed to minimize coupling with DevTools internals.
import * as TraceEngine from 'chrome-devtools-frontend/front_end/models/trace/trace.js';
import { PerformanceTraceFormatter } from 'chrome-devtools-frontend/front_end/models/ai_assistance/data_formatters/PerformanceTraceFormatter.js';
import { PerformanceInsightFormatter } from 'chrome-devtools-frontend/front_end/models/ai_assistance/data_formatters/PerformanceInsightFormatter.js';
import { AgentFocus } from 'chrome-devtools-frontend/front_end/models/ai_assistance/performance/AIContext.js';

const engine = TraceEngine.TraceModel.Model.createWithAllHandlers();

function readJsonFile(path: string): any {
  const text = fs.readFileSync(path, 'utf-8');
  return JSON.parse(text);
}

export async function parseTrace(json: any): Promise<{
  parsedTrace: any;
  insights: any | null;
}> {
  engine.resetProcessor();
  const events = Array.isArray(json) ? json : json.traceEvents;
  if (!events || !Array.isArray(events)) {
    throw new Error('Invalid trace format: expected array or {traceEvents: []}');
  }
  await engine.parse(events);
  const parsedTrace = engine.parsedTrace();
  const insights = parsedTrace?.insights ?? null;
  if (!parsedTrace) throw new Error('No parsed trace returned by engine');
  return { parsedTrace, insights };
}

export function getTraceSummary(parsedTrace: any): string {
  const focus = AgentFocus.fromParsedTrace(parsedTrace);
  const formatter = new PerformanceTraceFormatter(focus);
  return formatter.formatTraceSummary();
}

export function getInsightText(parsedTrace: any, insights: any, insightName: string): string {
  if (!insights) throw new Error('No insights available for this trace');
  const mainNavId = parsedTrace.data?.Meta?.mainFrameNavigations?.at(0)?.args?.data?.navigationId;
  const NO_NAV = TraceEngine.Types.Events.NO_NAVIGATION;
  const set = insights.get(mainNavId ?? NO_NAV);
  if (!set) throw new Error('No insights for selected navigation');
  const model = set.model || {};
  if (!(insightName in model)) throw new Error(`Insight not found: ${insightName}`);
  const formatter = new PerformanceInsightFormatter(
    AgentFocus.fromParsedTrace(parsedTrace),
    model[insightName],
  );
  return formatter.formatInsight();
}

export async function analyzeTraceFile(
  filePath: string,
  insightName?: string,
): Promise<{
  summary: string;
  insight?: string;
}> {
  const json = readJsonFile(filePath);
  const { parsedTrace, insights } = await parseTrace(json);
  const summary = getTraceSummary(parsedTrace);
  if (insightName) {
    try {
      const insight = getInsightText(parsedTrace, insights, insightName);
      return { summary, insight };
    } catch {
      // If requested insight missing, still return summary
      return { summary };
    }
  }
  return { summary };
}

export default { analyzeTraceFile };
