/**
 * AdminMigration — one-click "migrate this entire app anywhere".
 *
 * Two operations:
 *   1. Export — downloads a single .zip containing the full database
 *      (encrypted+gzipped) + any GridFS uploads + a manifest + README.
 *      The operator can run the same RGE REGALGOA code on a fresh server,
 *      log in, and upload this .zip on the new instance's /admin/migration
 *      page to clone everything.
 *   2. Import — accepts a .zip from a previous export and restores
 *      collections + uploads onto THIS instance.
 *
 * Why this exists: customers can't run mongodump/mongorestore. This is
 * the one-button equivalent.
 */
import React, { useEffect, useRef, useState } from "react";
import { api } from "@/lib/api";
import { Button } from "@/components/ui/button";
import { Card, CardContent } from "@/components/ui/card";
import { Badge } from "@/components/ui/badge";
import {
    Database, Download, Upload, Server, AlertTriangle, CheckCircle2, Loader2,
    HardDrive, Cloud, Shield, FileArchive, Info, GitBranch,
} from "lucide-react";
import { toast } from "sonner";

const BASE = process.env.REACT_APP_BACKEND_URL;

export default function AdminMigration() {
    const [info, setInfo] = useState(null);
    const [exporting, setExporting] = useState(false);
    const [importing, setImporting] = useState(false);
    const [importResult, setImportResult] = useState(null);
    const [mode, setMode] = useState("merge");
    const fileRef = useRef(null);

    const load = async () => {
        try {
            const { data } = await api.get("/admin/migrate/info");
            setInfo(data);
        } catch (e) {
            if (!e.isNetworkError) toast.error(e.response?.data?.detail || "Failed to load migration info");
        }
    };
    useEffect(() => { load(); }, []);

    const doExport = async () => {
        setExporting(true);
        try {
            // Stream via fetch so we get a proper file download regardless of
            // size. The axios JSON interceptor would buffer the whole thing.
            const resp = await fetch(`${BASE}/api/admin/migrate/export`, {
                method: "POST",
                credentials: "include",
                headers: { "Content-Type": "application/json" },
                body: JSON.stringify({ label: "migration", encrypt: true, include_uploads: true }),
            });
            if (!resp.ok) {
                const t = await resp.text();
                throw new Error(t || `HTTP ${resp.status}`);
            }
            const blob = await resp.blob();
            // Pull filename from Content-Disposition if present.
            const cd = resp.headers.get("content-disposition") || "";
            const fnMatch = cd.match(/filename="?([^"]+)"?/);
            const filename = fnMatch ? fnMatch[1] : `rbs-regal-migration-${Date.now()}.zip`;
            // Trigger download
            const url = URL.createObjectURL(blob);
            const a = document.createElement("a");
            a.href = url;
            a.download = filename;
            document.body.appendChild(a);
            a.click();
            a.remove();
            URL.revokeObjectURL(url);
            toast.success(`Exported (${(blob.size / 1024 / 1024).toFixed(1)} MB) — keep this file safe.`);
        } catch (e) {
            toast.error(`Export failed: ${e.message}`);
        } finally { setExporting(false); }
    };

    const doImport = async () => {
        const f = fileRef.current?.files?.[0];
        if (!f) { toast.error("Choose a migration .zip first"); return; }
        if (mode === "replace") {
            if (!window.confirm(
                "REPLACE mode will WIPE every collection and re-insert from the package.\n\n" +
                "This is destructive — only do this on a fresh/empty instance.\n\nContinue?"
            )) return;
        }
        setImporting(true);
        setImportResult(null);
        try {
            const form = new FormData();
            form.append("file", f);
            const { data } = await api.post(`/admin/migrate/import?mode=${mode}`, form, {
                headers: { "Content-Type": "multipart/form-data" },
                timeout: 240000,
            });
            setImportResult(data);
            toast.success(`Restored ${data.restored_documents.toLocaleString()} docs across ${data.restored_collections} collections`);
            load();
        } catch (e) {
            toast.error(`Import failed: ${e.response?.data?.detail || e.message}`);
        } finally { setImporting(false); if (fileRef.current) fileRef.current.value = ""; }
    };

    return (
        <div className="space-y-5" data-testid="admin-migration-page">
            <header>
                <div className="text-[10px] uppercase tracking-[0.2em] gold-text font-semibold">Platform</div>
                <h1 className="font-display text-3xl font-bold text-white flex items-center gap-2">
                    <GitBranch className="h-7 w-7 text-amber-400" /> Migrate Anywhere
                </h1>
                <p className="text-sm text-blue-100/70 mt-1">
                    Export the entire app as a single secure package, or import one onto this instance to clone an existing setup.
                </p>
            </header>

            {/* Source machine info */}
            <Card className="glass-card border-white/10">
                <CardContent className="p-5">
                    <h2 className="font-display text-lg font-bold text-white mb-3 flex items-center gap-2">
                        <Server className="h-5 w-5 text-blue-300" /> This Instance
                    </h2>
                    {!info ? (
                        <div className="text-sm text-blue-200/60 flex items-center gap-2">
                            <Loader2 className="h-4 w-4 animate-spin" /> Loading…
                        </div>
                    ) : (
                        <div className="grid grid-cols-2 sm:grid-cols-4 gap-3">
                            <Stat label="Documents" value={info.db_documents.toLocaleString()} />
                            <Stat label="Collections" value={info.db_collections} />
                            <Stat label="Uploads" value={info.gridfs_files} />
                            <Stat label="Format" value={`v${info.format_version}`} />
                        </div>
                    )}
                    {info && (
                        <div className="mt-3 text-[11px] text-blue-200/50 font-mono">
                            host: {info.source_host} · {info.encryption}
                        </div>
                    )}
                </CardContent>
            </Card>

            {/* Export */}
            <Card className="glass-card border-emerald-500/20">
                <CardContent className="p-5 space-y-3">
                    <div className="flex items-start gap-3 flex-wrap">
                        <div className="h-11 w-11 rounded-xl bg-emerald-500/20 text-emerald-300 flex items-center justify-center flex-shrink-0">
                            <Download className="h-5 w-5" />
                        </div>
                        <div className="flex-1 min-w-[200px]">
                            <h2 className="font-display text-lg font-bold text-white">Export Migration Package</h2>
                            <p className="text-xs text-blue-100/70">
                                Downloads a single <code className="bg-black/30 px-1 py-0.5 rounded">.zip</code> with the encrypted database snapshot, uploads, and a README. Save it somewhere safe — then move it to the new server.
                            </p>
                        </div>
                        <Button
                            onClick={doExport}
                            disabled={exporting || !info}
                            className="bg-emerald-600 hover:bg-emerald-700 text-white"
                            data-testid="migrate-export-btn"
                        >
                            {exporting ? <><Loader2 className="h-4 w-4 mr-1.5 animate-spin" /> Building…</> : <><Download className="h-4 w-4 mr-1.5" /> Export Now</>}
                        </Button>
                    </div>
                    <ul className="text-[11px] text-blue-200/60 space-y-1 pl-3">
                        <li>• Encrypted with the source server's <code>JWT_SECRET</code> — the same secret is required on the target to decrypt.</li>
                        <li>• Includes a manifest + README for the operator on the receiving end.</li>
                    </ul>
                </CardContent>
            </Card>

            {/* Import */}
            <Card className="glass-card border-amber-500/20">
                <CardContent className="p-5 space-y-3">
                    <div className="flex items-start gap-3 flex-wrap">
                        <div className="h-11 w-11 rounded-xl bg-amber-500/20 text-amber-300 flex items-center justify-center flex-shrink-0">
                            <Upload className="h-5 w-5" />
                        </div>
                        <div className="flex-1 min-w-[200px]">
                            <h2 className="font-display text-lg font-bold text-white">Import Migration Package</h2>
                            <p className="text-xs text-blue-100/70">
                                Upload a <code className="bg-black/30 px-1 py-0.5 rounded">.zip</code> from a previous export to restore onto this instance.
                            </p>
                        </div>
                    </div>

                    <div className="grid grid-cols-1 md:grid-cols-[1fr_auto_auto] gap-2 items-center">
                        <input
                            ref={fileRef}
                            type="file"
                            accept=".zip,application/zip"
                            disabled={importing}
                            className="text-sm text-blue-100 file:mr-3 file:py-1.5 file:px-3 file:rounded-md file:border-0 file:bg-amber-500/25 file:text-amber-200 file:cursor-pointer hover:file:bg-amber-500/40"
                            data-testid="migrate-import-file"
                        />
                        <select
                            value={mode}
                            onChange={(e) => setMode(e.target.value)}
                            disabled={importing}
                            className="bg-black/30 border border-white/10 text-blue-50 text-sm rounded-md px-3 py-1.5"
                            data-testid="migrate-import-mode"
                        >
                            <option value="merge">Merge (upsert)</option>
                            <option value="replace">Replace (wipe first)</option>
                        </select>
                        <Button
                            onClick={doImport}
                            disabled={importing}
                            className="bg-amber-500 hover:bg-amber-600 text-amber-950 font-bold"
                            data-testid="migrate-import-btn"
                        >
                            {importing ? <><Loader2 className="h-4 w-4 mr-1.5 animate-spin" /> Importing…</> : <><Upload className="h-4 w-4 mr-1.5" /> Import</>}
                        </Button>
                    </div>

                    <div className="rounded-md bg-amber-500/10 border border-amber-500/30 p-3 flex items-start gap-2 text-[12px]">
                        <AlertTriangle className="h-4 w-4 text-amber-300 flex-shrink-0 mt-0.5" />
                        <div className="text-blue-100/80 leading-relaxed">
                            <b>Replace mode</b> wipes every collection before restoring — only use on an empty/fresh instance.
                            <b className="ml-2">Merge mode</b> upserts; existing records with the same _id are overwritten by the package's version.
                        </div>
                    </div>

                    {importResult && (
                        <div className="rounded-md bg-emerald-500/10 border border-emerald-500/30 p-3 space-y-1" data-testid="migrate-import-result">
                            <div className="flex items-center gap-2 text-sm text-emerald-200 font-semibold">
                                <CheckCircle2 className="h-4 w-4" /> Restore complete
                            </div>
                            <ul className="text-xs text-blue-100/70 space-y-0.5">
                                <li>• Label: <span className="font-mono">{importResult.label}</span></li>
                                <li>• Collections restored: <b>{importResult.restored_collections}</b></li>
                                <li>• Documents restored: <b>{importResult.restored_documents.toLocaleString()}</b></li>
                                <li>• Uploads restored: <b>{importResult.restored_uploads}</b></li>
                            </ul>
                            {importResult.notes?.length > 0 && (
                                <details className="text-xs text-amber-200/80 mt-2">
                                    <summary className="cursor-pointer">{importResult.notes.length} note(s)</summary>
                                    <ul className="mt-1 pl-3 space-y-0.5">
                                        {importResult.notes.map((n, i) => <li key={i}>• {n}</li>)}
                                    </ul>
                                </details>
                            )}
                        </div>
                    )}
                </CardContent>
            </Card>

            {/* Operator runbook */}
            <Card className="glass-card border-blue-500/20">
                <CardContent className="p-5">
                    <h2 className="font-display text-lg font-bold text-white mb-2 flex items-center gap-2">
                        <Info className="h-5 w-5 text-blue-300" /> Quick Runbook
                    </h2>
                    <ol className="text-xs text-blue-100/80 space-y-1.5 list-decimal pl-5 leading-relaxed">
                        <li>On the <b>source</b> server, click <b>Export Now</b>. Save the .zip securely.</li>
                        <li>Spin up the <b>target</b> server with the same RGE REGALGOA code + a fresh MongoDB.</li>
                        <li>Copy the source's <code className="bg-black/30 px-1 rounded">JWT_SECRET</code> from <code className="bg-black/30 px-1 rounded">/app/backend/.env</code> to the target's <code className="bg-black/30 px-1 rounded">.env</code>, then restart the backend. The manifest stores a SHA-256 fingerprint of this secret for verification.</li>
                        <li>Log in to the target with the seeded admin → come to this page → upload the .zip in <b>Replace</b> mode.</li>
                        <li>Log out, log back in with the <b>original admin credentials</b> from the source. Done.</li>
                    </ol>
                </CardContent>
            </Card>
        </div>
    );
}

function Stat({ label, value }) {
    return (
        <div>
            <div className="text-[10px] uppercase tracking-wider text-blue-200/50 font-semibold">{label}</div>
            <div className="font-display text-2xl font-bold text-white mt-0.5">{value}</div>
        </div>
    );
}
