import { formatGoaPayload } from '@/lib/goa-architect';
import {
  executeGoaPayload,
  fetchAstMetadataTree,
  formatExecutionResults,
  revisePayloadOnCompilerError,
} from '@/lib/goa-executor';
import { buildGoaPayloadWithPlanner } from '@/lib/goa-planner';
import { resolveTemplateIdFromPrompt } from '@/lib/template-catalog';
import { isValidProjectRoot } from '@/lib/tauri-bridge';
import { templateMatch } from '@/lib/vigthoria-services';
import type { GoaExecutionPayload } from '@/types/goa-orchestrator';

export interface GoaPipelineContext {
  hyperloopUrl: string;
  templateUrl: string;
  token: string | null;
  workspaceRoot: string;
  userPrompt: string;
}

export interface GoaPipelineResult {
  payload: GoaExecutionPayload;
  payloadJson: string;
  results: Awaited<ReturnType<typeof executeGoaPayload>>;
  summary: string;
  executed: boolean;
}

export interface GoaPipelineOptions {
  execute: boolean;
}

const GOA_ROUTE_SIGNAL =
  /\b(template|landing|auth|login|signup|dashboard|api docs|stripe|checkout|billing|fix|repair|bug|error|refactor|hook|middleware|express|next\.js|vite|build|create|scaffold|inject)\b/i;

export function shouldAutoRouteGoa(prompt: string): boolean {
  const trimmed = prompt.trim();
  if (trimmed.length < 12) return false;
  if (trimmed.startsWith('@vigthoria-goa:')) return false;
  return GOA_ROUTE_SIGNAL.test(trimmed) || resolveTemplateIdFromPrompt(trimmed) !== null;
}

/** Architect-only planning. This function never writes to the workspace. */
export async function planGoaPipeline(
  ctx: GoaPipelineContext,
): Promise<Pick<GoaPipelineResult, 'payload' | 'payloadJson'>> {
  const isExisting = await isValidProjectRoot(ctx.workspaceRoot);

  let templateMatchMeta: { id: string; category: string; confidence: number } | null = null;
  if (!isExisting || /\b(template|landing|new|create)\b/i.test(ctx.userPrompt)) {
    const tm = await templateMatch(ctx.templateUrl, ctx.token, ctx.userPrompt);
    const tpl = tm.template as { id?: string; category?: string } | undefined;
    if (tpl?.id) {
      templateMatchMeta = {
        id: tpl.id,
        category: tpl.category || '',
        confidence: typeof tm.confidence === 'number' ? tm.confidence : 0,
      };
    }
  }

  let astMetadata: Record<string, unknown> | null = null;
  if (isExisting && ctx.token) {
    astMetadata = await fetchAstMetadataTree({
      hyperloopUrl: ctx.hyperloopUrl,
      token: ctx.token,
      workspaceRoot: ctx.workspaceRoot,
      userPrompt: ctx.userPrompt,
    });
  }

  const payload = await buildGoaPayloadWithPlanner(
    {
      userPrompt: ctx.userPrompt,
      workspaceRoot: ctx.workspaceRoot,
      isExistingProject: isExisting,
      astMetadata,
      templateMatch: templateMatchMeta,
    },
    ctx.hyperloopUrl,
    ctx.token,
  );

  return {
    payload,
    payloadJson: formatGoaPayload(payload),
  };
}

/** Architect → optional approved execute → stabilize pipeline. */
export async function runGoaPipeline(
  ctx: GoaPipelineContext,
  options: GoaPipelineOptions,
): Promise<GoaPipelineResult> {
  let { payload, payloadJson } = await planGoaPipeline(ctx);

  if (!options.execute) {
    return {
      payload,
      payloadJson,
      results: [],
      summary: `Plan ready: ${payload.workspace_type} · ${payload.instructions.length} instruction(s). No files changed.`,
      executed: false,
    };
  }

  let results = await executeGoaPayload(payload, ctx);

  for (let attempt = 0; attempt < 3; attempt += 1) {
    const failed = results.find((r) => !r.success && r.layer === 'stabilization');
    if (!failed?.error || !ctx.token) break;
    const revised = await revisePayloadOnCompilerError(payload, failed.error, ctx);
    if (!revised) break;
    payload = revised;
    payloadJson = formatGoaPayload(revised);
    results = await executeGoaPayload(revised, ctx);
  }

  const summary = formatExecutionResults(results);
  return {
    payload,
    payloadJson,
    results,
    summary,
    executed: results.some((r) => r.success),
  };
}

/** Prefix injected into Main Agent terminal so deck/CLI can read GOA context. */
export function buildGoaAgentInjection(result: GoaPipelineResult): string {
  const compact = {
    workspace_type: result.payload.workspace_type,
    analysis: result.payload.analysis,
    instruction_count: result.payload.instructions.length,
    executed: result.executed,
  };
  return `@vigthoria-goa:${JSON.stringify(compact)}`;
}
