/**
 * MCPEngine Studio — Deploy to MCPEngine (Cloudflare Workers)
 *
 * Phase 1: Simulates the Cloudflare Workers upload flow.
 * Compile → Package → "Upload" (writes to local output dir).
 * TODO: Real Wrangler API integration.
 */

import { promises as fs } from 'fs';
import path from 'path';
import type {
  ServerBundle,
  DeployConfig,
  DeployResult,
} from '@mcpengine/ai-pipeline/types';
import { compileWithMeta } from '../compiler';
import { generateWorkerScript } from '../worker-template';

// ---------------------------------------------------------------------------
// Types
// ---------------------------------------------------------------------------

export interface DeployProgress {
  step: string;
  message: string;
  percent: number;
  level: 'info' | 'success' | 'warning' | 'error';
}

// ---------------------------------------------------------------------------
// Config
// ---------------------------------------------------------------------------

const OUTPUT_BASE = path.join(process.cwd(), '.mcpengine-output', 'workers');

// ---------------------------------------------------------------------------
// Main
// ---------------------------------------------------------------------------

export async function* deployToMCPEngine(
  projectId: string,
  bundle: ServerBundle,
  config: DeployConfig,
): AsyncGenerator<DeployProgress, DeployResult, void> {
  const slug = config.slug ?? projectId.slice(0, 8);
  const deployId = crypto.randomUUID();
  const startedAt = new Date().toISOString();
  const logs: string[] = [];

  const log = (msg: string) => {
    logs.push(`[${new Date().toISOString()}] ${msg}`);
  };

  // ── Step 1: Compile ────────────────────────────────────────────────────
  yield {
    step: 'compile',
    message: 'Compiling server bundle…',
    percent: 10,
    level: 'info',
  };
  log('Starting compilation…');

  const compiled = compileWithMeta(bundle);
  log(`Compiled ${compiled.fileCount} files (${(compiled.sizeBytes / 1024).toFixed(1)} KB)`);

  yield {
    step: 'compile',
    message: `Compiled ${compiled.fileCount} files (${compiled.toolCount} tools)`,
    percent: 25,
    level: 'success',
  };

  // ── Step 2: Generate Worker script ─────────────────────────────────────
  yield {
    step: 'package',
    message: 'Generating Cloudflare Worker script…',
    percent: 35,
    level: 'info',
  };
  log('Generating worker script…');

  const workerScript = generateWorkerScript({
    serverName: config.slug ?? 'MCP Server',
    serverSlug: slug,
    compiledCode: compiled.code,
    toolNames: compiled.toolNames,
    toolCount: compiled.toolCount,
  });

  const workerSize = new TextEncoder().encode(workerScript).byteLength;
  log(`Worker script generated (${(workerSize / 1024).toFixed(1)} KB)`);

  yield {
    step: 'package',
    message: `Worker packaged (${(workerSize / 1024).toFixed(1)} KB)`,
    percent: 50,
    level: 'success',
  };

  // ── Step 3: "Upload" to local output (simulated) ──────────────────────
  yield {
    step: 'deploy',
    message: 'Deploying to MCPEngine…',
    percent: 60,
    level: 'info',
  };
  log('Uploading worker to MCPEngine…');

  const outputDir = path.join(OUTPUT_BASE, slug);
  await fs.mkdir(outputDir, { recursive: true });

  // Write the worker script
  await fs.writeFile(path.join(outputDir, 'worker.js'), workerScript, 'utf-8');

  // Write wrangler.toml (for future real deploys)
  const wranglerToml = `
# MCPEngine Studio — Auto-generated Wrangler config
name = "${slug}"
main = "worker.js"
compatibility_date = "${new Date().toISOString().split('T')[0]}"
compatibility_flags = ["nodejs_compat"]

[vars]
SERVER_NAME = "${slug}"
DEPLOY_ID = "${deployId}"

# TODO: Add KV/D1/R2 bindings as needed
# [[kv_namespaces]]
# binding = "CACHE"
# id = "xxx"
`.trimStart();

  await fs.writeFile(path.join(outputDir, 'wrangler.toml'), wranglerToml, 'utf-8');

  // Write deploy metadata
  const metadata = {
    deployId,
    projectId,
    slug,
    target: 'mcpengine' as const,
    toolCount: compiled.toolCount,
    toolNames: compiled.toolNames,
    sizeBytes: workerSize,
    createdAt: startedAt,
    url: `https://${slug}.mcpengine.run`,
    endpoint: `https://${slug}.mcpengine.run/mcp`,
  };

  await fs.writeFile(
    path.join(outputDir, 'deploy-meta.json'),
    JSON.stringify(metadata, null, 2),
    'utf-8',
  );

  log(`Worker written to ${outputDir}`);

  yield {
    step: 'deploy',
    message: 'Worker deployed successfully',
    percent: 85,
    level: 'success',
  };

  // ── Step 4: Verify ─────────────────────────────────────────────────────
  yield {
    step: 'verify',
    message: 'Verifying deployment…',
    percent: 90,
    level: 'info',
  };

  // TODO: Hit the real health endpoint once we have actual CF Workers deploy
  // For now, simulate verification
  log('Health check: OK (simulated)');
  log(`Server live at https://${slug}.mcpengine.run`);

  yield {
    step: 'verify',
    message: `Live at https://${slug}.mcpengine.run`,
    percent: 100,
    level: 'success',
  };

  // ── Return result ──────────────────────────────────────────────────────
  const result: DeployResult = {
    id: deployId,
    target: 'mcpengine',
    status: 'live',
    url: `https://${slug}.mcpengine.run`,
    endpoint: `https://${slug}.mcpengine.run/mcp`,
    logs,
    createdAt: startedAt,
  };

  return result;
}
