import type { ExtensionAPI } from "@jaeswift/jae-coding-agent";
import { existsSync, readFileSync } from "node:fs";
import { join, basename } from "node:path";
import { Type } from "@sinclair/typebox";

type DeployTarget = "docker" | "vercel" | "rsync" | "static" | "unknown";

interface StackInfo {
  type: DeployTarget;
  runtime: string;
  entrypoint?: string;
}

export default function (pi: ExtensionAPI) {
  function detectStack(cwd: string): StackInfo {
    if (existsSync(join(cwd, "Dockerfile"))) {
      return { type: "docker", runtime: "Docker", entrypoint: "Dockerfile" };
    }
    if (existsSync(join(cwd, "docker-compose.yml"))) {
      return { type: "docker", runtime: "Docker Compose", entrypoint: "docker-compose.yml" };
    }
    if (existsSync(join(cwd, "vercel.json"))) {
      return { type: "vercel", runtime: "Vercel" };
    }
    if (existsSync(join(cwd, "package.json"))) {
      try {
        const pkg = JSON.parse(readFileSync(join(cwd, "package.json"), "utf-8"));
        const deps = { ...pkg.dependencies, ...pkg.devDependencies };
        if (deps["next"]) return { type: "vercel", runtime: "Next.js" };
        if (deps["vite"] || deps["react-scripts"]) return { type: "static", runtime: "SPA (Vite/CRA)" };
        if (pkg.scripts?.start) return { type: "docker", runtime: "Node.js" };
      } catch { /* ignore */ }
      return { type: "docker", runtime: "Node.js" };
    }
    if (existsSync(join(cwd, "requirements.txt")) || existsSync(join(cwd, "pyproject.toml"))) {
      return { type: "docker", runtime: "Python" };
    }
    if (existsSync(join(cwd, "index.html"))) {
      return { type: "static", runtime: "Static HTML" };
    }
    return { type: "unknown", runtime: "Unknown" };
  }

  pi.registerTool({
    name: "deploy",
    label: "Deploy Project",
    description: "Detect project stack and deploy. Supports Docker, Vercel, rsync, and static sites.",
    parameters: Type.Object({
      target: Type.Optional(Type.String({ description: "Deploy target: docker, vercel, rsync, static (auto-detected if omitted)" })),
      host: Type.Optional(Type.String({ description: "Remote host for rsync deploy (user@host:/path)" })),
      tag: Type.Optional(Type.String({ description: "Docker image tag" })),
    }),
    execute: async (args, ctx) => {
      const stack = detectStack(ctx.cwd);
      const deployType = (args.target as DeployTarget) || stack.type;

      if (deployType === "unknown") {
        return { error: "Could not detect project stack. Specify a target: docker, vercel, rsync, static" };
      }

      const results: string[] = [`Detected: ${stack.runtime}`, `Deploy target: ${deployType}`];

      if (deployType === "docker") {
        const tag = args.tag || basename(ctx.cwd).toLowerCase();
        const buildResult = await pi.exec("docker", ["build", "-t", tag, "."], { cwd: ctx.cwd });
        if (buildResult.code !== 0) {
          return { error: `Docker build failed: ${buildResult.stderr}` };
        }
        results.push(`Docker image built: ${tag}`);
        results.push(`Run with: docker run -d -p 3000:3000 ${tag}`);
      } else if (deployType === "vercel") {
        const vercelResult = await pi.exec("npx", ["vercel", "--yes"], { cwd: ctx.cwd });
        results.push(vercelResult.code === 0 ? `Vercel deployed: ${vercelResult.stdout.trim()}` : `Vercel error: ${vercelResult.stderr}`);
      } else if (deployType === "rsync") {
        if (!args.host) {
          return { error: "rsync deploy requires --host argument (user@host:/path)" };
        }
        const rsyncResult = await pi.exec(
          "rsync",
          ["-avz", "--exclude", "node_modules", "--exclude", ".git", "./", args.host],
          { cwd: ctx.cwd },
        );
        results.push(rsyncResult.code === 0 ? `Synced to ${args.host}` : `rsync error: ${rsyncResult.stderr}`);
      } else if (deployType === "static") {
        // Build if needed
        const pkgPath = join(ctx.cwd, "package.json");
        if (existsSync(pkgPath)) {
          const pkg = JSON.parse(readFileSync(pkgPath, "utf-8"));
          if (pkg.scripts?.build) {
            const buildResult = await pi.exec("npm", ["run", "build"], { cwd: ctx.cwd });
            results.push(buildResult.code === 0 ? "Build succeeded" : `Build error: ${buildResult.stderr}`);
          }
        }
        const distDir = existsSync(join(ctx.cwd, "dist")) ? "dist" : existsSync(join(ctx.cwd, "build")) ? "build" : ".";
        results.push(`Static files in: ${distDir}/`);
        results.push(`Serve locally: npx serve ${distDir}`);
        if (args.host) {
          const rsyncResult = await pi.exec("rsync", ["-avz", `${distDir}/`, args.host], { cwd: ctx.cwd });
          results.push(rsyncResult.code === 0 ? `Deployed to ${args.host}` : `rsync error: ${rsyncResult.stderr}`);
        }
      }

      return { output: results.join("\n") };
    },
  });

  pi.registerCommand("deploy", {
    description: "Deploy project: /deploy [docker|vercel|rsync|static] [--host user@host:/path] [--tag image-tag]",
    handler: async (args, ctx) => {
      const stack = detectStack(ctx.cwd);
      const parts = args.trim().split(/\s+/);
      const target = parts[0] || undefined;

      let host: string | undefined;
      let tag: string | undefined;
      for (let i = 0; i < parts.length; i++) {
        if (parts[i] === "--host" && parts[i + 1]) host = parts[i + 1];
        if (parts[i] === "--tag" && parts[i + 1]) tag = parts[i + 1];
      }

      if (!target) {
        ctx.ui.notify(
          `\u{1F680} Stack detected: ${stack.runtime} (${stack.type})\n\nUsage: /deploy [target] [options]\n  Targets: docker, vercel, rsync, static\n  Options: --host user@host:/path  --tag image-name`,
          "info",
        );
        return;
      }

      ctx.ui.notify(`\u{1F680} Deploying as ${target}...`, "info");
      // Delegate to the tool
      ctx.ui.notify(`Use the deploy tool for full deployment. Target: ${target}, Host: ${host || "none"}, Tag: ${tag || "auto"}`, "info");
    },
  });
}
