#!/usr/bin/env node
import { Command } from "commander";
import fs from "fs-extra";
import path from "path";
import chalk from "chalk";
import { fileURLToPath } from "url";

const __dirname = path.dirname(fileURLToPath(import.meta.url));
const program = new Command();

program
  .name("mintel")
  .description("CLI for Mintel monorepo management")
  .version("1.0.1");

program
  .command("dev")
  .description("Start the development environment (Docker stack)")
  .option("-l, --local", "Run Next.js locally instead of in Docker")
  .action(async (options) => {
    const { execSync } = await import("child_process");
    console.log(chalk.blue("🚀 Starting Development Environment..."));

    if (options.local) {
      console.log(chalk.cyan("Running Next.js locally..."));
      execSync("next dev", { stdio: "inherit" });
    } else {
      try {
        console.log(chalk.cyan("Starting Docker stack (App, Directus, DB)..."));
        // Ensure network exists
      } catch (_e) {
        // Network already exists or docker is not running
      }
    }

    console.log(
      chalk.yellow(`
📱 App:      http://localhost:3000
🗄️  CMS:      http://localhost:8055/admin
🚦 Traefik:  http://localhost:8080
`),
    );
    execSync(
      "docker-compose down --remove-orphans && docker-compose up app directus directus-db",
      { stdio: "inherit" },
    );
  });

const directus = program
  .command("directus")
  .description("Directus management commands");

directus
  .command("bootstrap")
  .description("Setup Directus branding and settings")
  .action(async () => {
    const { execSync } = await import("child_process");
    console.log(chalk.blue("🎨 Bootstrapping Directus..."));
    execSync("npx tsx --env-file=.env scripts/setup-directus.ts", {
      stdio: "inherit",
    });
  });

directus
  .command("bootstrap-feedback")
  .description("Setup Directus collections and flows for Feedback")
  .action(async () => {
    const { execSync } = await import("child_process");
    console.log(chalk.blue("📧 Bootstrapping Visual Feedback System..."));
    // Use the logic from setup-feedback-hardened.ts
    const bootstrapScript = `
import { createDirectus, rest, authentication, createCollection, createDashboard, createPanel, createItems, createPermission, readPolicies, readRoles, readUsers } from '@directus/sdk';

async function setup() {
    const url = process.env.DIRECTUS_URL || 'http://localhost:8055';
    const email = process.env.DIRECTUS_ADMIN_EMAIL;
    const password = process.env.DIRECTUS_ADMIN_PASSWORD;

    if (!email || !password) {
        console.error('❌ DIRECTUS_ADMIN_EMAIL or DIRECTUS_ADMIN_PASSWORD not set');
        process.exit(1);
    }

    const client = createDirectus(url).with(authentication('json')).with(rest());

    try {
        console.log('🔑 Authenticating...');
        await client.login(email, password);

        const roles = await client.request(readRoles());
        const adminRole = roles.find(r => r.name === 'Administrator');
        const policies = await client.request(readPolicies());
        const adminPolicy = policies.find(p => p.name === 'Administrator');

        console.log('🏗️ Creating Collection "visual_feedback"...');
        try {
            await client.request(createCollection({
                collection: 'visual_feedback',
                meta: { icon: 'feedback', display_template: '{{user_name}}: {{text}}' },
                fields: [
                    { field: 'id', type: 'uuid', schema: { is_primary_key: true } },
                    { field: 'status', type: 'string', schema: { default_value: 'open' }, meta: { interface: 'select-dropdown' } },
                    { field: 'url', type: 'string' },
                    { field: 'selector', type: 'string' },
                    { field: 'x', type: 'float' },
                    { field: 'y', type: 'float' },
                    { field: 'type', type: 'string' },
                    { field: 'text', type: 'text' },
                    { field: 'user_name', type: 'string' },
                    { field: 'user_identity', type: 'string' },
                    { field: 'screenshot', type: 'uuid', meta: { interface: 'file' } },
                    { field: 'date_created', type: 'timestamp', schema: { default_value: 'NOW()' } }
                ]
            } as any));
        } catch (_e) { console.log('  (Collection might already exist)'); }

        try {
            await client.request(createCollection({
                collection: 'visual_feedback_comments',
                meta: { icon: 'comment' },
                fields: [
                    { field: 'id', type: 'integer', schema: { is_primary_key: true, has_auto_increment: true } },
                    { field: 'feedback_id', type: 'uuid', meta: { interface: 'select-dropdown' } },
                    { field: 'user_name', type: 'string' },
                    { field: 'text', type: 'text' },
                    { field: 'date_created', type: 'timestamp', schema: { default_value: 'NOW()' } }
                ]
            } as any));
        } catch (e) { }

        if (adminPolicy) {
            console.log('🔐 Granting ALL permissions to Administrator Policy...');
            for (const coll of ['visual_feedback', 'visual_feedback_comments']) {
              for (const action of ['create', 'read', 'update', 'delete']) {
                try {
                    await client.request(createPermission({
                        collection: coll,
                        action,
                        fields: ['*'],
                        policy: adminPolicy.id
                    } as any));
                } catch (_e) { }
              }
            }
        }

        console.log('📊 Creating Dashboard...');
        try {
          const dash = await client.request(createDashboard({ name: 'Visual Feedback', icon: 'feedback', color: '#6366f1' }));
          await client.request(createPanel({
              dashboard: dash.id,
              name: 'Total Feedbacks',
              type: 'metric',
              width: 12, height: 6, position_x: 1, position_y: 1,
              options: { collection: 'visual_feedback', function: 'count', field: 'id' }
          } as any));
        } catch (e) { }

        console.log('✨ FEEDBACK BOOTSTRAP DONE.');
    } catch (e) { console.error('❌ FAILURE:', e); }
}
setup();
    `;
    const tempFile = path.join(process.cwd(), "temp-bootstrap-feedback.ts");
    await fs.writeFile(tempFile, bootstrapScript);
    try {
      execSync("npx tsx --env-file=.env " + tempFile, { stdio: "inherit" });
    } finally {
      await fs.remove(tempFile);
    }
  });

directus
  .command("sync <action> <env>")
  .description("Sync Directus data (push/pull) for a specific environment")
  .action(async (action, env) => {
    const { execSync } = await import("child_process");
    console.log(
      chalk.blue(`📥 Executing Directus sync: ${action} -> ${env}...`),
    );
    execSync(`./scripts/sync-directus.sh ${action} ${env}`, {
      stdio: "inherit",
    });
  });

program
  .command("pagespeed")
  .description("Run PageSpeed (Lighthouse) tests")
  .action(async () => {
    const { execSync } = await import("child_process");
    console.log(chalk.blue("⚡ Running PageSpeed tests..."));
    execSync("npx tsx ./scripts/pagespeed-sitemap.ts", { stdio: "inherit" });
  });

program
  .command("init <path>")
  .description("Initialize a new website project")
  .action(async (projectPath) => {
    const fullPath = path.isAbsolute(projectPath)
      ? projectPath
      : path.resolve(process.cwd(), projectPath);
    const projectName = path.basename(fullPath);

    console.log(chalk.blue(`Initializing new project: ${projectName}...`));

    try {
      // Create directory
      await fs.ensureDir(fullPath);

      // Create package.json
      const pkgJson = {
        name: projectName,
        version: "0.1.0",
        private: true,
        type: "module",
        scripts: {
          dev: "mintel dev",
          "dev:local": "mintel dev --local",
          build: "next build",
          start: "next start",
          lint: "next lint",
          typecheck: "tsc --noEmit",
          test: "vitest run --passWithNoTests",
          "directus:bootstrap": "mintel directus bootstrap",
          "directus:push:testing": "mintel directus sync push testing",
          "directus:pull:testing": "mintel directus sync pull testing",
          "directus:push:staging": "mintel directus sync push staging",
          "directus:pull:staging": "mintel directus sync pull staging",
          "directus:push:prod": "mintel directus sync push production",
          "directus:pull:prod": "mintel directus sync pull production",
          "pagespeed:test": "mintel pagespeed",
        },
        dependencies: {
          next: "16.1.6",
          react: "^19.0.0",
          "react-dom": "^19.0.0",
          "@mintel/next-utils": "workspace:*",
          "@mintel/next-observability": "workspace:*",
          "@directus/sdk": "^21.0.0",
        },
        devDependencies: {
          "@types/node": "^20.0.0",
          "@types/react": "^19.0.0",
          "@types/react-dom": "^19.0.0",
          typescript: "^5.0.0",
          "@mintel/tsconfig": "workspace:*",
          "@mintel/eslint-config": "workspace:*",
          "@mintel/next-config": "workspace:*",
          "@mintel/husky-config": "workspace:*",
        },
      };
      await fs.writeJson(path.join(fullPath, "package.json"), pkgJson, {
        spaces: 2,
      });

      // Create next.config.ts
      const nextConfig = `import mintelNextConfig from "@mintel/next-config";

/** @type {import('next').NextConfig} */
const nextConfig = {};

export default mintelNextConfig(nextConfig);
`;
      await fs.writeFile(path.join(fullPath, "next.config.ts"), nextConfig);

      // Create tsconfig.json
      const tsConfig = {
        extends: "@mintel/tsconfig/nextjs.json",
        compilerOptions: {
          paths: {
            "@/*": ["./src/*"],
          },
        },
        include: [
          "next-env.d.ts",
          "**/*.ts",
          "**/*.tsx",
          ".next/types/**/*.ts",
        ],
        exclude: ["node_modules"],
      };
      await fs.writeJson(path.join(fullPath, "tsconfig.json"), tsConfig, {
        spaces: 2,
      });

      // Create eslint.config.mjs
      const eslintConfig = `import { nextConfig } from "@mintel/eslint-config/next";

export default nextConfig;
`;
      await fs.writeFile(
        path.join(fullPath, "eslint.config.mjs"),
        eslintConfig,
      );

      // Create Husky/Linting configs
      await fs.writeFile(
        path.join(fullPath, "commitlint.config.js"),
        `export { default } from "@mintel/husky-config/commitlint";\n`,
      );
      await fs.writeFile(
        path.join(fullPath, ".lintstagedrc.js"),
        `export { default } from "@mintel/husky-config/lint-staged";\n`,
      );

      // Create env validation script
      await fs.ensureDir(path.join(fullPath, "scripts"));
      await fs.writeFile(
        path.join(fullPath, "scripts/validate-env.ts"),
        `import { validateMintelEnv } from "@mintel/next-utils";

try {
  validateMintelEnv();
  console.log("✅ Environment variables validated");
} catch (error) {
  process.exit(1);
}
`,
      );

      // Create basic src structure
      await fs.ensureDir(path.join(fullPath, "src/app/[locale]"));
      await fs.writeFile(
        path.join(fullPath, "src/middleware.ts"),
        `import { createMintelMiddleware } from "@mintel/next-utils";

export default createMintelMiddleware({
  locales: ["en", "de"],
  defaultLocale: "en",
  logRequests: true,
});

export const config = {
  matcher: ["/((?!api|_next|_vercel|health|.*\\\\..*).*)", "/", "/(de|en)/:path*"]
};
`,
      );

      // Create i18n/request.ts
      await fs.ensureDir(path.join(fullPath, "src/i18n"));
      await fs.writeFile(
        path.join(fullPath, "src/i18n/request.ts"),
        `import { createMintelI18nRequestConfig } from "@mintel/next-utils";

export default createMintelI18nRequestConfig(
  ["en", "de"],
  "en",
  (locale) => import(\`../../messages/\${locale}.json\`)
);
`,
      );

      // Create messages directory
      await fs.ensureDir(path.join(fullPath, "messages"));
      await fs.writeJson(
        path.join(fullPath, "messages/en.json"),
        {
          Index: {
            title: "Welcome",
          },
        },
        { spaces: 2 },
      );
      await fs.writeJson(
        path.join(fullPath, "messages/de.json"),
        {
          Index: {
            title: "Willkommen",
          },
        },
        { spaces: 2 },
      );

      // Create instrumentation.ts
      await fs.writeFile(
        path.join(fullPath, "src/instrumentation.ts"),
        `import { Sentry } from '@mintel/next-observability';

export async function register() {
  if (process.env.NEXT_RUNTIME === 'nodejs') {
    await import('./sentry.server.config');
  }

  if (process.env.NEXT_RUNTIME === 'edge') {
    await import('./sentry.edge.config');
  }
}

export const onRequestError = Sentry.captureRequestError;
`,
      );

      await fs.writeFile(
        path.join(fullPath, "src/app/[locale]/layout.tsx"),
        `import type { Metadata } from "next";

export const metadata: Metadata = {
  title: "${projectName}",
  description: "Created with Mintel CLI",
};

export default function RootLayout({
  children,
  params: { locale }
}: {
  children: React.ReactNode;
  params: { locale: string };
}) {
  return (
    <html lang={locale}>
      <body className="antialiased">{children}</body>
    </html>
  );
}
`,
      );

      await fs.writeFile(
        path.join(fullPath, "src/app/[locale]/page.tsx"),
        `import { useTranslations } from 'next-intl';

export default function Home() {
  const t = useTranslations('Index');
  
  return (
    <main>
      <h1>{t('title')} to ${projectName}</h1>
    </main>
  );
}
`,
      );

      // Copy infra templates
      const infraPath = path.resolve(__dirname, "../../infra");
      if (await fs.pathExists(infraPath)) {
        // Setup Dockerfile from template
        const templatePath = path.join(
          infraPath,
          "docker/Dockerfile.app-template",
        );
        if (await fs.pathExists(templatePath)) {
          let dockerfile = await fs.readFile(templatePath, "utf8");
          dockerfile = dockerfile.replace(/\$\{APP_NAME:-app\}/g, projectName);
          await fs.writeFile(path.join(fullPath, "Dockerfile"), dockerfile);
        }

        // Setup docker-compose from template
        const composeTemplatePath = path.join(
          infraPath,
          "docker/docker-compose.template.yml",
        );
        if (await fs.pathExists(composeTemplatePath)) {
          let compose = await fs.readFile(composeTemplatePath, "utf8");
          compose = compose.replace(/\$\{APP_NAME:-app\}/g, projectName);
          compose = compose.replace(/\$\{PROJECT_NAME:-app\}/g, projectName);
          await fs.writeFile(
            path.join(fullPath, "docker-compose.yml"),
            compose,
          );
        }

        await fs.ensureDir(path.join(fullPath, ".gitea/workflows"));
        const deployActionPath = path.join(
          infraPath,
          "gitea/deploy-action.yml",
        );
        if (await fs.pathExists(deployActionPath)) {
          await fs.copy(
            deployActionPath,
            path.join(fullPath, ".gitea/workflows/deploy.yml"),
          );
        }
      }

      // Create Directus structure
      await fs.ensureDir(path.join(fullPath, "directus/uploads"));
      await fs.ensureDir(path.join(fullPath, "directus/extensions"));
      await fs.writeFile(path.join(fullPath, "directus/uploads/.gitkeep"), "");
      await fs.writeFile(
        path.join(fullPath, "directus/extensions/.gitkeep"),
        "",
      );

      // Create .env.example
      const envExample = `# Project
PROJECT_NAME=${projectName}
PROJECT_COLOR=#82ed20

# Authentication
GATEKEEPER_PASSWORD=mintel
AUTH_COOKIE_NAME=mintel_gatekeeper_session

# Host Config (Local)
TRAEFIK_HOST=\`${projectName}.localhost\`
DIRECTUS_HOST=\`cms.${projectName}.localhost\`

# Next.js
NEXT_PUBLIC_BASE_URL=http://${projectName}.localhost

# Directus
DIRECTUS_URL=http://cms.${projectName}.localhost
DIRECTUS_KEY=$(openssl rand -hex 32 2>/dev/null || echo "mintel-key")
DIRECTUS_SECRET=$(openssl rand -hex 32 2>/dev/null || echo "mintel-secret")
DIRECTUS_ADMIN_EMAIL=admin@mintel.me
DIRECTUS_ADMIN_PASSWORD=mintel-admin-pass
DIRECTUS_DB_NAME=directus
DIRECTUS_DB_USER=directus
DIRECTUS_DB_PASSWORD=mintel-db-pass

# Sentry / Glitchtip
SENTRY_DSN=

# Analytics (Umami)
UMAMI_WEBSITE_ID=
UMAMI_API_ENDPOINT=https://analytics.infra.mintel.me

# Notifications (Gotify)
GOTIFY_URL=
GOTIFY_TOKEN=
`;
      await fs.writeFile(path.join(fullPath, ".env.example"), envExample);

      // Copy premium templates (globals.css, lib/directus.ts, scripts/setup-directus.ts)
      const templatePath = path.join(infraPath, "templates/website");
      if (await fs.pathExists(templatePath)) {
        console.log(chalk.blue("Applying premium templates..."));
        await fs.copy(templatePath, fullPath, { overwrite: true });
      }

      console.log(
        chalk.green(`Successfully initialized ${projectName} at ${fullPath}`),
      );
      console.log(chalk.yellow("\nNext steps:"));
      console.log(chalk.cyan("1. pnpm install"));
      console.log(chalk.cyan(`2. cd ${projectPath} && pnpm dev`));
    } catch (error) {
      console.error(chalk.red("Error initializing project:"), error);
    }
  });

program.parse();
