"use client";

import { useState } from "react";
import { useParams } from "next/navigation";
import {
  Loader2, AlertCircle, ExternalLink, Globe, RefreshCw,
  CircleDot, ChevronDown, ChevronRight, Copy, Check,
  Terminal, Server,
} from "lucide-react";
import { useAnatomy, type Anatomy } from "@/components/project/use-anatomy";

/**
 * Hosting tab — user-facing: "Is my thing live? How do I reach it?"
 *
 * One endpoint = one card. Each card shows:
 *   - Live URL (open in new tab)
 *   - Status dot + plain-language status
 *   - Redeploy button
 *   - Domain(s) list
 *   - Last build (time + status)
 *   - Expandable recent logs
 *
 * No master-detail split — with 1-3 services the overhead isn't worth it.
 * Previews (dev server URLs) shown below in a secondary section.
 */

// ──────────────────────────────────────────────────
// Types
// ──────────────────────────────────────────────────

type LiveItem = Anatomy["hosting"]["live"][number];
type Preview = Anatomy["hosting"]["previews"][number];

// ──────────────────────────────────────────────────
// Main component
// ──────────────────────────────────────────────────

export default function HostingTab() {
  const params = useParams();
  const projectId = params.projectId as string;
  const { anatomy, loading, error } = useAnatomy(projectId, { pollMs: 8000 });
  const showLoading = loading && !anatomy;

  return (
    <div style={pageWrap}>
      {showLoading && (
        <div style={centeredMsg}>
          <Loader2 size={16} className="animate-spin" style={{ color: INK.muted }} />
          <span style={{ color: INK.muted, fontSize: "0.85rem" }}>Loading…</span>
        </div>
      )}
      {error && !showLoading && (
        <div style={centeredMsg}>
          <AlertCircle size={15} style={{ color: DANGER }} />
          <span style={{ fontSize: "0.85rem", color: DANGER }}>{error}</span>
        </div>
      )}

      {anatomy && (
        <>
          {/* ── Live endpoints ── */}
          <section>
            <SectionHeader title="Live" count={anatomy.hosting.live.length} />
            {anatomy.hosting.live.length === 0 ? (
              <EmptySection
                icon={<Server size={20} style={{ color: INK.muted }} />}
                title="Nothing deployed yet"
                hint="Ask the AI to deploy your app and it will appear here."
                promptSuggestion="Deploy my app to production"
              />
            ) : (
              <div style={{ display: "flex", flexDirection: "column", gap: 16 }}>
                {anatomy.hosting.live.map(item => (
                  <LiveCard key={item.uuid} item={item} projectId={projectId} />
                ))}
              </div>
            )}
          </section>

          {/* ── Previews ── */}
          {anatomy.hosting.previews.length > 0 && (
            <section style={{ marginTop: 40 }}>
              <SectionHeader title="Dev Previews" count={anatomy.hosting.previews.length} />
              <div style={{ display: "flex", flexDirection: "column", gap: 10 }}>
                {anatomy.hosting.previews.map(p => (
                  <PreviewRow key={p.id} preview={p} />
                ))}
              </div>
            </section>
          )}
        </>
      )}
    </div>
  );
}

// ──────────────────────────────────────────────────
// Live card
// ──────────────────────────────────────────────────

function LiveCard({ item, projectId }: { item: LiveItem; projectId: string }) {
  const [deploying, setDeploying] = useState(false);
  const [logsOpen, setLogsOpen] = useState(false);
  const [logs, setLogs] = useState<string | null>(null);
  const [logsLoading, setLogsLoading] = useState(false);
  const [copied, setCopied] = useState(false);

  const primaryUrl = item.fqdn ? `https://${item.fqdn}` : null;
  const phase = classifyPhase(item.status);
  const { color: statusColor, label: statusLabel } = phaseDisplay(phase, item);

  const redeploy = async () => {
    if (deploying) return;
    setDeploying(true);
    try {
      await fetch(`/api/mcp`, {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({
          action: "apps.deploy",
          params: { uuid: item.uuid, projectId },
        }),
      });
    } finally {
      setTimeout(() => setDeploying(false), 3000);
    }
  };

  const openLogs = async () => {
    if (!logsOpen) {
      setLogsOpen(true);
      setLogsLoading(true);
      try {
        const r = await fetch(`/api/mcp`, {
          method: "POST",
          headers: { "Content-Type": "application/json" },
          body: JSON.stringify({
            action: "apps.logs",
            params: { uuid: item.uuid, lines: 60 },
          }),
        });
        const d = await r.json();
        setLogs(typeof d.result === "string" ? d.result : JSON.stringify(d.result ?? d.error, null, 2));
      } catch {
        setLogs("Failed to load logs.");
      } finally {
        setLogsLoading(false);
      }
    } else {
      setLogsOpen(false);
    }
  };

  const copyUrl = () => {
    if (!primaryUrl) return;
    navigator.clipboard.writeText(primaryUrl);
    setCopied(true);
    setTimeout(() => setCopied(false), 2000);
  };

  return (
    <div style={card}>
      {/* ── Card header ── */}
      <div style={cardHeader}>
        <div style={{ display: "flex", alignItems: "center", gap: 10, minWidth: 0, flex: 1 }}>
          <CircleDot size={11} style={{ color: statusColor, flexShrink: 0 }} />
          <span style={cardTitle}>{item.name}</span>
          <span style={sourcePill(item.source)}>{item.source === "repo" ? "built" : "image"}</span>
        </div>
        <div style={{ display: "flex", alignItems: "center", gap: 8 }}>
          <button
            onClick={redeploy}
            disabled={deploying}
            style={actionBtn}
            title="Redeploy now"
          >
            {deploying
              ? <Loader2 size={13} className="animate-spin" />
              : <RefreshCw size={13} />}
            {deploying ? "Deploying…" : "Redeploy"}
          </button>
        </div>
      </div>

      {/* ── Status line ── */}
      <div style={statusLine}>
        <span style={{ color: statusColor, fontWeight: 600 }}>{statusLabel}</span>
        {item.lastBuild && (
          <span style={{ color: INK.muted }}>
            · Last build {item.lastBuild.status} {formatRelative(item.lastBuild.finishedAt)}
          </span>
        )}
      </div>

      {/* ── Live URL ── */}
      {primaryUrl ? (
        <div style={urlRow}>
          <Globe size={13} style={{ color: "#2e7d32", flexShrink: 0 }} />
          <a href={primaryUrl} target="_blank" rel="noreferrer" style={urlLink}>
            {primaryUrl}
          </a>
          <ExternalLink size={11} style={{ color: INK.muted, flexShrink: 0 }} />
          <button onClick={copyUrl} style={iconBtn} title="Copy URL">
            {copied ? <Check size={12} style={{ color: "#2e7d32" }} /> : <Copy size={12} />}
          </button>
        </div>
      ) : (
        <div style={urlRow}>
          <Globe size={13} style={{ color: INK.muted, flexShrink: 0 }} />
          <span style={{ color: INK.muted, fontSize: "0.82rem", fontStyle: "italic" }}>
            No domain attached — ask the AI to add one.
          </span>
        </div>
      )}

      {/* ── Extra domains ── */}
      {item.domains.length > 1 && (
        <div style={{ paddingLeft: 23, display: "flex", flexDirection: "column", gap: 4, marginTop: 4 }}>
          {item.domains.slice(1).map(d => (
            <a
              key={d}
              href={`https://${d}`}
              target="_blank"
              rel="noreferrer"
              style={{ ...urlLink, fontSize: "0.78rem", color: INK.mid }}
            >
              {d} <ExternalLink size={10} style={{ display: "inline", verticalAlign: "middle" }} />
            </a>
          ))}
        </div>
      )}

      {/* ── Logs toggle ── */}
      <div style={{ marginTop: 14, borderTop: `1px solid ${INK.borderSoft}`, paddingTop: 10 }}>
        <button onClick={openLogs} style={logsToggleBtn}>
          <Terminal size={12} />
          {logsOpen ? "Hide logs" : "Show recent logs"}
          {logsOpen ? <ChevronDown size={12} /> : <ChevronRight size={12} />}
        </button>

        {logsOpen && (
          <div style={logsBox}>
            {logsLoading
              ? <span style={{ color: INK.muted, fontSize: "0.8rem" }}>Loading…</span>
              : <pre style={logsPre}>{logs || "(no logs)"}</pre>}
          </div>
        )}
      </div>
    </div>
  );
}

// ──────────────────────────────────────────────────
// Preview row
// ──────────────────────────────────────────────────

function PreviewRow({ preview }: { preview: Preview }) {
  const running = preview.state === "running";
  return (
    <div style={{ ...card, padding: "12px 16px" }}>
      <div style={{ display: "flex", alignItems: "center", gap: 10 }}>
        <CircleDot size={10} style={{ color: running ? "#2e7d32" : INK.muted, flexShrink: 0 }} />
        <span style={{ fontSize: "0.85rem", fontWeight: 600, color: INK.ink }}>{preview.name}</span>
        <span style={{ fontSize: "0.75rem", color: INK.mid }}>port {preview.port}</span>
        {preview.url && running && (
          <a href={preview.url} target="_blank" rel="noreferrer" style={urlLink}>
            {preview.url} <ExternalLink size={10} style={{ display: "inline", verticalAlign: "middle" }} />
          </a>
        )}
        <span style={{ marginLeft: "auto", fontSize: "0.75rem", color: INK.muted }}>
          Started {formatRelative(preview.startedAt)}
        </span>
      </div>
    </div>
  );
}

// ──────────────────────────────────────────────────
// Helpers
// ──────────────────────────────────────────────────

type Phase = "up" | "deploying" | "down" | "unknown";

function classifyPhase(status: string | undefined): Phase {
  const s = (status ?? "").toLowerCase();
  if (!s || s === "unknown") return "unknown";
  if (/^(running|healthy)/.test(s)) return "up";
  if (/^(starting|restarting|created|deploying|building|in_progress|queued|paused)/.test(s)) return "deploying";
  if (/^(exited|dead|failed|stopped|unhealthy|error)/.test(s)) return "down";
  return "unknown";
}

function phaseDisplay(phase: Phase, item: LiveItem): { color: string; label: string } {
  if (item.inFlightBuild) return { color: AMBER, label: `Deploying (${item.inFlightBuild.status ?? "in progress"})` };
  switch (phase) {
    case "up":        return { color: GREEN,      label: "Live" };
    case "deploying": return { color: AMBER,       label: "Starting…" };
    case "down":      return { color: DANGER,      label: "Down" };
    default:          return { color: INK.muted,   label: "Unknown" };
  }
}

function formatRelative(iso: string | undefined) {
  if (!iso) return "";
  const ms = Date.now() - new Date(iso).getTime();
  if (Number.isNaN(ms)) return "";
  const min = Math.floor(ms / 60_000);
  if (min < 1) return "just now";
  if (min < 60) return `${min}m ago`;
  const hr = Math.floor(min / 60);
  if (hr < 24) return `${hr}h ago`;
  return `${Math.floor(hr / 24)}d ago`;
}

// ──────────────────────────────────────────────────
// Sub-components
// ──────────────────────────────────────────────────

function SectionHeader({ title, count }: { title: string; count: number }) {
  return (
    <div style={sectionHeader}>
      <span style={sectionTitle}>{title}</span>
      <span style={countPill}>{count}</span>
    </div>
  );
}

function EmptySection({ icon, title, hint, promptSuggestion }: {
  icon: React.ReactNode; title: string; hint: string; promptSuggestion?: string;
}) {
  return (
    <div style={emptyBox}>
      <div style={{ marginBottom: 10 }}>{icon}</div>
      <div style={{ fontWeight: 600, fontSize: "0.9rem", color: INK.ink, marginBottom: 6 }}>{title}</div>
      <div style={{ fontSize: "0.82rem", color: INK.mid, marginBottom: promptSuggestion ? 14 : 0 }}>{hint}</div>
      {promptSuggestion && (
        <div style={promptChip}>
          <span style={{ fontSize: "0.7rem", color: INK.muted, marginRight: 6 }}>Try asking:</span>
          <span style={{ fontStyle: "italic", fontSize: "0.8rem", color: INK.mid }}>"{promptSuggestion}"</span>
        </div>
      )}
    </div>
  );
}

// ──────────────────────────────────────────────────
// Tokens
// ──────────────────────────────────────────────────

const INK = {
  ink: "#1a1a1a",
  mid: "#5f5e5a",
  muted: "#a09a90",
  border: "#e8e4dc",
  borderSoft: "#efebe1",
  cardBg: "#fff",
  fontSans: '"Outfit", "Inter", ui-sans-serif, sans-serif',
} as const;
const GREEN = "#2e7d32";
const AMBER = "#d4a04a";
const DANGER = "#c5392b";

// ──────────────────────────────────────────────────
// Styles
// ──────────────────────────────────────────────────

const pageWrap: React.CSSProperties = {
  padding: "28px 48px 64px",
  fontFamily: INK.fontSans,
  color: INK.ink,
  maxWidth: 860,
};
const centeredMsg: React.CSSProperties = {
  display: "flex", alignItems: "center", gap: 10, padding: "24px 0",
};
const sectionHeader: React.CSSProperties = {
  display: "flex", alignItems: "center", gap: 8, marginBottom: 14,
};
const sectionTitle: React.CSSProperties = {
  fontSize: "0.68rem", fontWeight: 700, letterSpacing: "0.12em",
  textTransform: "uppercase", color: INK.muted,
};
const countPill: React.CSSProperties = {
  fontSize: "0.7rem", fontWeight: 600, color: INK.mid,
  padding: "1px 7px", borderRadius: 999, background: "#f3eee4",
};
const card: React.CSSProperties = {
  background: INK.cardBg,
  border: `1px solid ${INK.border}`,
  borderRadius: 10,
  padding: "18px 20px",
};
const cardHeader: React.CSSProperties = {
  display: "flex", alignItems: "center", justifyContent: "space-between",
  gap: 12, marginBottom: 6,
};
const cardTitle: React.CSSProperties = {
  fontSize: "0.95rem", fontWeight: 700, color: INK.ink,
};
const statusLine: React.CSSProperties = {
  fontSize: "0.8rem", color: INK.mid, marginBottom: 12,
  display: "flex", alignItems: "center", gap: 6, flexWrap: "wrap",
};
const urlRow: React.CSSProperties = {
  display: "flex", alignItems: "center", gap: 8,
  background: "#f8f5f0", borderRadius: 6, padding: "8px 12px",
  marginBottom: 2,
};
const urlLink: React.CSSProperties = {
  fontSize: "0.85rem", color: INK.ink, textDecoration: "none",
  flex: 1, minWidth: 0, overflow: "hidden", textOverflow: "ellipsis",
  whiteSpace: "nowrap", display: "inline-flex", alignItems: "center", gap: 4,
};
const actionBtn: React.CSSProperties = {
  display: "inline-flex", alignItems: "center", gap: 6,
  padding: "6px 12px", border: `1px solid ${INK.border}`,
  borderRadius: 6, background: "#fff", cursor: "pointer",
  font: "inherit", fontSize: "0.78rem", fontWeight: 600, color: INK.mid,
  transition: "background 0.1s, border-color 0.1s",
};
const iconBtn: React.CSSProperties = {
  display: "inline-flex", alignItems: "center", justifyContent: "center",
  width: 26, height: 26, border: "none", background: "transparent",
  cursor: "pointer", color: INK.muted, borderRadius: 4,
  flexShrink: 0,
};
const logsToggleBtn: React.CSSProperties = {
  display: "inline-flex", alignItems: "center", gap: 6,
  fontSize: "0.75rem", fontWeight: 600, color: INK.mid,
  background: "none", border: "none", cursor: "pointer",
  font: "inherit", padding: 0,
};
const logsBox: React.CSSProperties = {
  marginTop: 10, background: "#1a1a1a", borderRadius: 6,
  padding: "12px 14px", maxHeight: 320, overflowY: "auto",
};
const logsPre: React.CSSProperties = {
  margin: 0, fontFamily: "ui-monospace, monospace",
  fontSize: "0.72rem", color: "#d4d0c8", lineHeight: 1.6,
  whiteSpace: "pre-wrap", wordBreak: "break-all",
};
const emptyBox: React.CSSProperties = {
  border: `1px dashed ${INK.border}`, borderRadius: 10,
  padding: "36px 28px", textAlign: "center",
  display: "flex", flexDirection: "column", alignItems: "center",
};
const promptChip: React.CSSProperties = {
  display: "inline-flex", alignItems: "center",
  background: "#f3eee4", borderRadius: 6,
  padding: "6px 12px", fontSize: "0.8rem",
};

function sourcePill(source: "repo" | "image"): React.CSSProperties {
  const isRepo = source === "repo";
  return {
    fontSize: "0.62rem", fontWeight: 700, letterSpacing: "0.08em",
    textTransform: "uppercase",
    color: isRepo ? "#2e6d2e" : "#3b5a78",
    background: isRepo ? "#eaf3e8" : "#e9eff5",
    padding: "1px 6px", borderRadius: 4, flexShrink: 0,
  };
}
