"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 ServicesPage() {
  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 ? "#10b981" : 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>
        <span
          style={{
            fontSize: "0.75rem",
            color: running ? "#10b981" : INK.muted,
            fontWeight: 500,
            background: running ? "#ecfdf5" : "#f4f4f5",
            padding: "2px 8px",
            borderRadius: 12,
            marginLeft: 8,
          }}
        >
          {preview.state}
        </span>
        {preview.url && running && (
          <div
            style={{
              marginLeft: "auto",
              display: "flex",
              gap: 8,
              alignItems: "center",
            }}
          >
            <a
              href={preview.url}
              target="_blank"
              rel="noreferrer"
              style={{ ...urlLink, marginLeft: 0 }}
            >
              {preview.url.replace(/^https?:\/\//, "")}{" "}
              <ExternalLink
                size={10}
                style={{ display: "inline", verticalAlign: "middle" }}
              />
            </a>
          </div>
        )}
      </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 }}
          >
            &quot;{promptSuggestion}&quot;
          </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 = "#10b981";
const AMBER = "#f59e0b";
const DANGER = "#ef4444";

// ──────────────────────────────────────────────────
// 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,
  };
}
