"use client";

/**
 * Project header URL chips — surfaces the user's "front door" URLs
 * next to the status pill so they're one click away from any tab.
 *
 *  - Live  chips → every Coolify endpoint with an attached fqdn
 *  - Prev. chips → every running dev-server preview
 *
 * When there are more than MAX_VISIBLE total links, extras collapse
 * into a "+N" pill that opens a popover with the full list as
 * clickable links (was a `title=` tooltip before — popover is
 * discoverable on touch and keyboard, tooltip wasn't).
 *
 * Polls anatomy every 30s for URL chips (stage pill polls faster while deploying).
 */

import { ExternalLink, Globe, Play, Zap } from "lucide-react";
import { useEffect, useRef, useState } from "react";
import { dashboardBridgeScriptUrl } from "@/lib/dashboard-bridge-url";
import { useAnatomy } from "./use-anatomy";

const MAX_VISIBLE = 3;

const START_PREVIEW_PROMPT_BASE =
  "Start the dev server for the user-facing app in this project on port 3000 and share the preview URL so I can see what it looks like. If multiple services exist (frontend + API + worker), pick the user-facing one. If a server is already running, just share the URL.";

interface Props {
  projectId: string;
}

export function ProjectHeaderUrls({ projectId }: Props) {
  /** Rare churn — stage pill polls when deploys are active; 30s is plenty for new preview URLs */
  const { anatomy } = useAnatomy(projectId, { pollMs: 30000 });
  const [overflowOpen, setOverflowOpen] = useState(false);
  const overflowRef = useRef<HTMLDivElement>(null);

  // Close popover on outside click / Escape — both expected by users
  // who don't realize it's modal-ish.
  useEffect(() => {
    if (!overflowOpen) return;
    function onDoc(e: MouseEvent) {
      if (overflowRef.current && !overflowRef.current.contains(e.target as Node)) {
        setOverflowOpen(false);
      }
    }
    function onKey(e: KeyboardEvent) {
      if (e.key === "Escape") setOverflowOpen(false);
    }
    document.addEventListener("mousedown", onDoc);
    document.addEventListener("keydown", onKey);
    return () => {
      document.removeEventListener("mousedown", onDoc);
      document.removeEventListener("keydown", onKey);
    };
  }, [overflowOpen]);

  if (!anatomy) return null;

  const liveLinks = anatomy.hosting.live
    .filter((l) => !!l.fqdn)
    .map((l) => ({
      key: l.uuid,
      kind: "live" as const,
      label: l.name,
      url: ensureScheme(l.fqdn!),
      host: stripScheme(l.fqdn!),
    }));

  const previewLinks = anatomy.hosting.previews
    .filter((p) => p.state === "running" && p.url)
    .map((p) => ({
      key: p.id,
      kind: "preview" as const,
      label: `${p.name}:${p.port}`,
      url: p.url,
      host: hostOf(p.url),
    }));

  const allLinks = [...liveLinks, ...previewLinks];

  // Empty header is dishonest UX — the user has no idea whether they
  // SHOULD have a preview or whether nothing has been built yet. Surface
  // a one-click "Start preview" affordance instead. Clicking it opens
  // the chat panel (if collapsed) and fires the canned prompt; the
  // moment dev_server_start lands in anatomy (poll cadence: 4s) this
  // button is replaced by the real preview chip.
  if (allLinks.length === 0) {
    return (
      <button
        type="button"
        onClick={() => {
          const bridgeUrl = dashboardBridgeScriptUrl();
          const prompt =
            START_PREVIEW_PROMPT_BASE +
            ` After startup, add the preview picker script once (e.g. next/script in the root layout): ${bridgeUrl}`;
          window.dispatchEvent(
            new CustomEvent("vibn:chat-prompt", {
              detail: { prompt, scopeProjectId: projectId },
            }),
          );
        }}
        title="Start the dev server and share a preview URL in chat"
        style={startPreviewBtn}
        onMouseEnter={(e) => {
          e.currentTarget.style.background = "#f6f2ec";
          e.currentTarget.style.borderColor = "#d9d2c5";
          e.currentTarget.style.color = "#1a1a1a";
        }}
        onMouseLeave={(e) => {
          e.currentTarget.style.background = "#fff";
          e.currentTarget.style.borderColor = "#e8e4dc";
          e.currentTarget.style.color = "#6b665e";
        }}
      >
        <Play size={10} style={{ flexShrink: 0 }} fill="currentColor" />
        <span>Preview</span>
      </button>
    );
  }

  const visible = allLinks.slice(0, MAX_VISIBLE);
  const hidden = allLinks.slice(MAX_VISIBLE);

  return (
    <div style={wrap}>
      {visible.map((l) => (
        <a
          key={l.key}
          href={l.url}
          target="_blank"
          rel="noreferrer"
          style={l.kind === "live" ? liveChip : previewChip}
          title={`${l.label} → ${l.host}`}
        >
          {l.kind === "live"
            ? <Globe size={11} style={{ flexShrink: 0 }} />
            : <Zap size={11} style={{ flexShrink: 0 }} />}
          <span style={chipLabel}>{l.label}</span>
          <ExternalLink size={10} style={{ flexShrink: 0, opacity: 0.7 }} />
        </a>
      ))}
      {hidden.length > 0 && (
        <div ref={overflowRef} style={{ position: "relative" }}>
          <button
            type="button"
            onClick={() => setOverflowOpen((v) => !v)}
            aria-expanded={overflowOpen}
            aria-haspopup="true"
            style={overflowPill}
          >
            +{hidden.length}
          </button>
          {overflowOpen && (
            <div role="menu" style={popoverStyle}>
              <div style={popoverHeader}>{hidden.length} more endpoint{hidden.length === 1 ? "" : "s"}</div>
              {hidden.map((l) => (
                <a
                  key={l.key}
                  href={l.url}
                  target="_blank"
                  rel="noreferrer"
                  style={popoverItem}
                  onClick={() => setOverflowOpen(false)}
                  role="menuitem"
                >
                  {l.kind === "live"
                    ? <Globe size={12} style={{ flexShrink: 0, color: "#1a1a1a" }} />
                    : <Zap size={12} style={{ flexShrink: 0, color: "#3d5afe" }} />}
                  <div style={popoverItemText}>
                    <div style={popoverItemLabel}>{l.label}</div>
                    <div style={popoverItemHost}>{l.host}</div>
                  </div>
                  <ExternalLink size={11} style={{ flexShrink: 0, opacity: 0.5 }} />
                </a>
              ))}
            </div>
          )}
        </div>
      )}
    </div>
  );
}

// ──────────────────────────────────────────────────

function ensureScheme(host: string): string {
  if (/^https?:\/\//i.test(host)) return host;
  return `https://${host}`;
}
function stripScheme(host: string): string {
  return host.replace(/^https?:\/\//i, "").replace(/\/$/, "");
}
function hostOf(url: string): string {
  try { return new URL(url).host; } catch { return url; }
}

const wrap: React.CSSProperties = {
  display: "flex", gap: 6, alignItems: "center",
  flexWrap: "wrap",
};

const chipBase: React.CSSProperties = {
  display: "inline-flex", alignItems: "center", gap: 6,
  padding: "4px 10px", borderRadius: 4,
  fontSize: "0.72rem", fontWeight: 500,
  textDecoration: "none",
  whiteSpace: "nowrap", maxWidth: 220,
  border: "1px solid",
  fontFamily: '"Outfit", "Inter", ui-sans-serif, sans-serif',
  transition: "background 0.15s, border-color 0.15s",
};
const liveChip: React.CSSProperties = {
  ...chipBase,
  color: "#1a1a1a", borderColor: "#e8e4dc", background: "#fff",
};
const previewChip: React.CSSProperties = {
  ...chipBase,
  color: "#3d5afe", borderColor: "#3d5afe33", background: "#3d5afe08",
};
const startPreviewBtn: React.CSSProperties = {
  ...chipBase,
  color: "#6b665e",
  borderColor: "#e8e4dc",
  background: "#fff",
  cursor: "pointer",
  font: "inherit",
  fontSize: "0.72rem",
  fontWeight: 500,
  transition: "background 0.15s, border-color 0.15s, color 0.15s",
};
const chipLabel: React.CSSProperties = {
  overflow: "hidden", textOverflow: "ellipsis",
  maxWidth: 180,
};
const overflowPill: React.CSSProperties = {
  ...chipBase,
  borderColor: "#e8e4dc",
  color: "#6b665e",
  background: "#f8f5f0",
  cursor: "pointer",
  font: "inherit",
  fontSize: "0.72rem",
  fontWeight: 500,
};

const popoverStyle: React.CSSProperties = {
  position: "absolute",
  top: "calc(100% + 6px)",
  right: 0,
  minWidth: 240,
  maxWidth: 360,
  padding: 4,
  background: "#fff",
  border: "1px solid #e8e4dc",
  borderRadius: 6,
  boxShadow: "0 6px 20px rgba(0,0,0,0.08)",
  zIndex: 50,
  display: "flex",
  flexDirection: "column",
  gap: 2,
  fontFamily: '"Outfit", "Inter", ui-sans-serif, sans-serif',
};
const popoverHeader: React.CSSProperties = {
  padding: "6px 10px 4px",
  fontSize: "0.65rem",
  textTransform: "uppercase",
  letterSpacing: "0.04em",
  color: "#a09a90",
  fontWeight: 600,
};
const popoverItem: React.CSSProperties = {
  display: "flex",
  alignItems: "center",
  gap: 8,
  padding: "8px 10px",
  borderRadius: 4,
  textDecoration: "none",
  color: "#1a1a1a",
  fontSize: "0.78rem",
  cursor: "pointer",
};
const popoverItemText: React.CSSProperties = {
  flex: 1,
  minWidth: 0,
  overflow: "hidden",
};
const popoverItemLabel: React.CSSProperties = {
  fontWeight: 500,
  whiteSpace: "nowrap",
  overflow: "hidden",
  textOverflow: "ellipsis",
};
const popoverItemHost: React.CSSProperties = {
  fontSize: "0.7rem",
  color: "#a09a90",
  whiteSpace: "nowrap",
  overflow: "hidden",
  textOverflow: "ellipsis",
};
