// app/install/page.tsx
"use client";

import { useEffect, useState } from "react";
import {
  Mail,
  Database,
  UserCog,
  Server,
  CheckCircle2,
  XCircle,
  Loader2,
  AlertCircle,
  ArrowRight,
  ArrowLeft,
} from "lucide-react";

type Step = "welcome" | "database" | "admin" | "mail" | "review" | "done";

interface DbFields {
  host: string;
  port: string;
  database: string;
  user: string;
  password: string;
}

interface AdminFields {
  username: string;
  password: string;
  confirmPassword: string;
}

interface MailFields {
  webhookSigningKey: string;
  mxHost: string;
  mxHostFallback: string;
}

const STEP_ORDER: Step[] = ["welcome", "database", "admin", "mail", "review", "done"];

function StepIndicator({ current }: { current: Step }) {
  const labels: { step: Step; label: string }[] = [
    { step: "database", label: "Database" },
    { step: "admin", label: "Admin" },
    { step: "mail", label: "Mail" },
    { step: "review", label: "Install" },
  ];
  const currentIndex = STEP_ORDER.indexOf(current);

  return (
    <div className="flex items-center gap-2 mb-8">
      {labels.map(({ step, label }, i) => {
        const stepIndex = STEP_ORDER.indexOf(step);
        const isDone = currentIndex > stepIndex;
        const isActive = currentIndex === stepIndex;
        return (
          <div key={step} className="flex items-center gap-2 flex-1">
            <div
              className={`w-6 h-6 rounded-full flex items-center justify-center text-[11px] font-semibold shrink-0 ${
                isDone
                  ? "bg-emerald-600 text-white"
                  : isActive
                  ? "bg-indigo-600 text-white"
                  : "bg-slate-800 text-slate-500"
              }`}
            >
              {isDone ? <CheckCircle2 className="w-3.5 h-3.5" /> : i + 1}
            </div>
            <span
              className={`text-xs font-medium hidden sm:inline ${
                isActive ? "text-white" : "text-slate-500"
              }`}
            >
              {label}
            </span>
            {i < labels.length - 1 && <div className="flex-1 h-px bg-slate-800" />}
          </div>
        );
      })}
    </div>
  );
}

export default function InstallPage() {
  const [step, setStep] = useState<Step>("welcome");
  const [error, setError] = useState<string | null>(null);

  const [db, setDb] = useState<DbFields>({
    host: "localhost",
    port: "3306",
    database: "",
    user: "",
    password: "",
  });
  const [dbTestState, setDbTestState] = useState<"idle" | "testing" | "ok" | "failed">("idle");
  const [dbTestError, setDbTestError] = useState<string | null>(null);

  const [admin, setAdmin] = useState<AdminFields>({
    username: "admin",
    password: "",
    confirmPassword: "",
  });

  const [mail, setMail] = useState<MailFields>({
    webhookSigningKey: "",
    mxHost: "",
    mxHostFallback: "",
  });

  const [isInstalling, setIsInstalling] = useState(false);
  const [installResult, setInstallResult] = useState<{
    restarted: boolean;
    mechanism: "pm2" | "passenger" | "none";
  } | null>(null);
  const [pollingDone, setPollingDone] = useState(false);

  async function handleTestConnection() {
    setDbTestState("testing");
    setDbTestError(null);
    try {
      const res = await fetch("/api/install/test-db", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify(db),
      });
      const data = await res.json();
      if (res.ok && data.ok) {
        setDbTestState("ok");
      } else {
        setDbTestState("failed");
        setDbTestError(data.error || "Connection failed");
      }
    } catch {
      setDbTestState("failed");
      setDbTestError("Could not reach the server to test the connection");
    }
  }

  function validateAdminStep(): string | null {
    if (!admin.username.trim() || admin.username.trim().length < 3) {
      return "Username must be at least 3 characters";
    }
    if (!admin.password || admin.password.length < 8) {
      return "Password must be at least 8 characters";
    }
    if (admin.password !== admin.confirmPassword) {
      return "Passwords do not match";
    }
    return null;
  }

  async function handleInstall() {
    setError(null);
    setIsInstalling(true);
    try {
      const res = await fetch("/api/install/run", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({
          db,
          admin: { username: admin.username.trim(), password: admin.password },
          mail: mail.webhookSigningKey || mail.mxHost ? mail : undefined,
        }),
      });
      const data = await res.json();
      if (!res.ok) {
        setError(data.error || "Installation failed");
        setIsInstalling(false);
        return;
      }
      setInstallResult({ restarted: !!data.restarted, mechanism: data.mechanism || "none" });
      setStep("done");
    } catch {
      setError("Something went wrong while installing. Check the server logs.");
    } finally {
      setIsInstalling(false);
    }
  }

  // Poll for the restarted process to come back up with INSTALL_COMPLETE set.
  useEffect(() => {
    if (step !== "done" || !installResult?.restarted || pollingDone) return;

    const interval = setInterval(async () => {
      try {
        const res = await fetch("/api/install/status");
        const data = await res.json();
        if (data.installed) {
          setPollingDone(true);
          clearInterval(interval);
          window.location.href = "/login";
        }
      } catch {
        // Server is mid-restart and briefly unreachable — keep polling.
      }
    }, 2000);

    // Give up auto-polling after 2 minutes so the manual instructions show.
    const timeout = setTimeout(() => clearInterval(interval), 120_000);

    return () => {
      clearInterval(interval);
      clearTimeout(timeout);
    };
  }, [step, installResult, pollingDone]);

  return (
    <div className="min-h-screen w-full flex items-center justify-center bg-slate-950 px-4 py-10">
      <div className="w-full max-w-lg">
        <div className="flex flex-col items-center mb-6">
          <div className="w-12 h-12 rounded-xl bg-indigo-600 flex items-center justify-center mb-4">
            <Mail className="w-6 h-6 text-white" />
          </div>
          <h1 className="text-xl font-semibold text-white">TempMail Admin Setup</h1>
          <p className="text-sm text-slate-400 mt-1">First-time installation wizard</p>
        </div>

        <div className="bg-slate-900 border border-slate-800 rounded-2xl p-6 shadow-xl">
          {step !== "welcome" && step !== "done" && <StepIndicator current={step} />}

          {error && (
            <div className="flex items-center gap-2 text-sm text-red-400 bg-red-950/40 border border-red-900 rounded-lg px-3 py-2 mb-4">
              <AlertCircle className="w-4 h-4 shrink-0" />
              <span>{error}</span>
            </div>
          )}

          {step === "welcome" && (
            <div className="space-y-5">
              <p className="text-sm text-slate-400 leading-relaxed">
                This wizard will connect to your MySQL/MariaDB database, create the required
                tables, and set up your admin login. It should take about two minutes.
              </p>
              <div className="flex items-start gap-2 text-xs text-amber-400 bg-amber-950/40 border border-amber-900 rounded-lg px-3 py-2">
                <AlertCircle className="w-4 h-4 shrink-0 mt-0.5" />
                <span>
                  Run this now, before sharing the domain publicly — anyone who reaches this page
                  before you finish setup could configure the admin account themselves. The
                  wizard permanently locks itself after the first successful install.
                </span>
              </div>
              <button
                onClick={() => setStep("database")}
                className="w-full flex items-center justify-center gap-2 bg-indigo-600 hover:bg-indigo-500 text-white text-sm font-medium rounded-lg py-2.5 transition-colors"
              >
                Get Started
                <ArrowRight className="w-4 h-4" />
              </button>
            </div>
          )}

          {step === "database" && (
            <div className="space-y-4">
              <div className="flex items-center gap-2 text-sm font-semibold text-white">
                <Database className="w-4 h-4 text-indigo-400" />
                Database Connection
              </div>

              <div className="grid grid-cols-3 gap-3">
                <div className="col-span-2 space-y-1.5">
                  <label className="text-xs font-medium text-slate-400">Host</label>
                  <input
                    type="text"
                    value={db.host}
                    onChange={(e) => {
                      setDb({ ...db, host: e.target.value });
                      setDbTestState("idle");
                    }}
                    className="w-full bg-slate-800 border border-slate-700 rounded-lg px-3 py-2 text-sm text-white focus:outline-none focus:ring-2 focus:ring-indigo-500"
                  />
                </div>
                <div className="space-y-1.5">
                  <label className="text-xs font-medium text-slate-400">Port</label>
                  <input
                    type="text"
                    value={db.port}
                    onChange={(e) => {
                      setDb({ ...db, port: e.target.value });
                      setDbTestState("idle");
                    }}
                    className="w-full bg-slate-800 border border-slate-700 rounded-lg px-3 py-2 text-sm text-white focus:outline-none focus:ring-2 focus:ring-indigo-500"
                  />
                </div>
              </div>

              <div className="space-y-1.5">
                <label className="text-xs font-medium text-slate-400">Database name</label>
                <input
                  type="text"
                  value={db.database}
                  onChange={(e) => {
                    setDb({ ...db, database: e.target.value });
                    setDbTestState("idle");
                  }}
                  placeholder="cpaneluser_tempmail"
                  className="w-full bg-slate-800 border border-slate-700 rounded-lg px-3 py-2 text-sm text-white placeholder-slate-500 focus:outline-none focus:ring-2 focus:ring-indigo-500"
                />
              </div>

              <div className="space-y-1.5">
                <label className="text-xs font-medium text-slate-400">Username</label>
                <input
                  type="text"
                  value={db.user}
                  onChange={(e) => {
                    setDb({ ...db, user: e.target.value });
                    setDbTestState("idle");
                  }}
                  placeholder="cpaneluser_dbuser"
                  className="w-full bg-slate-800 border border-slate-700 rounded-lg px-3 py-2 text-sm text-white placeholder-slate-500 focus:outline-none focus:ring-2 focus:ring-indigo-500"
                />
              </div>

              <div className="space-y-1.5">
                <label className="text-xs font-medium text-slate-400">Password</label>
                <input
                  type="password"
                  value={db.password}
                  onChange={(e) => {
                    setDb({ ...db, password: e.target.value });
                    setDbTestState("idle");
                  }}
                  className="w-full bg-slate-800 border border-slate-700 rounded-lg px-3 py-2 text-sm text-white focus:outline-none focus:ring-2 focus:ring-indigo-500"
                />
              </div>

              <button
                onClick={handleTestConnection}
                disabled={
                  dbTestState === "testing" || !db.host || !db.database || !db.user
                }
                className="w-full flex items-center justify-center gap-2 bg-slate-800 hover:bg-slate-700 disabled:opacity-50 text-slate-200 text-sm font-medium rounded-lg py-2.5 transition-colors"
              >
                {dbTestState === "testing" && <Loader2 className="w-4 h-4 animate-spin" />}
                Test Connection
              </button>

              {dbTestState === "ok" && (
                <div className="flex items-center gap-2 text-sm text-emerald-400 bg-emerald-950/40 border border-emerald-900 rounded-lg px-3 py-2">
                  <CheckCircle2 className="w-4 h-4 shrink-0" />
                  Connection successful
                </div>
              )}
              {dbTestState === "failed" && (
                <div className="flex items-center gap-2 text-sm text-red-400 bg-red-950/40 border border-red-900 rounded-lg px-3 py-2">
                  <XCircle className="w-4 h-4 shrink-0" />
                  {dbTestError}
                </div>
              )}

              <div className="flex justify-between pt-2">
                <button
                  onClick={() => setStep("welcome")}
                  className="flex items-center gap-1 px-4 py-2 text-sm font-medium text-slate-300 hover:text-white transition-colors"
                >
                  <ArrowLeft className="w-4 h-4" />
                  Back
                </button>
                <button
                  onClick={() => setStep("admin")}
                  disabled={dbTestState !== "ok"}
                  className="flex items-center gap-2 px-4 py-2 text-sm font-medium bg-indigo-600 hover:bg-indigo-500 disabled:bg-indigo-900 disabled:cursor-not-allowed text-white rounded-lg transition-colors"
                >
                  Next
                  <ArrowRight className="w-4 h-4" />
                </button>
              </div>
            </div>
          )}

          {step === "admin" && (
            <div className="space-y-4">
              <div className="flex items-center gap-2 text-sm font-semibold text-white">
                <UserCog className="w-4 h-4 text-indigo-400" />
                Admin Account
              </div>

              <div className="space-y-1.5">
                <label className="text-xs font-medium text-slate-400">Username</label>
                <input
                  type="text"
                  value={admin.username}
                  onChange={(e) => setAdmin({ ...admin, username: e.target.value })}
                  className="w-full bg-slate-800 border border-slate-700 rounded-lg px-3 py-2 text-sm text-white focus:outline-none focus:ring-2 focus:ring-indigo-500"
                />
              </div>

              <div className="space-y-1.5">
                <label className="text-xs font-medium text-slate-400">Password</label>
                <input
                  type="password"
                  value={admin.password}
                  onChange={(e) => setAdmin({ ...admin, password: e.target.value })}
                  className="w-full bg-slate-800 border border-slate-700 rounded-lg px-3 py-2 text-sm text-white focus:outline-none focus:ring-2 focus:ring-indigo-500"
                />
              </div>

              <div className="space-y-1.5">
                <label className="text-xs font-medium text-slate-400">Confirm password</label>
                <input
                  type="password"
                  value={admin.confirmPassword}
                  onChange={(e) => setAdmin({ ...admin, confirmPassword: e.target.value })}
                  className="w-full bg-slate-800 border border-slate-700 rounded-lg px-3 py-2 text-sm text-white focus:outline-none focus:ring-2 focus:ring-indigo-500"
                />
              </div>

              <div className="flex justify-between pt-2">
                <button
                  onClick={() => setStep("database")}
                  className="flex items-center gap-1 px-4 py-2 text-sm font-medium text-slate-300 hover:text-white transition-colors"
                >
                  <ArrowLeft className="w-4 h-4" />
                  Back
                </button>
                <button
                  onClick={() => {
                    const validationError = validateAdminStep();
                    if (validationError) {
                      setError(validationError);
                      return;
                    }
                    setError(null);
                    setStep("mail");
                  }}
                  className="flex items-center gap-2 px-4 py-2 text-sm font-medium bg-indigo-600 hover:bg-indigo-500 text-white rounded-lg transition-colors"
                >
                  Next
                  <ArrowRight className="w-4 h-4" />
                </button>
              </div>
            </div>
          )}

          {step === "mail" && (
            <div className="space-y-4">
              <div className="flex items-center gap-2 text-sm font-semibold text-white">
                <Server className="w-4 h-4 text-indigo-400" />
                Mail Provider <span className="text-xs font-normal text-slate-500">(optional)</span>
              </div>
              <p className="text-xs text-slate-500">
                Needed for inbound mail to work. You can skip this and add it to .env later.
              </p>

              <div className="space-y-1.5">
                <label className="text-xs font-medium text-slate-400">Webhook signing key</label>
                <input
                  type="text"
                  value={mail.webhookSigningKey}
                  onChange={(e) => setMail({ ...mail, webhookSigningKey: e.target.value })}
                  placeholder="from your inbound mail provider's dashboard"
                  className="w-full bg-slate-800 border border-slate-700 rounded-lg px-3 py-2 text-sm text-white placeholder-slate-500 focus:outline-none focus:ring-2 focus:ring-indigo-500"
                />
              </div>

              <div className="grid grid-cols-2 gap-3">
                <div className="space-y-1.5">
                  <label className="text-xs font-medium text-slate-400">MX host</label>
                  <input
                    type="text"
                    value={mail.mxHost}
                    onChange={(e) => setMail({ ...mail, mxHost: e.target.value })}
                    placeholder="mxa.mailgun.org"
                    className="w-full bg-slate-800 border border-slate-700 rounded-lg px-3 py-2 text-sm text-white placeholder-slate-500 focus:outline-none focus:ring-2 focus:ring-indigo-500"
                  />
                </div>
                <div className="space-y-1.5">
                  <label className="text-xs font-medium text-slate-400">MX host (fallback)</label>
                  <input
                    type="text"
                    value={mail.mxHostFallback}
                    onChange={(e) => setMail({ ...mail, mxHostFallback: e.target.value })}
                    placeholder="mxb.mailgun.org"
                    className="w-full bg-slate-800 border border-slate-700 rounded-lg px-3 py-2 text-sm text-white placeholder-slate-500 focus:outline-none focus:ring-2 focus:ring-indigo-500"
                  />
                </div>
              </div>

              <div className="flex justify-between pt-2">
                <button
                  onClick={() => setStep("admin")}
                  className="flex items-center gap-1 px-4 py-2 text-sm font-medium text-slate-300 hover:text-white transition-colors"
                >
                  <ArrowLeft className="w-4 h-4" />
                  Back
                </button>
                <button
                  onClick={() => setStep("review")}
                  className="flex items-center gap-2 px-4 py-2 text-sm font-medium bg-indigo-600 hover:bg-indigo-500 text-white rounded-lg transition-colors"
                >
                  Next
                  <ArrowRight className="w-4 h-4" />
                </button>
              </div>
            </div>
          )}

          {step === "review" && (
            <div className="space-y-4">
              <div className="text-sm font-semibold text-white">Review &amp; Install</div>

              <div className="space-y-2 text-xs text-slate-400 bg-slate-800/60 rounded-lg p-3">
                <p>
                  <span className="text-slate-500">Database:</span> {db.user}@{db.host}:{db.port}/
                  {db.database}
                </p>
                <p>
                  <span className="text-slate-500">Admin username:</span> {admin.username}
                </p>
                <p>
                  <span className="text-slate-500">Mail provider:</span>{" "}
                  {mail.webhookSigningKey || mail.mxHost ? "configured" : "skipped (add later)"}
                </p>
              </div>

              <p className="text-xs text-slate-500">
                Clicking install will create the database tables, create your admin account,
                write the server configuration, and attempt to restart the app so it takes
                effect.
              </p>

              <div className="flex justify-between pt-2">
                <button
                  onClick={() => setStep("mail")}
                  disabled={isInstalling}
                  className="flex items-center gap-1 px-4 py-2 text-sm font-medium text-slate-300 hover:text-white transition-colors disabled:opacity-50"
                >
                  <ArrowLeft className="w-4 h-4" />
                  Back
                </button>
                <button
                  onClick={handleInstall}
                  disabled={isInstalling}
                  className="flex items-center gap-2 px-5 py-2 text-sm font-medium bg-indigo-600 hover:bg-indigo-500 disabled:bg-indigo-900 text-white rounded-lg transition-colors"
                >
                  {isInstalling && <Loader2 className="w-4 h-4 animate-spin" />}
                  {isInstalling ? "Installing..." : "Install Now"}
                </button>
              </div>
            </div>
          )}

          {step === "done" && installResult && (
            <div className="space-y-4 text-center py-2">
              <div className="w-12 h-12 rounded-full bg-emerald-950/60 border border-emerald-900 flex items-center justify-center mx-auto">
                <CheckCircle2 className="w-6 h-6 text-emerald-400" />
              </div>
              <h2 className="text-base font-semibold text-white">Installation complete</h2>

              {installResult.mechanism === "pm2" && (
                <div className="space-y-3">
                  <p className="text-sm text-slate-400">
                    Restarting the app to apply your configuration. This page will redirect to
                    login automatically once it&apos;s back up.
                  </p>
                  <div className="flex items-center justify-center gap-2 text-xs text-slate-500">
                    <Loader2 className="w-3.5 h-3.5 animate-spin" />
                    Waiting for restart...
                  </div>
                </div>
              )}

              {installResult.mechanism === "passenger" && (
                <div className="space-y-3">
                  <p className="text-sm text-slate-400">
                    Configuration written. The app will pick it up on its very next request —
                    which happens automatically as this page checks in below.
                  </p>
                  <div className="flex items-center justify-center gap-2 text-xs text-slate-500">
                    <Loader2 className="w-3.5 h-3.5 animate-spin" />
                    Applying configuration...
                  </div>
                </div>
              )}

              {installResult.mechanism === "none" && (
                <div className="text-left space-y-3">
                  <p className="text-sm text-slate-400">
                    Configuration was written, but the app couldn&apos;t restart itself
                    automatically. Restart it manually to apply the new settings, then continue:
                  </p>
                  <div className="text-xs text-slate-500 space-y-2">
                    <p>
                      <span className="text-slate-300 font-medium">
                        cPanel &quot;Setup Node.js App&quot;:
                      </span>{" "}
                      open the app in WHM/cPanel and click <span className="text-slate-300">Restart</span>.
                    </p>
                    <p>
                      <span className="text-slate-300 font-medium">SSH + PM2:</span>{" "}
                      run the command below.
                    </p>
                  </div>
                  <pre className="bg-slate-950 border border-slate-800 rounded-lg p-3 text-xs text-emerald-400 overflow-x-auto">
                    pm2 restart ecosystem.config.js
                  </pre>
                  <button
                    onClick={() => (window.location.href = "/login")}
                    className="w-full flex items-center justify-center gap-2 bg-indigo-600 hover:bg-indigo-500 text-white text-sm font-medium rounded-lg py-2.5 transition-colors"
                  >
                    I&apos;ve restarted — Go to login
                  </button>
                </div>
              )}
            </div>
          )}
        </div>
      </div>
    </div>
  );
}
