/**
 * RoutineQualityAgent — A2A pipeline for ChronoMind routine health checks.
 *
 * Agent roster (3 steps):
 *   1. RoutineInventoryAgent  — list all routines (templates + user routines)
 *   2. QualityCheckAgent      — flag routines exceeding duration limits or with zero completions
 *   3. QualityReportAgent     — assemble flagged routines with remediation suggestions
 *
 * MCP tools:
 *   chronomind.routines.checkQuality(maxDurationMinutes?) — run pipeline
 */

import { randomUUID } from 'node:crypto';
import { z } from 'zod';
import { registerTool } from '../tools/registry.js';
import type { McpToolRequest } from '../tools/types.js';
import { chronomindRoutinesList, type RoutineDoc } from '../../lib/chronomind-client.js';
import { config } from '../../lib/config.js';

// ── Types ──────────────────────────────────────────────────────────────────────

type QualityIssue = 'duration_overflow' | 'never_completed' | 'empty_steps' | 'no_category';

interface RoutineQualityResult {
  routineId: string;
  routineName: string;
  isTemplate: boolean;
  totalDurationMinutes: number;
  status: string;
  stepCount: number;
  issues: QualityIssue[];
  suggestions: string[];
  healthy: boolean;
}

export interface RoutineQualityReport {
  runId: string;
  productId: 'chronomind';
  maxDurationMinutes: number;
  totalRoutines: number;
  healthyCount: number;
  flaggedCount: number;
  perRoutine: RoutineQualityResult[];
  topIssues: Record<QualityIssue, number>;
  summary: string;
  generatedAt: string;
}

// ── Step 1: RoutineInventoryAgent ─────────────────────────────────────────────

async function inventoryRoutines(opts: {
  token?: string;
  requestId?: string;
}): Promise<RoutineDoc[]> {
  try {
    const result = await chronomindRoutinesList({ limit: config.QUERY_MAX_LIMIT }, opts);
    return result.items;
  } catch {
    return [];
  }
}

// ── Step 2: QualityCheckAgent ─────────────────────────────────────────────────

function checkRoutineQuality(
  routine: RoutineDoc,
  maxDurationMinutes: number
): RoutineQualityResult {
  const issues: QualityIssue[] = [];
  const suggestions: string[] = [];

  const stepCount = Array.isArray(routine.steps) ? routine.steps.length : 0;

  if (routine.totalDurationMinutes > maxDurationMinutes) {
    issues.push('duration_overflow');
    suggestions.push(
      `Duration ${routine.totalDurationMinutes}m exceeds max ${maxDurationMinutes}m. Split into sub-routines or shorten step durations.`
    );
  }

  if (routine.status !== 'completed' && !routine.isTemplate && stepCount > 0) {
    issues.push('never_completed');
    suggestions.push(
      'Routine has never reached completed status. Verify step durations and triggers are reachable.'
    );
  }

  if (stepCount === 0) {
    issues.push('empty_steps');
    suggestions.push('Routine has no steps defined. Add at least one step or delete this routine.');
  }

  if (!routine.category) {
    issues.push('no_category');
    suggestions.push('No category assigned. Categorizing improves searchability and filtering.');
  }

  return {
    routineId: routine.id,
    routineName: routine.name,
    isTemplate: routine.isTemplate,
    totalDurationMinutes: routine.totalDurationMinutes,
    status: routine.status,
    stepCount,
    issues,
    suggestions,
    healthy: issues.length === 0,
  };
}

// ── Step 3: QualityReportAgent ────────────────────────────────────────────────

function assembleQualityReport(
  runId: string,
  maxDurationMinutes: number,
  results: RoutineQualityResult[]
): RoutineQualityReport {
  const flaggedCount = results.filter(r => !r.healthy).length;
  const healthyCount = results.length - flaggedCount;

  const topIssues: Record<QualityIssue, number> = {
    duration_overflow: 0,
    never_completed: 0,
    empty_steps: 0,
    no_category: 0,
  };
  for (const result of results) {
    for (const issue of result.issues) {
      topIssues[issue]++;
    }
  }

  const summary =
    results.length === 0
      ? 'No routines found.'
      : flaggedCount === 0
        ? `All ${results.length} routines pass quality checks.`
        : `${flaggedCount}/${results.length} routines flagged. Top issues: ${Object.entries(
            topIssues
          )
            .filter(([, count]) => count > 0)
            .sort((a, b) => b[1] - a[1])
            .map(([issue, count]) => `${issue} (${count})`)
            .join(', ')}.`;

  return {
    runId,
    productId: 'chronomind',
    maxDurationMinutes,
    totalRoutines: results.length,
    healthyCount,
    flaggedCount,
    perRoutine: results,
    topIssues,
    summary,
    generatedAt: new Date().toISOString(),
  };
}

// ── Pipeline runner ────────────────────────────────────────────────────────────

async function runRoutineQualityPipeline(
  maxDurationMinutes: number,
  req: McpToolRequest
): Promise<RoutineQualityReport> {
  const runId = randomUUID();
  const opts = { token: req.headers.authorization?.slice(7), requestId: req.id };

  req.log.info({ runId, stepId: 'inventory' }, 'RoutineInventoryAgent start');
  const routines = await inventoryRoutines(opts);
  req.log.info(
    { runId, stepId: 'inventory', count: routines.length },
    'RoutineInventoryAgent done'
  );

  req.log.info(
    { runId, stepId: 'check', count: routines.length, maxDurationMinutes },
    'QualityCheckAgent start'
  );
  const results = routines.map(r => checkRoutineQuality(r, maxDurationMinutes));
  req.log.info(
    { runId, stepId: 'check', flagged: results.filter(r => !r.healthy).length },
    'QualityCheckAgent done'
  );

  req.log.info({ runId, stepId: 'report' }, 'QualityReportAgent start');
  const report = assembleQualityReport(runId, maxDurationMinutes, results);
  req.log.info({ runId, stepId: 'report', summary: report.summary }, 'QualityReportAgent done');

  return report;
}

// ── MCP tool registration ─────────────────────────────────────────────────────

registerTool({
  name: 'chronomind.routines.checkQuality',
  description:
    'A2A pipeline: scans all ChronoMind routines for quality issues — excessive duration, empty steps, never-completed non-template routines, and missing categories. Returns a per-routine health report with remediation suggestions. Requires admin role.',
  requiredRole: 'admin',
  inputSchema: z.object({
    maxDurationMinutes: z.coerce
      .number()
      .int()
      .min(1)
      .default(480)
      .describe(
        'Maximum allowed routine duration in minutes before flagging (default 480 = 8 hours)'
      ),
  }),
  async execute(args, req) {
    return runRoutineQualityPipeline(args.maxDurationMinutes, req);
  },
});
