"use client";

/**
 * /admin/sessions — Session Explorer
 *
 * Superadmin view for drilling into individual visitor journeys.
 * Shared brand selector + range pills + filter chips above a
 * sortable session table. Clicking a row navigates to
 * /admin/sessions/[sessionId]?brandId=X for the full timeline.
 *
 * Designed to answer: "which sessions converted, and what did the
 * user actually do before they converted?" — the kind of question
 * that's been a raw-SQL panel until now.
 */

import { useCallback, useEffect, useMemo, useState } from "react";
import Link from "next/link";
import {
  Footprints, Phone, FileCheck, CalendarCheck, MousePointerClick,
  Clock, Eye, Loader2, ArrowRight, Users, Search,
  Monitor, Smartphone, Tablet, Globe,
} from "lucide-react";
import {
  PageHeader, SectionHeader, Card, CardHeader, EmptyState,
  TableSkeleton,
} from "@/components/admin";

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

interface BrandOption { id: string; name: string }

interface SessionRow {
  sessionId: string;
  internalId: string;
  startedAt: string;
  lastSeenAt: string;
  durationMs: number;
  pageCount: number;
  eventCount: number;
  conversionCount: number;
  topConversionType: string | null;
  source: string;
  medium: string | null;
  campaign: string | null;
  referrer: string | null;
  country: string | null;
  device: string | null;
  browser?: string | null;
  os?: string | null;
  city?: string | null;
  region?: string | null;
}

interface SessionsResponse {
  sessions: SessionRow[];
  total: number;
  page: number;
  limit: number;
  hasMore: boolean;
  error?: string;
}

type Filter = "all" | "conversions" | "phone" | "form" | "booking";
type Sort   = "recent" | "interactions" | "duration";
type Range  = "1d" | "7d" | "30d" | "90d";

const FILTER_CHIPS: Array<{ id: Filter; label: string; icon: typeof Phone }> = [
  { id: "all",         label: "All",          icon: Users },
  { id: "conversions", label: "Conversions",  icon: MousePointerClick },
  { id: "phone",       label: "Phone calls",  icon: Phone },
  { id: "form",        label: "Form submits", icon: FileCheck },
  { id: "booking",     label: "Bookings",     icon: CalendarCheck },
];

const RANGES: Array<{ id: Range; label: string }> = [
  { id: "1d",  label: "Today" },
  { id: "7d",  label: "7d" },
  { id: "30d", label: "30d" },
  { id: "90d", label: "90d" },
];

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

function formatDuration(ms: number): string {
  if (ms < 1000) return "<1s";
  const s = Math.floor(ms / 1000);
  if (s < 60) return `${s}s`;
  const m = Math.floor(s / 60);
  const rs = s % 60;
  if (m < 60) return `${m}m ${rs}s`;
  const h = Math.floor(m / 60);
  const rm = m % 60;
  return `${h}h ${rm}m`;
}

function formatRelative(iso: string): string {
  try {
    const delta = Date.now() - new Date(iso).getTime();
    const s = Math.floor(delta / 1000);
    if (s < 60) return `${s}s ago`;
    const m = Math.floor(s / 60);
    if (m < 60) return `${m}m ago`;
    const h = Math.floor(m / 60);
    if (h < 24) return `${h}h ago`;
    const d = Math.floor(h / 24);
    return `${d}d ago`;
  } catch { return ""; }
}

// Canonical type → pill colour.
function conversionPillColor(canonical: string | null): string {
  switch (canonical) {
    // Tier 1 — hard conversions
    case "appointment_booked":     return "bg-emerald-50 text-emerald-700 border-emerald-200";
    case "form_submitted":         return "bg-blue-50 text-blue-700 border-blue-200";
    case "phone_call":             return "bg-violet-50 text-violet-700 border-violet-200";
    case "email_contact":          return "bg-blue-50 text-blue-700 border-blue-200";
    case "sms_contact":            return "bg-violet-50 text-violet-700 border-violet-200";
    case "purchase":               return "bg-amber-50 text-amber-700 border-amber-200";
    // Tier 2 — soft / engagement
    case "appointment_attempted":  return "bg-teal-50 text-teal-700 border-teal-200";
    case "form_started":           return "bg-slate-100 text-slate-600 border-slate-200";
    case "appointment_intent":     return "bg-orange-50 text-orange-700 border-orange-200";
    case "chat_initiated":         return "bg-cyan-50 text-cyan-700 border-cyan-200";
    case "newsletter_signup":      return "bg-cyan-50 text-cyan-700 border-cyan-200";
    case "add_to_cart":            return "bg-orange-50 text-orange-700 border-orange-200";
    case "checkout_started":       return "bg-teal-50 text-teal-700 border-teal-200";
    case "file_download":          return "bg-slate-50 text-slate-700 border-slate-200";
    case "waitlist_signup":        return "bg-amber-50 text-amber-700 border-amber-200";
    default:                       return "bg-slate-100 text-slate-600 border-slate-200";
  }
}

// Device class → lucide icon. Falls back to Monitor so rows with
// an unknown / missing device value still render a consistent chip
// next to the country code rather than a "?" placeholder.
function DeviceIcon({ device }: { device: string | null | undefined }) {
  const d = (device ?? "").toLowerCase();
  if (d === "mobile") return <Smartphone className="w-3 h-3 text-slate-500" />;
  if (d === "tablet") return <Tablet className="w-3 h-3 text-slate-500" />;
  return <Monitor className="w-3 h-3 text-slate-500" />;
}

function deviceLabel(device: string | null | undefined): string {
  const d = (device ?? "").toLowerCase();
  if (d === "mobile") return "Mobile";
  if (d === "tablet") return "Tablet";
  if (d === "desktop") return "Desktop";
  return "Unknown";
}

function conversionPillLabel(canonical: string | null): string {
  switch (canonical) {
    // Tier 1 — hard conversions
    case "appointment_booked":     return "Appointment";
    case "form_submitted":         return "Form";
    case "phone_call":             return "Phone";
    case "email_contact":          return "Email";
    case "sms_contact":            return "SMS";
    case "purchase":               return "Purchase";
    // Tier 2 — soft / engagement
    case "appointment_attempted":  return "Booking attempt";
    case "form_started":           return "Form started";
    case "appointment_intent":     return "Intent";
    case "chat_initiated":         return "Chat";
    case "newsletter_signup":      return "Newsletter";
    case "add_to_cart":            return "Add to cart";
    case "checkout_started":       return "Checkout";
    case "file_download":          return "Download";
    case "waitlist_signup":        return "Waitlist";
    default:                       return canonical ?? "—";
  }
}

// ─── Page ──────────────────────────────────────────────────────────

export default function SessionExplorerPage() {
  const [brands, setBrands] = useState<BrandOption[]>([]);
  const [brandId, setBrandId] = useState<string>("");
  const [filter, setFilter]   = useState<Filter>("conversions");
  const [range, setRange]     = useState<Range>("30d");
  const [sort, setSort]       = useState<Sort>("recent");
  const [page, setPage]       = useState(1);
  const [query, setQuery]     = useState("");
  const [feed, setFeed]       = useState<SessionsResponse | null>(null);
  const [loading, setLoading] = useState(false);

  // Mount-once: brand list.
  useEffect(() => {
    fetch("/api/admin/brands?limit=500")
      .then((r) => r.ok ? r.json() : null)
      .then((d) => {
        if (Array.isArray(d?.brands)) {
          const list: BrandOption[] = d.brands.map((b: { id: string; name: string }) => ({ id: b.id, name: b.name }));
          setBrands(list);
          if (!brandId && list.length > 0) setBrandId(list[0].id);
        }
      })
      .catch(() => {});
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

  const fetchSessions = useCallback(() => {
    if (!brandId) return;
    const params = new URLSearchParams({
      brandId, filter, range, sort,
      page: String(page), limit: "25",
    });
    setLoading(true);
    fetch(`/api/admin/sessions?${params.toString()}`)
      .then((r) => r.ok ? r.json() : null)
      .then((d: SessionsResponse | null) => setFeed(d))
      .finally(() => setLoading(false));
  }, [brandId, filter, range, sort, page]);

  useEffect(() => { fetchSessions(); }, [fetchSessions]);
  useEffect(() => { setPage(1); }, [brandId, filter, range, sort]);

  const filteredSessions = useMemo(() => {
    if (!feed?.sessions) return [];
    if (!query.trim()) return feed.sessions;
    const q = query.toLowerCase();
    return feed.sessions.filter((s) =>
      s.sessionId.toLowerCase().includes(q)
      || (s.source ?? "").toLowerCase().includes(q)
      || (s.country ?? "").toLowerCase().includes(q)
      || (s.referrer ?? "").toLowerCase().includes(q));
  }, [feed, query]);

  return (
    <div className="space-y-6">
      <PageHeader
        title="Session Explorer"
        subtitle="Individual visitor journeys with full event + conversion timelines"
        icon={Footprints}
        actions={
          <div className="flex items-center gap-2">
            <select
              value={brandId}
              onChange={(e) => setBrandId(e.target.value)}
              className="px-3 py-1.5 text-xs bg-white border border-slate-200 rounded-lg min-w-[220px]"
            >
              {brands.length === 0 && <option value="">Loading brands…</option>}
              {brands.map((b) => (<option key={b.id} value={b.id}>{b.name}</option>))}
            </select>
            <div className="inline-flex bg-slate-100 rounded-lg p-0.5">
              {RANGES.map((r) => (
                <button
                  key={r.id}
                  onClick={() => setRange(r.id)}
                  className={`px-2.5 py-1 text-[11px] font-semibold rounded-md transition-colors ${
                    range === r.id ? "bg-white text-slate-900 shadow-sm" : "text-slate-500 hover:text-slate-700"
                  }`}
                >{r.label}</button>
              ))}
            </div>
          </div>
        }
      />

      {/* Filter chips + sort + search */}
      <section>
        <SectionHeader
          title="Sessions"
          right={
            <div className="flex items-center gap-2">
              <select
                value={sort}
                onChange={(e) => setSort(e.target.value as Sort)}
                className="px-3 py-1.5 text-[11px] bg-white border border-slate-200 rounded-lg"
              >
                <option value="recent">Most recent</option>
                <option value="interactions">Most interactions</option>
                <option value="duration">Longest duration</option>
              </select>
            </div>
          }
        />
        <div className="flex items-center gap-2 flex-wrap mb-3">
          {FILTER_CHIPS.map(({ id, label, icon: Icon }) => (
            <button
              key={id}
              onClick={() => setFilter(id)}
              className={`inline-flex items-center gap-1.5 px-2.5 py-1 text-[11px] font-semibold rounded-md border transition-colors ${
                filter === id
                  ? "bg-slate-900 text-white border-slate-900"
                  : "bg-white text-slate-600 border-slate-200 hover:bg-slate-50"
              }`}
            >
              <Icon className="w-3 h-3" />{label}
            </button>
          ))}
          <div className="relative ml-auto">
            <Search className="absolute left-2 top-1/2 -translate-y-1/2 w-3.5 h-3.5 text-slate-400" />
            <input
              type="search"
              value={query}
              onChange={(e) => setQuery(e.target.value)}
              placeholder="Filter by sessionId, source, country…"
              className="pl-7 pr-3 py-1.5 text-[11px] bg-white border border-slate-200 rounded-lg min-w-[260px]"
            />
          </div>
        </div>

        <Card>
          <CardHeader
            title="Session list"
            right={feed && <span className="text-[10px] text-slate-400">{feed.total.toLocaleString()} total</span>}
          />
          {loading && !feed ? (
            <TableSkeleton rows={6} />
          ) : (!feed || filteredSessions.length === 0) ? (
            <EmptyState
              icon={Footprints}
              title="No sessions found"
              description={filter === "all"
                ? "No TrackedSession rows in the selected window for this brand."
                : `No sessions matching filter \"${filter}\" in the selected window.`}
            />
          ) : (
            <>
              <table className="w-full text-xs">
                <thead className="text-[10px] font-semibold uppercase tracking-widest text-slate-400 border-b border-slate-100 bg-slate-50/40">
                  <tr>
                    <th className="text-left px-4 py-2">Session</th>
                    <th className="text-left px-4 py-2">Source</th>
                    <th className="text-right px-4 py-2">Duration</th>
                    <th className="text-right px-4 py-2">Pages</th>
                    <th className="text-right px-4 py-2">Events</th>
                    <th className="text-right px-4 py-2">Conversions</th>
                    <th className="text-right px-4 py-2">When</th>
                  </tr>
                </thead>
                <tbody className="divide-y divide-slate-100">
                  {filteredSessions.map((s) => (
                    <tr key={s.internalId} className="hover:bg-slate-50 transition-colors">
                      <td className="px-4 py-2">
                        <Link
                          href={`/admin/sessions/${encodeURIComponent(s.sessionId)}?brandId=${encodeURIComponent(brandId)}`}
                          className="inline-flex items-center gap-1.5 font-mono text-[11px] text-slate-700 hover:text-slate-900"
                        >
                          <span className="font-semibold">{s.sessionId.slice(0, 12)}</span>…
                          <ArrowRight className="w-3 h-3 text-slate-400" />
                        </Link>
                        <span className="inline-flex items-center gap-1.5 text-[10px] text-slate-500 mt-0.5">
                          <DeviceIcon device={s.device} />
                          <span>{deviceLabel(s.device)}</span>
                          {s.country && (
                            <>
                              <span className="text-slate-300">·</span>
                              <Globe className="w-2.5 h-2.5 text-slate-400" />
                              <span className="font-mono">{s.country}</span>
                            </>
                          )}
                        </span>
                      </td>
                      <td className="px-4 py-2">
                        <span className="inline-flex items-center gap-1 text-[11px] text-slate-700">
                          {s.source}
                        </span>
                        {s.medium && <p className="text-[10px] text-slate-400 mt-0.5">{s.medium}</p>}
                      </td>
                      <td className="px-4 py-2 text-right tabular-nums text-slate-600">
                        <span className="inline-flex items-center gap-1 justify-end">
                          <Clock className="w-3 h-3 text-slate-400" />{formatDuration(s.durationMs)}
                        </span>
                      </td>
                      <td className="px-4 py-2 text-right tabular-nums text-slate-600">
                        <span className="inline-flex items-center gap-1 justify-end">
                          <Eye className="w-3 h-3 text-slate-400" />{s.pageCount}
                        </span>
                      </td>
                      <td className="px-4 py-2 text-right tabular-nums text-slate-600">{s.eventCount.toLocaleString()}</td>
                      <td className="px-4 py-2 text-right">
                        {s.conversionCount > 0 ? (
                          <span className={`inline-flex items-center gap-1 text-[10px] font-bold uppercase tracking-wide px-1.5 py-0.5 rounded border ${conversionPillColor(s.topConversionType)}`}>
                            {s.conversionCount} · {conversionPillLabel(s.topConversionType)}
                          </span>
                        ) : (
                          <span className="text-[10px] text-slate-400">—</span>
                        )}
                      </td>
                      <td className="px-4 py-2 text-right text-[10px] text-slate-500">
                        {formatRelative(s.startedAt)}
                      </td>
                    </tr>
                  ))}
                </tbody>
              </table>
              {feed.hasMore && (
                <div className="flex items-center justify-between px-4 py-3 border-t border-slate-100 bg-slate-50/40">
                  <p className="text-[10px] text-slate-500">Page {feed.page}</p>
                  <div className="flex items-center gap-2">
                    <button
                      onClick={() => setPage((p) => Math.max(1, p - 1))}
                      disabled={page <= 1}
                      className="px-3 py-1 text-[11px] bg-white border border-slate-200 rounded-md disabled:opacity-50"
                    >Prev</button>
                    <button
                      onClick={() => setPage((p) => p + 1)}
                      className="px-3 py-1 text-[11px] bg-slate-900 text-white rounded-md inline-flex items-center gap-1"
                    >
                      Next {loading && <Loader2 className="w-3 h-3 animate-spin" />}
                    </button>
                  </div>
                </div>
              )}
            </>
          )}
        </Card>
      </section>
    </div>
  );
}
