'use client';

/**
 * /website-analytics page shell. Mirrors the dashboard shell's layout:
 *   - PageHeader with date-range picker (presets + custom)
 *   - KPI tiles (pageviews / visitors / visits / bounces)
 *   - Two-column grid: pageviews trend + active visitors badge
 *   - Top-N tables: pages, referrers, countries
 *
 * Gracefully renders an empty state when Umami isn't configured for the
 * port - points the operator at /admin/website-analytics to set creds.
 */

import { useState, type ReactNode } from 'react';
import Link from 'next/link';
import { useRouter, useSearchParams } from 'next/navigation';
import { Globe, Info, Settings, ExternalLink } from 'lucide-react';

import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover';

import { PageHeader } from '@/components/shared/page-header';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { KPITile } from '@/components/ui/kpi-tile';
import { Skeleton } from '@/components/ui/skeleton';
import { Button } from '@/components/ui/button';
import { DateRangePicker } from '@/components/dashboard/date-range-picker';
import { isCustomRange, type DateRange } from '@/lib/analytics/range';
import { getCountryName } from '@/lib/i18n/countries';
import { useUIStore } from '@/stores/ui-store';
import {
  useUmamiActive,
  useUmamiAllCountries,
  useUmamiPageviews,
  useUmamiStats,
  useUmamiTopBrowsers,
  useUmamiTopCountries,
  useUmamiTopDevices,
  useUmamiTopOS,
  useUmamiTopPages,
  useUmamiTopReferrers,
  useUmamiWebsiteInfo,
} from './use-website-analytics';
import { PageviewsChart } from './pageviews-chart';
import { RealtimePanel } from './realtime-panel';
import { SessionsList } from './sessions-list';
import { TopList } from './top-list';
import { VisitorWorldMap } from './visitor-world-map';
import { WeeklyHeatmap } from './weekly-heatmap';

export function WebsiteAnalyticsShell() {
  const router = useRouter();
  const searchParams = useSearchParams();
  const portSlug = useUIStore((s) => s.currentPortSlug);
  // Hydrate range from URL so /website-analytics?range=90d (or
  // ?range=custom&from=…&to=…) survives refreshes and round-trips from
  // the "View all" detail pages.
  const [range, setRange] = useState<DateRange>(() => parseRangeFromQuery(searchParams));

  function handleRangeChange(next: DateRange) {
    setRange(next);
    const sp = new URLSearchParams();
    if (isCustomRange(next)) {
      sp.set('range', 'custom');
      sp.set('from', next.from);
      sp.set('to', next.to);
    } else {
      sp.set('range', next);
    }
    router.replace(`/${portSlug}/website-analytics?${sp.toString()}` as never);
  }

  const stats = useUmamiStats(range);
  const pageviews = useUmamiPageviews(range);
  const active = useUmamiActive(range);
  const topPages = useUmamiTopPages(range);
  const topReferrers = useUmamiTopReferrers(range);
  const topCountries = useUmamiTopCountries(range);
  const allCountries = useUmamiAllCountries(range);
  const topBrowsers = useUmamiTopBrowsers(range);
  const topOS = useUmamiTopOS(range);
  const topDevices = useUmamiTopDevices(range);
  const websiteInfo = useUmamiWebsiteInfo(range);
  // Prefer the live domain from the connected website; fall back to a
  // generic eyebrow until the metadata request resolves.
  const eyebrow = websiteInfo.data?.data?.domain || websiteInfo.data?.data?.name || 'Marketing';

  // API surfaces `notConfigured: true` on a 200 response (not 4xx) so
  // React Query doesn't infinite-retry - that retry loop saturated the
  // postgres pool and stalled the dev server. Single empty state covers
  // all widgets so the page doesn't show six loading spinners forever.
  const notConfigured = stats.data?.notConfigured === true;

  return (
    <div className="space-y-6">
      <PageHeader
        title="Website analytics"
        eyebrow={eyebrow}
        description="Site traffic, top pages, referrers, and audience geography."
        variant="gradient"
        actions={<DateRangePicker value={range} onChange={handleRangeChange} />}
      />

      {notConfigured ? (
        <NotConfiguredEmptyState portSlug={portSlug} />
      ) : (
        <>
          {/* Quiet-range nudge - when the range has near-zero visitors,
              surface a small banner suggesting a wider window. Avoids
              the rep thinking the integration is broken on a fresh
              port or during off-season. Threshold of 5 visitors keeps
              the banner from appearing on legitimately-busy ports. */}
          {!stats.isLoading &&
          stats.data?.data?.visitors !== undefined &&
          stats.data.data.visitors < 5 ? (
            <div className="rounded-md border border-amber-200 bg-amber-50 px-4 py-2 text-sm text-amber-900">
              <strong>Quiet range:</strong> only {stats.data.data.visitors} visitor
              {stats.data.data.visitors === 1 ? '' : 's'} in this window. Try a wider date range to
              surface meaningful trends, or confirm the marketing site is pointed at this Umami
              instance.
            </div>
          ) : null}

          {/* Realtime panel  -  collapsible "what's happening RIGHT NOW"
              strip at the very top. Polling only fires while expanded. */}
          <RealtimePanel />

          {/* Live indicator + KPI tiles  -  mirrors Umami's overview row.
              At lg the six tiles wrap to 3+3 so "Visit duration" doesn't
              truncate to "2." in the cramped 1024-with-sidebar layout.
              xl restores the single 6-column row when there's real room. */}
          <div className="grid gap-3 grid-cols-2 sm:gap-4 md:grid-cols-3 lg:grid-cols-3 xl:grid-cols-6">
            <ActiveVisitorsBadge value={active.data?.data?.visitors} loading={active.isLoading} />
            <KpiPair
              label="Visitors"
              loading={stats.isLoading}
              value={stats.data?.data?.visitors}
              prev={stats.data?.data?.comparison?.visitors}
              accent="teal"
              tooltip="Unique people who visited the site at least once. Counted by anonymous device fingerprint  -  one person across two devices counts as two."
            />
            <KpiPair
              label="Visits"
              loading={stats.isLoading}
              value={stats.data?.data?.visits}
              prev={stats.data?.data?.comparison?.visits}
              accent="success"
              tooltip="Distinct browsing sessions. A new visit starts when a visitor returns after 30 minutes of inactivity. One person can rack up multiple visits."
            />
            <KpiPair
              label="Pageviews"
              loading={stats.isLoading}
              value={stats.data?.data?.pageviews}
              prev={stats.data?.data?.comparison?.pageviews}
              accent="brand"
              tooltip="Total page loads, including refreshes and back-navigation. One visit browsing five pages = 5 pageviews."
            />
            <BounceRateTile
              loading={stats.isLoading}
              bounces={stats.data?.data?.bounces}
              visits={stats.data?.data?.visits}
              prevBounces={stats.data?.data?.comparison?.bounces}
              prevVisits={stats.data?.data?.comparison?.visits}
            />
            <VisitDurationTile
              loading={stats.isLoading}
              totaltime={stats.data?.data?.totaltime}
              visits={stats.data?.data?.visits}
              prevTotaltime={stats.data?.data?.comparison?.totaltime}
              prevVisits={stats.data?.data?.comparison?.visits}
            />
          </div>

          {/* Views (pageviews + sessions) trend */}
          <Card>
            <CardHeader>
              <CardTitle className="flex items-center gap-1.5 text-base">
                Views
                <Popover>
                  <PopoverTrigger
                    type="button"
                    aria-label="What's the difference between pageviews and sessions?"
                    className="inline-flex size-4 shrink-0 items-center justify-center rounded-full text-muted-foreground hover:bg-muted hover:text-foreground focus:outline-none focus-visible:ring-2 focus-visible:ring-brand-400"
                  >
                    <Info className="size-3.5" aria-hidden />
                  </PopoverTrigger>
                  <PopoverContent align="start" className="w-80 text-xs leading-relaxed">
                    <p className="font-semibold text-foreground">Pageviews vs Sessions</p>
                    <p className="mt-2 text-muted-foreground">
                      <strong>Pageviews</strong> = total page hits, including refreshes and
                      back-button navigation. One visitor browsing five pages = 5 pageviews.
                    </p>
                    <p className="mt-2 text-muted-foreground">
                      <strong>Sessions</strong> = distinct visitor sessions. The same person
                      browsing five pages in one sitting still counts as 1 session.
                    </p>
                    <p className="mt-2 text-muted-foreground">
                      Pages-per-session (pageviews ÷ sessions) is a rough engagement signal - higher
                      means people are exploring deeper.
                    </p>
                  </PopoverContent>
                </Popover>
              </CardTitle>
            </CardHeader>
            <CardContent>
              {pageviews.isLoading ? (
                <Skeleton className="h-[260px] w-full" />
              ) : (
                <PageviewsChart data={pageviews.data?.data ?? null} />
              )}
            </CardContent>
          </Card>

          {/* Audience: pages / referrers / countries */}
          <div className="grid gap-4 grid-cols-1 lg:grid-cols-3">
            <TopList
              title="Top pages"
              loading={topPages.isLoading}
              viewAllHref={detailHref(portSlug, 'pages', range)}
              rows={
                topPages.data?.data
                  ? topPages.data.data.map((row) => ({
                      ...row,
                      x: row.x === '/' ? 'Homepage' : row.x,
                    }))
                  : null
              }
            />
            <TopList
              title="Top referrers"
              loading={topReferrers.isLoading}
              viewAllHref={detailHref(portSlug, 'referrers', range)}
              rows={topReferrers.data?.data ?? null}
              defaultLabel="(direct)"
            />
            <TopList
              title="Top countries"
              loading={topCountries.isLoading}
              viewAllHref={detailHref(portSlug, 'countries', range)}
              rows={
                topCountries.data?.data
                  ? topCountries.data.data.map((row) => ({
                      ...row,
                      x: getCountryName(row.x, 'en'),
                    }))
                  : null
              }
            />
          </div>

          {/* Tech breakdown: browsers / OS / devices */}
          <div className="grid gap-4 grid-cols-1 lg:grid-cols-3">
            <TopList
              title="Top browsers"
              loading={topBrowsers.isLoading}
              viewAllHref={detailHref(portSlug, 'browsers', range)}
              rows={topBrowsers.data?.data ?? null}
            />
            <TopList
              title="Top operating systems"
              loading={topOS.isLoading}
              viewAllHref={detailHref(portSlug, 'os', range)}
              rows={topOS.data?.data ?? null}
            />
            <TopList
              title="Top devices"
              loading={topDevices.isLoading}
              viewAllHref={detailHref(portSlug, 'devices', range)}
              rows={
                topDevices.data?.data
                  ? topDevices.data.data.map((row) => ({
                      ...row,
                      x: row.x === '' ? 'Unknown' : row.x.charAt(0).toUpperCase() + row.x.slice(1),
                    }))
                  : null
              }
            />
          </div>

          {/* Engagement heatmap  -  full-width so the 7×24 grid has room
              to breathe and cells are large enough to hover comfortably. */}
          <WeeklyHeatmap range={range} />

          {/* Recent sessions */}
          <SessionsList range={range} />

          {/* World heatmap  -  visitor counts per country (full-width, bottom of page).
              Clicking a country emits a toast with the deep-link target;
              the rep can copy the URL to filter the Clients list by that
              nationality. A proper inline analytics filter (scoping the
              session list + KPIs to the picked country) requires the
              useUmami* hooks to accept a country param, which they don't
              yet - that's parked alongside the Phase 5 funnels work. */}
          <VisitorWorldMap
            rows={allCountries.data?.data ?? null}
            loading={allCountries.isLoading}
            onCountryClick={(iso2) => {
              router.push(`/${portSlug}/clients?nationality=${encodeURIComponent(iso2)}` as never);
            }}
          />
        </>
      )}
    </div>
  );
}

function ActiveVisitorsBadge({ value, loading }: { value?: number; loading: boolean }) {
  return (
    <div className="rounded-xl border border-border bg-card p-3 sm:p-5 shadow-sm relative overflow-hidden">
      <div className="absolute inset-x-0 top-0 h-1 bg-mint" aria-hidden />
      <div className="flex items-center gap-1.5">
        <div className="text-xs font-medium uppercase tracking-wide text-muted-foreground sm:text-xs">
          Active right now
        </div>
        <Popover>
          <PopoverTrigger
            type="button"
            aria-label="How is this counted?"
            className="inline-flex size-3.5 shrink-0 items-center justify-center rounded-full text-muted-foreground hover:bg-muted hover:text-foreground focus:outline-none focus-visible:ring-2 focus-visible:ring-brand-400"
          >
            <Info className="size-3" aria-hidden />
          </PopoverTrigger>
          <PopoverContent align="start" className="w-72 text-xs leading-relaxed">
            <p className="font-semibold text-foreground">Live visitor count</p>
            <p className="mt-2 text-muted-foreground">
              Visitors active in the last <strong>5 minutes</strong>, as reported by your analytics
              backend. This card auto-refreshes every <strong>30 seconds</strong>.
            </p>
          </PopoverContent>
        </Popover>
      </div>
      <div className="mt-1 flex items-center gap-2">
        {loading ? (
          <Skeleton className="h-7 w-12" />
        ) : (
          <>
            <span className="relative flex h-2 w-2">
              <span className="absolute inline-flex h-full w-full animate-ping rounded-full bg-emerald-400 opacity-75" />
              <span className="relative inline-flex h-2 w-2 rounded-full bg-emerald-500" />
            </span>
            <span className="text-lg font-semibold tabular-nums sm:text-2xl">{value ?? 0}</span>
          </>
        )}
      </div>
    </div>
  );
}

function KpiPair({
  label,
  value,
  prev,
  accent,
  loading,
  invertDelta = false,
  tooltip,
}: {
  label: string;
  value: number | undefined;
  prev: number | undefined;
  accent: 'brand' | 'success' | 'warning' | 'mint' | 'teal' | 'purple';
  loading: boolean;
  /** For metrics where lower is better (bounces). Flip the sign so green
   *  still means "good" in the UI. */
  invertDelta?: boolean;
  tooltip?: ReactNode;
}) {
  if (loading) {
    return (
      <div className="rounded-xl border border-border bg-card p-3 sm:p-5 shadow-sm">
        <Skeleton className="h-3 w-20" />
        <Skeleton className="mt-2 h-7 w-16" />
      </div>
    );
  }
  const v = value ?? 0;
  const p = prev ?? 0;
  let delta: number | undefined;
  if (p > 0) {
    delta = Math.round(((v - p) / p) * 100);
    if (invertDelta) delta = -delta;
  }
  return (
    <KPITile
      title={label}
      value={v.toLocaleString()}
      accent={accent}
      delta={delta}
      deltaSuffix="%"
      tooltip={tooltip}
    />
  );
}

/**
 * Bounce rate = bounces / visits × 100. Lower is better, so the delta is
 * inverted relative to the raw bounce count (a drop in bounce rate is
 * "good" → green up-arrow).
 */
function BounceRateTile({
  bounces,
  visits,
  prevBounces,
  prevVisits,
  loading,
}: {
  bounces: number | undefined;
  visits: number | undefined;
  prevBounces: number | undefined;
  prevVisits: number | undefined;
  loading: boolean;
}) {
  if (loading) {
    return (
      <div className="rounded-xl border border-border bg-card p-3 sm:p-5 shadow-sm">
        <Skeleton className="h-3 w-20" />
        <Skeleton className="mt-2 h-7 w-16" />
      </div>
    );
  }
  const rate = (visits ?? 0) > 0 ? ((bounces ?? 0) / (visits ?? 1)) * 100 : 0;
  const prevRate = (prevVisits ?? 0) > 0 ? ((prevBounces ?? 0) / (prevVisits ?? 1)) * 100 : 0;
  let delta: number | undefined;
  if (prevRate > 0) {
    // Show the raw percentage-point change (positive = bounce went up).
    // KPITile's lowerIsBetter flips the colour so a drop renders green.
    delta = Math.round(rate - prevRate);
  }
  return (
    <KPITile
      title="Bounce rate"
      value={`${rate.toFixed(1)}%`}
      accent="purple"
      delta={delta}
      deltaSuffix="%"
      lowerIsBetter
      tooltip="Share of visits that ended without a second pageview  -  i.e. someone landed, didn't click anything, and left. Lower is generally better."
    />
  );
}

/**
 * Avg visit duration = totaltime / visits (Umami returns totaltime in
 * seconds across all visits in the range). Formatted as `Xm Ys`.
 */
function VisitDurationTile({
  totaltime,
  visits,
  prevTotaltime,
  prevVisits,
  loading,
}: {
  totaltime: number | undefined;
  visits: number | undefined;
  prevTotaltime: number | undefined;
  prevVisits: number | undefined;
  loading: boolean;
}) {
  if (loading) {
    return (
      <div className="rounded-xl border border-border bg-card p-3 sm:p-5 shadow-sm">
        <Skeleton className="h-3 w-20" />
        <Skeleton className="mt-2 h-7 w-16" />
      </div>
    );
  }
  const secs = (visits ?? 0) > 0 ? (totaltime ?? 0) / (visits ?? 1) : 0;
  const prevSecs = (prevVisits ?? 0) > 0 ? (prevTotaltime ?? 0) / (prevVisits ?? 1) : 0;
  let delta: number | undefined;
  if (prevSecs > 0) {
    delta = Math.round(((secs - prevSecs) / prevSecs) * 100);
  }
  const m = Math.floor(secs / 60);
  const s = Math.round(secs % 60);
  const display = m > 0 ? `${m}m ${s}s` : `${s}s`;
  return (
    <KPITile
      title="Visit duration"
      value={display}
      accent="mint"
      delta={delta}
      deltaSuffix="%"
      tooltip="Average time a visitor spent on the site per visit. Longer usually means deeper engagement, though it can also mean people got stuck."
    />
  );
}

/** Read the range from the current URL search params, defaulting to 30d. */
function parseRangeFromQuery(searchParams: URLSearchParams | null): DateRange {
  const rawRange = searchParams?.get('range') ?? '30d';
  if (rawRange === 'custom') {
    const from = searchParams?.get('from');
    const to = searchParams?.get('to');
    if (from && to) return { kind: 'custom', from, to };
    return '30d';
  }
  if (rawRange === 'today' || rawRange === '7d' || rawRange === '30d' || rawRange === '90d') {
    return rawRange;
  }
  return '30d';
}

/** Build the "View all" href for a metric, carrying the current range. */
function detailHref(
  portSlug: string | null,
  metric: 'pages' | 'referrers' | 'countries' | 'browsers' | 'os' | 'devices',
  range: DateRange,
): string {
  const sp = new URLSearchParams();
  if (isCustomRange(range)) {
    sp.set('range', 'custom');
    sp.set('from', range.from);
    sp.set('to', range.to);
  } else {
    sp.set('range', range);
  }
  return `/${portSlug}/website-analytics/${metric}?${sp.toString()}`;
}

function NotConfiguredEmptyState({ portSlug }: { portSlug: string | null }) {
  return (
    <Card>
      <CardContent className="flex flex-col items-center gap-4 py-16 text-center">
        <Globe className="h-12 w-12 text-muted-foreground/40" aria-hidden />
        <div>
          <h3 className="text-base font-semibold">Connect Umami to see your website analytics</h3>
          <p className="mt-1 text-sm text-muted-foreground max-w-md">
            Add your Umami URL, API token (or username/password), and Website ID for this port to
            unlock pageview trends, top pages, referrers, and audience geography.
          </p>
        </div>
        <div className="flex gap-2">
          <Button asChild>
            <Link
              /* eslint-disable-next-line @typescript-eslint/no-explicit-any */
              href={`/${portSlug}/admin/website-analytics` as any}
            >
              <Settings className="mr-2 h-4 w-4" />
              Configure
            </Link>
          </Button>
          <Button asChild variant="outline">
            <a href="https://docs.umami.is/docs/api" target="_blank" rel="noreferrer">
              <ExternalLink className="mr-2 h-4 w-4" />
              Umami API docs
            </a>
          </Button>
        </div>
      </CardContent>
    </Card>
  );
}
