// ═══════════════════════════════════════════════════════════
// Pipeline Tools: status, advance, create, search
// ═══════════════════════════════════════════════════════════

import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { z } from "zod";
import * as api from "../api-client.js";
import type { Pipeline, Priority, PipelineStatus } from "../types.js";

const STAGE_ORDER = [
  "intake",
  "scaffolding",
  "building",
  "testing",
  "review",
  "staging",
  "production",
  "published",
] as const;

function stageProgress(stage: string): number {
  const idx = STAGE_ORDER.indexOf(stage as (typeof STAGE_ORDER)[number]);
  return idx >= 0 ? Math.round(((idx + 1) / STAGE_ORDER.length) * 100) : 0;
}

const priorityEmoji: Record<Priority, string> = {
  critical: "🔴",
  high: "🟡",
  medium: "🔵",
  low: "⚪",
};

const statusEmoji: Record<PipelineStatus, string> = {
  active: "▶️",
  paused: "⏸️",
  completed: "✅",
  failed: "❌",
  archived: "📦",
};

function formatPipeline(p: Pipeline, detailed: boolean): string {
  const progress = stageProgress(p.currentStage);
  const bar = "█".repeat(Math.floor(progress / 10)) + "░".repeat(10 - Math.floor(progress / 10));

  let out = `${statusEmoji[p.status]} **${p.name}** (${p.platform})`;
  out += `\n   ID: ${p.id}`;
  out += `\n   Stage: ${p.currentStage} [${bar}] ${progress}%`;
  out += `\n   Priority: ${priorityEmoji[p.priority]} ${p.priority}`;
  out += `\n   Status: ${p.status}`;
  if (p.slaDeadline) {
    out += `\n   SLA: ${new Date(p.slaDeadline).toLocaleString()}`;
  }
  if (p.assigneeId) out += `\n   Assignee: ${p.assigneeId}`;

  if (detailed) {
    out += `\n   Template: ${p.template}`;
    out += `\n   Created: ${new Date(p.createdAt).toLocaleString()}`;
    out += `\n   Updated: ${new Date(p.updatedAt).toLocaleString()}`;
    if (p.completedAt) {
      out += `\n   Completed: ${new Date(p.completedAt).toLocaleString()}`;
    }
  }

  return out;
}

export function registerPipelineTools(server: McpServer): void {
  // ───────────────────────────────────────
  // factory_get_pipeline_status
  // ───────────────────────────────────────
  server.tool(
    "factory_get_pipeline_status",
    "Get current state of all pipelines or a specific pipeline. " +
      "Shows stage, progress, blockers, and timeline.",
    {
      pipeline_id: z
        .string()
        .uuid()
        .optional()
        .describe("Specific pipeline UUID. Omit for all active pipelines."),
      status: z
        .enum(["active", "paused", "completed", "failed", "all"])
        .default("active")
        .describe("Filter by status. Default: active"),
      include_details: z
        .boolean()
        .default(false)
        .describe("Include tasks, assets, and stage history. Default: false"),
    },
    async ({ pipeline_id, status, include_details }) => {
      try {
        if (pipeline_id) {
          const pipeline = await api.getPipeline(pipeline_id);
          let response = formatPipeline(pipeline, true);

          if (include_details) {
            try {
              const stages = await api.getPipelineStages(pipeline_id);
              response += `\n\n   📋 Stage History:`;
              for (const s of stages) {
                const emoji =
                  s.status === "completed"
                    ? "✅"
                    : s.status === "active"
                      ? "🔄"
                      : s.status === "failed"
                        ? "❌"
                        : "⏳";
                response += `\n     ${emoji} ${s.stageName} — ${s.status}`;
                if (s.requiresApproval) response += " ★";
                if (s.durationSeconds) response += ` (${Math.round(s.durationSeconds / 60)}min)`;
              }
            } catch {
              // stage data unavailable
            }

            try {
              const tasks = await api.listTasks({ pipelineId: pipeline_id, limit: 10 });
              if (tasks.length > 0) {
                response += `\n\n   📥 Tasks (${tasks.length}):`;
                for (const t of tasks) {
                  response += `\n     ${priorityEmoji[t.priority]} ${t.title} [${t.status}]`;
                }
              }
            } catch {
              // task data unavailable
            }
          }

          return {
            content: [{ type: "text" as const, text: response }],
          };
        }

        // List all pipelines
        const pipelines = await api.listPipelines({
          status: status === "all" ? undefined : (status as PipelineStatus),
          sort: "-priority",
        });

        if (pipelines.length === 0) {
          return {
            content: [
              {
                type: "text" as const,
                text: `No ${status === "all" ? "" : status + " "}pipelines found.`,
              },
            ],
          };
        }

        const byStage: Record<string, Pipeline[]> = {};
        for (const p of pipelines) {
          if (!byStage[p.currentStage]) byStage[p.currentStage] = [];
          byStage[p.currentStage].push(p);
        }

        let response = `📊 **Pipeline Status** (${pipelines.length} ${status === "all" ? "total" : status})`;
        response += "\n" + "─".repeat(60);

        for (const stage of STAGE_ORDER) {
          const ps = byStage[stage];
          if (!ps) continue;
          response += `\n\n**${stage.toUpperCase()}** (${ps.length})`;
          for (const p of ps) {
            response += `\n${formatPipeline(p, include_details)}`;
          }
        }

        return {
          content: [{ type: "text" as const, text: response }],
        };
      } catch (err) {
        const msg = err instanceof Error ? err.message : String(err);
        return {
          content: [{ type: "text" as const, text: `❌ Error fetching pipeline status: ${msg}` }],
          isError: true,
        };
      }
    },
  );

  // ───────────────────────────────────────
  // factory_advance_stage
  // ───────────────────────────────────────
  server.tool(
    "factory_advance_stage",
    "Manually advance a pipeline to its next stage. Triggers validation checks. " +
      "If validation fails, returns the failures instead of advancing.",
    {
      pipeline_id: z.string().uuid().describe("UUID of the pipeline to advance"),
      target_stage: z
        .enum(["intake", "scaffolding", "building", "testing", "review", "staging", "production", "published"])
        .optional()
        .describe("Target stage. Default: next in sequence"),
      skip_validation: z
        .boolean()
        .default(false)
        .describe("Skip gate checks. Admin/owner only. Default: false"),
      notes: z.string().optional().describe("Notes for the stage transition"),
    },
    async ({ pipeline_id, target_stage, skip_validation, notes }) => {
      try {
        const result = await api.advanceStage(pipeline_id, {
          targetStage: target_stage,
          skipValidation: skip_validation,
          notes,
        });

        let response = `🔄 **Stage Advanced**`;
        response += `\n   New Stage: ${result.stage.stageName}`;
        response += `\n   Status: ${result.stage.status}`;
        if (notes) response += `\n   Notes: ${notes}`;

        if (result.tasksCreated.length > 0) {
          response += `\n\n   📥 ${result.tasksCreated.length} new task(s) created:`;
          for (const t of result.tasksCreated) {
            response += `\n     • ${t.title} [${t.priority}]`;
          }
        }

        return {
          content: [{ type: "text" as const, text: response }],
        };
      } catch (err) {
        const msg = err instanceof Error ? err.message : String(err);
        return {
          content: [{ type: "text" as const, text: `❌ Error advancing stage: ${msg}` }],
          isError: true,
        };
      }
    },
  );

  // ───────────────────────────────────────
  // factory_create_pipeline
  // ───────────────────────────────────────
  server.tool(
    "factory_create_pipeline",
    "Initialize a new MCP server pipeline from a template.",
    {
      name: z.string().min(1).describe("Pipeline name (e.g., 'ghl-mcp-server')"),
      platform: z.string().min(1).describe("Target platform (e.g., 'go-high-level', 'shopify')"),
      template: z
        .enum(["mcp-server-standard", "mcp-server-minimal", "mcp-server-enterprise"])
        .default("mcp-server-standard")
        .describe("Pipeline template. Default: mcp-server-standard"),
      priority: z
        .enum(["critical", "high", "medium", "low"])
        .default("medium")
        .describe("Initial priority. Default: medium"),
    },
    async ({ name, platform, template, priority }) => {
      try {
        const pipeline = await api.createPipeline({
          name,
          platform,
          template,
          priority: priority as Priority,
        });

        let response = `🆕 **Pipeline Created**`;
        response += `\n${formatPipeline(pipeline, true)}`;
        response += `\n\n   The pipeline starts at the "intake" stage and will auto-advance through scaffolding.`;

        return {
          content: [{ type: "text" as const, text: response }],
        };
      } catch (err) {
        const msg = err instanceof Error ? err.message : String(err);
        return {
          content: [{ type: "text" as const, text: `❌ Error creating pipeline: ${msg}` }],
          isError: true,
        };
      }
    },
  );

  // ───────────────────────────────────────
  // factory_search
  // ───────────────────────────────────────
  server.tool(
    "factory_search",
    "Search across pipelines, tasks, assets, and audit logs.",
    {
      query: z.string().min(1).describe("Search query text"),
      entity_types: z
        .array(z.enum(["pipeline", "task", "asset", "audit"]))
        .optional()
        .describe("Which entity types to search. Default: all"),
      limit: z.number().min(1).max(50).default(10).describe("Max results. Default: 10"),
    },
    async ({ query, entity_types, limit }) => {
      try {
        const results = await api.search(query, entity_types, limit);

        const total =
          results.pipelines.length +
          results.tasks.length +
          results.assets.length +
          results.auditEntries.length;

        if (total === 0) {
          return {
            content: [
              {
                type: "text" as const,
                text: `🔍 No results found for "${query}".`,
              },
            ],
          };
        }

        let response = `🔍 **Search Results for "${query}"** (${total} matches)`;
        response += "\n" + "─".repeat(60);

        if (results.pipelines.length > 0) {
          response += `\n\n**Pipelines (${results.pipelines.length})**`;
          for (const p of results.pipelines) {
            response += `\n  ${statusEmoji[p.status]} ${p.name} — ${p.currentStage} [${p.priority}]`;
          }
        }

        if (results.tasks.length > 0) {
          response += `\n\n**Tasks (${results.tasks.length})**`;
          for (const t of results.tasks) {
            response += `\n  ${priorityEmoji[t.priority]} ${t.title} [${t.status}]`;
          }
        }

        if (results.auditEntries.length > 0) {
          response += `\n\n**Audit Log (${results.auditEntries.length})**`;
          for (const a of results.auditEntries) {
            response += `\n  ${a.action} on ${a.entityType}:${a.entityId}`;
          }
        }

        return {
          content: [{ type: "text" as const, text: response }],
        };
      } catch (err) {
        const msg = err instanceof Error ? err.message : String(err);
        return {
          content: [{ type: "text" as const, text: `❌ Error searching: ${msg}` }],
          isError: true,
        };
      }
    },
  );
}
