/**
 * List view for /v1/tenants/{id}/sources.
 *
 * Layout:
 *   - For super_admin: a tenant picker (dropdown) at the top so
 *     they can switch between companies.
 *   - For tenant_admin: pinned to their own tenant (picker hidden).
 *   - Below: search + type filter + status filter + the table.
 *
 * tenant_admin scope is enforced server-side; the URL path
 * carries the tenant id and the server returns only that
 * tenant's sources.
 */

import { useEffect, useMemo, useState } from 'react';
import { Link, useNavigate, useParams, useSearchParams } from 'react-router-dom';
import { Radio, Search } from 'lucide-react';

import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import { EmptyState } from '@/components/ui/empty-state';
import {
  Table,
  TableBody,
  TableCell,
  TableHead,
  TableHeader,
  TableRow,
} from '@/components/ui/table';

import { useAuth } from '@/lib/auth-context';
import { canManageSources, isSuperAdmin } from '@/lib/scope';
import { useTenantsList } from '@/features/companies/api';
import { useSourcesList } from './api';
import { CreateSourceDialog } from './create-dialog';
import { StatusBadge, TypeBadge, formatDate, formatRateLimit } from './format';
import type { SourceStatus, SourceType } from './types';

const TYPE_OPTIONS = [
  { value: '', label: 'All types' },
  { value: 'http', label: 'HTTP' },
  { value: 'mqtt', label: 'MQTT' },
  { value: 'ws', label: 'WebSocket' },
  { value: 'grpc', label: 'gRPC' },
];

const STATUS_OPTIONS = [
  { value: '', label: 'All' },
  { value: 'active', label: 'Active' },
  { value: 'suspended', label: 'Suspended' },
];

export function SourcesList() {
  const navigate = useNavigate();
  const params = useParams();
  const { user } = useAuth();
  const canCreate = canManageSources(user?.role);
  const isAdmin = isSuperAdmin(user?.role);

  const tenantId = params.id;

  const [searchParams, setSearchParams] = useSearchParams();
  const [q, setQ] = useState(searchParams.get('q') ?? '');
  const type = searchParams.get('type') ?? '';
  const status = searchParams.get('status') ?? '';

  // For super_admin without a tenant in the URL, list tenants to
  // populate the picker. We also auto-pick the first one so the
  // rest of the page can render immediately.
  const tenantsQ = useTenantsList({ limit: 200 });
  useEffect(() => {
    if (tenantId || !isAdmin) return;
    const first = tenantsQ.data && tenantsQ.data.items[0];
    if (first) navigate(`/sources/${first.id}`, { replace: true });
  }, [tenantId, isAdmin, tenantsQ.data, navigate]);

  // Debounce q -> URL (300ms).
  useEffect(() => {
    const handle = setTimeout(() => {
      const next = new URLSearchParams(searchParams);
      if (q.trim()) next.set('q', q.trim());
      else next.delete('q');
      setSearchParams(next, { replace: true });
    }, 300);
    return () => clearTimeout(handle);
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [q]);

  const queryParams = useMemo(
    () => ({
      q: searchParams.get('q') ?? undefined,
      type: type || undefined,
      status: status || undefined,
      limit: 100,
    }),
    // eslint-disable-next-line react-hooks/exhaustive-deps
    [searchParams, type, status],
  );
  const { data, isPending, isError, error, refetch } = useSourcesList(tenantId, queryParams);

  const onTenantChange = (next: string) => {
    if (next) navigate(`/sources/${next}`);
    else navigate('/sources');
  };

  return (
    <div className="flex flex-col gap-4">
      <div className="flex flex-col gap-2 sm:flex-row sm:items-center sm:justify-between">
        <div>
          <h1 className="text-2xl font-semibold tracking-tight">Sources</h1>
          <p className="text-sm text-muted-foreground">
            Manage the ingest endpoints per company. Each source has its own
            credentials, rate limit, and routing rules.
          </p>
        </div>
        <div className="flex items-center gap-2">
          {isAdmin && tenantsQ.data ? (
            <select
              className="h-9 rounded-md border border-input bg-background px-3 text-sm"
              value={tenantId ?? ''}
              onChange={(e) => onTenantChange(e.target.value)}
              aria-label="Company"
            >
              <option value="">Select a company</option>
              {tenantsQ.data.items.map((t) => (
                <option key={t.id} value={t.id}>
                  {t.display_name}
                </option>
              ))}
            </select>
          ) : null}
          {canCreate && tenantId ? <CreateSourceDialog tenantId={tenantId} /> : null}
        </div>
      </div>

      {tenantId ? (
        <div className="flex flex-col gap-2 sm:flex-row sm:items-center">
          <div className="relative flex-1 sm:max-w-sm">
            <Search className="pointer-events-none absolute left-2.5 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground" />
            <Input
              placeholder="Search by id or name"
              className="pl-8"
              value={q}
              onChange={(e) => setQ(e.target.value)}
              aria-label="Search sources"
            />
          </div>
          <div className="flex flex-wrap gap-1">
            {TYPE_OPTIONS.map((opt) => {
              const active = type === opt.value;
              return (
                <Button
                  key={opt.value}
                  variant={active ? 'secondary' : 'ghost'}
                  size="sm"
                  onClick={() => {
                    const next = new URLSearchParams(searchParams);
                    if (opt.value) next.set('type', opt.value);
                    else next.delete('type');
                    setSearchParams(next, { replace: true });
                  }}
                >
                  {opt.label}
                </Button>
              );
            })}
          </div>
          <div className="flex gap-1">
            {STATUS_OPTIONS.map((opt) => {
              const active = status === opt.value;
              return (
                <Button
                  key={opt.value}
                  variant={active ? 'secondary' : 'ghost'}
                  size="sm"
                  onClick={() => {
                    const next = new URLSearchParams(searchParams);
                    if (opt.value) next.set('status', opt.value);
                    else next.delete('status');
                    setSearchParams(next, { replace: true });
                  }}
                >
                  {opt.label}
                </Button>
              );
            })}
          </div>
        </div>
      ) : null}

      {!tenantId ? (
        <div className="rounded-md border bg-card p-8 text-center text-sm text-muted-foreground">
          {isAdmin ? 'Select a company above to see its sources.' : 'You will see sources here once your company is set up.'}
        </div>
      ) : isError ? (
        <div className="rounded-md border border-destructive/40 bg-destructive/5 p-4 text-sm text-destructive">
          <p className="font-medium">Failed to load sources.</p>
          <p className="mt-1 text-xs opacity-80">
            {error instanceof Error ? error.message : 'Unknown error'}
          </p>
          <Button variant="outline" size="sm" className="mt-2" onClick={() => refetch()}>
            Retry
          </Button>
        </div>
      ) : isPending ? (
        <div className="rounded-md border bg-card p-8 text-center text-sm text-muted-foreground">
          Loading…
        </div>
      ) : data && data.items.length === 0 ? (
        <EmptyState
          icon={<Radio className="h-8 w-8" />}
          title="No sources yet"
          description={
            canCreate
              ? 'Create the first source for this company.'
              : 'Your operator has not set up any sources for this company yet.'
          }
          action={canCreate ? <CreateSourceDialog tenantId={tenantId} /> : null}
        />
      ) : data ? (
        <>
          <div className="rounded-md border bg-card">
            <Table>
              <TableHeader>
                <TableRow>
                  <TableHead>Name</TableHead>
                  <TableHead>ID</TableHead>
                  <TableHead>Type</TableHead>
                  <TableHead>Status</TableHead>
                  <TableHead className="text-right">Rate limit</TableHead>
                  <TableHead>Secrets</TableHead>
                  <TableHead>Created</TableHead>
                </TableRow>
              </TableHeader>
              <TableBody>
                {data.items.map((s) => (
                  <TableRow key={`${s.company_id}:${s.id}`}>
                    <TableCell>
                      <Link
                        to={`/sources/${tenantId}/${s.id}`}
                        className="font-medium text-foreground hover:underline"
                      >
                        {s.name}
                      </Link>
                    </TableCell>
                    <TableCell>
                      <code className="rounded bg-muted px-1.5 py-0.5 text-xs">
                        {s.id}
                      </code>
                    </TableCell>
                    <TableCell>
                      <TypeBadge type={s.type} />
                    </TableCell>
                    <TableCell>
                      <StatusBadge status={s.status} />
                    </TableCell>
                    <TableCell className="text-right tabular-nums">
                      {formatRateLimit(s.rate_limit_per_sec)}
                    </TableCell>
                    <TableCell className="text-xs text-muted-foreground">
                      {secretsLabel(s.hmac_set, s.api_key_set)}
                    </TableCell>
                    <TableCell className="text-xs text-muted-foreground">
                      {formatDate(s.created_at)}
                    </TableCell>
                  </TableRow>
                ))}
              </TableBody>
            </Table>
          </div>
          <p className="text-xs text-muted-foreground">
            Showing {data.items.length} of {data.total}
          </p>
        </>
      ) : null}
    </div>
  );
}

function secretsLabel(hmacSet: boolean, apiKeySet: boolean): string {
  if (hmacSet && apiKeySet) return 'HMAC + API';
  if (hmacSet) return 'HMAC only';
  if (apiKeySet) return 'API only';
  return 'none';
}
