'use client';

/**
 * Recent-sessions card for the website-analytics page. Paginated list
 * of visitor sessions (one row per unique session) with click-through to
 * a detail sheet showing the full activity stream.
 *
 * Umami's session model: one row per anonymous-device-fingerprint+IP+UA
 * combination, with first/last visit timestamps + visit/view counts +
 * geo + browser/os/device. The detail page shows the per-event stream
 * (pageviews + custom events) within that session.
 */

import { useState } from 'react';
import { Globe, Smartphone, Monitor, Tablet, ChevronRight } from 'lucide-react';

import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { Skeleton } from '@/components/ui/skeleton';
import { Button } from '@/components/ui/button';
import { CountryFlag } from '@/components/shared/country-flag';
import { getCountryName } from '@/lib/i18n/countries';
import { useUmamiSessions } from './use-website-analytics';
import { SessionDetailSheet } from './session-detail-sheet';
import { type DateRange } from '@/lib/analytics/range';
import type { UmamiSession } from '@/lib/services/umami.service';

interface Props {
  range: DateRange;
}

export function SessionsList({ range }: Props) {
  const [page, setPage] = useState(1);
  const [selected, setSelected] = useState<UmamiSession | null>(null);
  const pageSize = 15;
  const query = useUmamiSessions(range, { page, pageSize });

  const rawSessions = query.data?.data?.data ?? [];
  // Umami's /sessions page isn't reliably ordered by activity timestamp -
  // sort by most-recent activity (lastAt) descending so the row at the top
  // is genuinely the latest session, matching the displayed timestamp.
  const sessions = [...rawSessions].sort((a, b) => {
    const la = a.lastAt ? new Date(a.lastAt).getTime() : 0;
    const lb = b.lastAt ? new Date(b.lastAt).getTime() : 0;
    return lb - la;
  });
  const total = query.data?.data?.count ?? 0;
  const hasMore = page * pageSize < total;

  return (
    <>
      <Card>
        <CardHeader>
          <CardTitle className="text-base">Recent sessions</CardTitle>
        </CardHeader>
        <CardContent>
          {query.isLoading ? (
            <div className="space-y-2">
              {Array.from({ length: 5 }).map((_, i) => (
                <Skeleton key={i} className="h-12 w-full" />
              ))}
            </div>
          ) : sessions.length === 0 ? (
            <div className="py-6 text-center text-sm text-muted-foreground">
              No sessions in this range.
            </div>
          ) : (
            <>
              <ul className="divide-y divide-border">
                {sessions.map((s, i) => (
                  // Umami's sessions endpoint can return rows with the
                  // same session id within a page when activity straddles
                  // a bucket boundary. Compose the key to dedupe.
                  <li key={`${s.id}-${i}`}>
                    <button
                      type="button"
                      onClick={() => setSelected(s)}
                      className="group flex w-full items-center justify-between gap-3 py-3 text-left transition hover:bg-muted/40 -mx-2 px-2 rounded"
                    >
                      <div className="flex min-w-0 flex-1 items-center gap-3">
                        <DeviceIcon device={s.device} />
                        <div className="min-w-0 flex-1">
                          <div className="flex flex-wrap items-center gap-x-2 gap-y-0.5 text-sm">
                            {s.country ? (
                              <CountryFlag code={s.country} className="h-3 w-4" decorative />
                            ) : null}
                            <span className="font-medium">
                              {getCountryName(s.country, 'en') || 'Unknown'}
                            </span>
                            {s.city ? (
                              <span className="text-muted-foreground">{s.city}</span>
                            ) : null}
                          </div>
                          <div className="mt-0.5 truncate text-xs text-muted-foreground">
                            {s.browser} · {s.os} · {fmtTime(s.lastAt ?? s.firstAt)}
                          </div>
                        </div>
                      </div>
                      <div className="flex shrink-0 items-center gap-3 text-xs text-muted-foreground">
                        <span className="tabular-nums">{s.views.toLocaleString()} views</span>
                        <ChevronRight
                          className="size-4 opacity-0 transition group-hover:opacity-100"
                          aria-hidden
                        />
                      </div>
                    </button>
                  </li>
                ))}
              </ul>
              <div className="mt-4 flex items-center justify-between text-xs text-muted-foreground">
                <span>
                  Showing {(page - 1) * pageSize + 1}–{Math.min(page * pageSize, total)} of{' '}
                  {total.toLocaleString()}
                </span>
                <div className="flex gap-2">
                  <Button
                    size="sm"
                    variant="outline"
                    onClick={() => setPage((p) => Math.max(1, p - 1))}
                    disabled={page === 1}
                  >
                    Previous
                  </Button>
                  <Button
                    size="sm"
                    variant="outline"
                    onClick={() => setPage((p) => p + 1)}
                    disabled={!hasMore}
                  >
                    Next
                  </Button>
                </div>
              </div>
            </>
          )}
        </CardContent>
      </Card>

      <SessionDetailSheet session={selected} range={range} onClose={() => setSelected(null)} />
    </>
  );
}

function DeviceIcon({ device }: { device: string }) {
  const cls = 'size-5 shrink-0 text-muted-foreground';
  switch (device.toLowerCase()) {
    case 'mobile':
      return <Smartphone className={cls} aria-hidden />;
    case 'tablet':
      return <Tablet className={cls} aria-hidden />;
    case 'desktop':
    case 'laptop':
      return <Monitor className={cls} aria-hidden />;
    default:
      return <Globe className={cls} aria-hidden />;
  }
}

function fmtTime(iso: string): string {
  const d = new Date(iso);
  if (isNaN(d.getTime())) return iso;
  return d.toLocaleString('en-US', { dateStyle: 'medium', timeStyle: 'short' });
}
