import type { LucideIcon } from 'lucide-react';
import type { FacetEntry } from './useTorrentFilters';
import { useState } from 'react';
import { NavLink } from 'react-router';
import {
  ArrowDownToLine,
  ArrowUpFromLine,
  ChevronRight,
  CircleAlert,
  Folder,
  Gauge,
  ListChecks,
  Plug,
  Radio,
  Settings,
  Tag,
  Waves,
} from 'lucide-react';
import { TRANSMISSION_SECTIONS, transmissionSectionPath, type TransmissionSectionId } from './shared';
import { formatSpeed } from './format';
import { useSessionStats, useTorrents } from './useTransmissionData';
import { buildFacets, countByStatus, STATUS_FILTERS, useTorrentFilters } from './useTorrentFilters';

// Left panel of /transmission: live throughput on top, the three sections, then the facet filters.
//
// Sections are real links (cmd-click, back button, reload) with active state from react-router's NavLink.
// Filters are buttons because they write to the query string of the page you are already on — they are
// still addressable, just not a different route.
//
// The facet lists are derived from the torrents already in the cache, not fetched separately: Transmission
// has no "list my labels" RPC, and asking for one would mean a second poll returning the same data.

const ICONS: Record<TransmissionSectionId, LucideIcon> = {
  torrents: ListChecks,
  stats: Gauge,
  settings: Settings,
  connection: Plug,
};

const ROW = 'group relative flex items-center gap-3 rounded-lg px-3 py-2 text-left text-sm transition-colors';

export const TransmissionNav = () => {
  const { torrents } = useTorrents();
  const { stats } = useSessionStats();
  const { filters, setStatus, toggle, clearFilters } = useTorrentFilters();

  const facets = buildFacets(torrents);
  const counts = countByStatus(torrents);

  return (
    <div className="flex h-full flex-col overflow-y-auto bg-muted/30">
      <div className="flex items-center gap-3 px-4 py-4">
        <div className="flex h-9 w-9 items-center justify-center rounded-xl bg-amber-500/15 text-amber-500 ring-1 ring-black/5">
          <Waves className="h-5 w-5" />
        </div>
        <div className="min-w-0">
          <div className="truncate text-sm font-semibold leading-tight">Transmission</div>
          <div className="flex items-center gap-2.5 text-xs text-muted-foreground">
            <span className="flex items-center gap-1 tabular-nums">
              <ArrowDownToLine className="h-3 w-3 text-blue-500" />
              {formatSpeed(stats?.downloadSpeed) || '0'}
            </span>
            <span className="flex items-center gap-1 tabular-nums">
              <ArrowUpFromLine className="h-3 w-3 text-emerald-500" />
              {formatSpeed(stats?.uploadSpeed) || '0'}
            </span>
          </div>
        </div>
      </div>

      <nav className="flex flex-col gap-0.5 px-2 pb-3">
        {TRANSMISSION_SECTIONS.map(({ id, label }) => {
          const Icon = ICONS[id];
          return (
            <NavLink
              key={id}
              to={transmissionSectionPath(id)}
              className={({ isActive }) =>
                `${ROW} ${
                  isActive
                    ? 'bg-primary/10 font-medium text-primary'
                    : 'text-muted-foreground hover:bg-muted hover:text-foreground'
                }`
              }
            >
              {({ isActive }) => (
                <>
                  {isActive && (
                    <span className="absolute left-0 top-1/2 h-5 w-1 -translate-y-1/2 rounded-r-full bg-primary" />
                  )}
                  <Icon
                    className={`h-4 w-4 shrink-0 ${isActive ? 'text-primary' : 'text-muted-foreground group-hover:text-foreground'}`}
                  />
                  <span className="flex-1">{label}</span>
                  {id === 'torrents' && torrents.length > 0 && (
                    <span className="text-xs tabular-nums text-muted-foreground">{torrents.length}</span>
                  )}
                </>
              )}
            </NavLink>
          );
        })}
      </nav>

      <div className="flex items-center justify-between px-5 pb-1 pt-1">
        <span className="text-[10px] font-semibold uppercase tracking-wide text-muted-foreground">Filter</span>
        {filters.isFiltered && (
          <button type="button" onClick={clearFilters} className="text-[10px] font-medium text-primary hover:underline">
            clear
          </button>
        )}
      </div>

      <div className="flex flex-col gap-0.5 px-2 pb-2">
        {STATUS_FILTERS.map(({ id, label }) => (
          <FilterRow
            key={id}
            label={label}
            count={counts[id]}
            active={filters.status === id}
            onClick={() => setStatus(id)}
          />
        ))}
        {facets.errors > 0 && (
          <FilterRow
            icon={CircleAlert}
            label="Tracker errors"
            count={facets.errors}
            active={filters.errorOnly}
            tone="text-amber-500"
            onClick={() => toggle('error', '1', filters.errorOnly ? '1' : null)}
          />
        )}
      </div>

      <FacetGroup
        title="Labels"
        icon={Tag}
        entries={facets.labels}
        selected={filters.label}
        onPick={(v) => toggle('label', v, filters.label)}
      />
      <FacetGroup
        title="Trackers"
        icon={Radio}
        entries={facets.trackers}
        selected={filters.tracker}
        onPick={(v) => toggle('tracker', v, filters.tracker)}
      />
      <FacetGroup
        title="Locations"
        icon={Folder}
        entries={facets.dirs}
        selected={filters.downloadDir}
        onPick={(v) => toggle('dir', v, filters.downloadDir)}
        // A path is only distinguishable by its tail, and the panel is 22% of the window wide.
        renderLabel={(v) => v.split('/').filter(Boolean).slice(-1)[0] || v}
      />

      <div className="mt-auto px-4 py-3 text-[10px] text-muted-foreground">
        {stats ? `${stats.activeTorrentCount} active · ${stats.pausedTorrentCount} paused` : 'connecting…'}
      </div>
    </div>
  );
};

type FilterRowProps = {
  label: string;
  count: number;
  active: boolean;
  onClick: () => void;
  icon?: LucideIcon;
  tone?: string;
  title?: string;
};

const FilterRow = ({ label, count, active, onClick, icon: Icon, tone, title }: FilterRowProps) => (
  <button
    type="button"
    onClick={onClick}
    title={title ?? label}
    className={`flex items-center gap-2 rounded-lg px-3 py-1.5 text-left text-xs transition-colors ${
      active ? 'bg-muted font-medium text-foreground' : 'text-muted-foreground hover:bg-muted'
    }`}
  >
    {Icon && <Icon className={`h-3.5 w-3.5 shrink-0 ${tone ?? ''}`} />}
    <span className={`min-w-0 flex-1 truncate ${tone ?? ''}`}>{label}</span>
    <span className="shrink-0 tabular-nums opacity-60">{count}</span>
  </button>
);

type FacetGroupProps = {
  title: string;
  icon: LucideIcon;
  entries: FacetEntry[];
  selected: string | null;
  onPick: (value: string) => void;
  renderLabel?: (value: string) => string;
};

/**
 * Collapsible because these lists are open-ended — one tracker per site, one label per whim. Collapsed by
 * default unless something in the group is selected, so arriving on a shared filtered URL shows you why.
 */
const FacetGroup = ({ title, icon: Icon, entries, selected, onPick, renderLabel }: FacetGroupProps) => {
  const [open, setOpen] = useState(false);
  const expanded = open || selected != null;

  if (!entries.length) return null;

  return (
    <div className="px-2 pb-2">
      <button
        type="button"
        onClick={() => setOpen((v) => !v)}
        className="flex w-full items-center gap-2 rounded-lg px-3 py-1.5 text-left text-[10px] font-semibold uppercase tracking-wide text-muted-foreground hover:bg-muted"
      >
        <ChevronRight className={`h-3 w-3 shrink-0 transition-transform ${expanded ? 'rotate-90' : ''}`} />
        <Icon className="h-3 w-3 shrink-0" />
        <span className="flex-1">{title}</span>
        <span className="tabular-nums opacity-60">{entries.length}</span>
      </button>
      {expanded && (
        <div className="mt-0.5 flex flex-col gap-0.5">
          {entries.map(({ value, count }) => (
            <FilterRow
              key={value}
              label={renderLabel ? renderLabel(value) : value}
              title={value}
              count={count}
              active={selected === value}
              onClick={() => onPick(value)}
            />
          ))}
        </div>
      )}
    </div>
  );
};
