import { useState } from 'react';
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
import {
  Bot,
  Check,
  Copy,
  KeyRound,
  RefreshCw,
  ShieldCheck,
  UserPlus,
  Users,
} from 'lucide-react';
import { TEAM_LABELS, TEAM_ROLES, TEAMS, type Team, type TeamRole } from '@pig/core';
import { api, get, patch, post, relativeTime } from '@/lib/api';
import { Badge, Button, Card, CardContent, CardHeader, CardTitle, Input } from '@/components/ui';
import { Label } from '@/components/ui/label';
import { Select, SelectContent, SelectGroup, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select';
import { Switch } from '@/components/ui/switch';
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs';
import { IntegrationSettings } from './IntegrationSettings';

interface AdminRuntimeSettings {
  piggyModel: string;
  piggyInferenceBase: string;
  piggyEnabled: boolean;
  primeComputeBase: string;
  primeApiKey: {
    configured: boolean;
    source: 'database' | 'environment' | null;
    updatedAt: string | null;
    encryptionReady: boolean;
  };
  primeSyncEnabled: boolean;
  primeSyncIntervalMinutes: number;
  updatedAt: string;
}

interface Invite {
  id: string;
  email: string | null;
  team: Team | null;
  role: TeamRole;
  usesRemaining: number;
  expiresAt: string | null;
  createdAt: string;
  status: 'active' | 'used' | 'expired' | 'revoked';
}

interface Member {
  id: string;
  name: string;
  email: string;
  title: string | null;
  isPlatformAdmin: boolean;
  adminSource: 'environment' | 'database' | null;
  memberships: { team: Team; role: TeamRole }[];
}

export function AdminSettings() {
  const { data, isLoading } = useQuery({
    queryKey: ['admin-settings'],
    queryFn: () => get<AdminRuntimeSettings>('/api/admin/settings'),
  });

  return (
    <section className="overflow-hidden rounded-2xl border border-border bg-surface">
      <div className="relative overflow-hidden border-b border-border bg-surface-2 px-4 py-5 sm:px-6">
        <div className="absolute -right-12 -top-20 size-48 rounded-full bg-accent-subtle blur-3xl" aria-hidden />
        <div className="relative flex items-start gap-3">
          <div className="flex size-10 shrink-0 items-center justify-center rounded-xl bg-accent text-accent-on">
            <ShieldCheck aria-hidden />
          </div>
          <div className="min-w-0">
            <div className="flex flex-wrap items-center gap-2">
              <h2 className="text-lg font-semibold tracking-tight">Platform control plane</h2>
              <Badge tone="warning">Admin only</Badge>
            </div>
            <p className="mt-1 max-w-2xl text-sm text-muted">
              Configure intelligence, inventory sync, workspace entry, and team authority.
            </p>
          </div>
        </div>
      </div>

      <Tabs defaultValue="runtime" className="p-4 sm:p-6">
        <TabsList className="scroll-x flex h-auto w-full justify-start bg-surface-2 p-1 sm:w-auto sm:inline-flex">
          <TabsTrigger value="runtime" className="tap flex-1 sm:flex-none">Runtime</TabsTrigger>
          <TabsTrigger value="invites" className="tap flex-1 sm:flex-none">Invites</TabsTrigger>
          <TabsTrigger value="access" className="tap flex-1 sm:flex-none">Access</TabsTrigger>
          <TabsTrigger value="integrations" className="tap flex-1 sm:flex-none">Integrations</TabsTrigger>
        </TabsList>
        <TabsContent value="runtime" className="mt-5">
          {isLoading || !data ? <p className="text-sm text-muted">Loading runtime settings…</p> : <RuntimeForm key={data.updatedAt} settings={data} />}
        </TabsContent>
        <TabsContent value="invites" className="mt-5"><InviteManager /></TabsContent>
        <TabsContent value="access" className="mt-5"><MemberManager /></TabsContent>
        <TabsContent value="integrations" className="mt-5"><IntegrationSettings /></TabsContent>
      </Tabs>
    </section>
  );
}

function RuntimeForm({ settings }: { settings: AdminRuntimeSettings }) {
  const queryClient = useQueryClient();
  const [model, setModel] = useState(settings.piggyModel);
  const [inferenceBase, setInferenceBase] = useState(settings.piggyInferenceBase);
  const [piggyEnabled, setPiggyEnabled] = useState(settings.piggyEnabled);
  const [syncEnabled, setSyncEnabled] = useState(settings.primeSyncEnabled);
  const [interval, setIntervalValue] = useState(String(settings.primeSyncIntervalMinutes));
  const [primeApiKey, setPrimeApiKey] = useState('');
  const [clearKey, setClearKey] = useState(false);
  const [message, setMessage] = useState<string | null>(null);

  const save = useMutation({
    mutationFn: () =>
      patch<AdminRuntimeSettings>('/api/admin/settings', {
        piggyModel: model,
        piggyInferenceBase: inferenceBase,
        piggyEnabled,
        primeSyncEnabled: syncEnabled,
        primeSyncIntervalMinutes: Number(interval),
        ...(primeApiKey ? { primeApiKey } : {}),
        ...(clearKey ? { clearPrimeApiKey: true } : {}),
      }),
    onSuccess: () => {
      setPrimeApiKey('');
      setClearKey(false);
      setMessage('Runtime settings saved. Prime sync is reloading in the background.');
      void queryClient.invalidateQueries({ queryKey: ['admin-settings'] });
    },
  });

  return (
    <form className="flex flex-col gap-5" onSubmit={(event) => { event.preventDefault(); setMessage(null); save.mutate(); }}>
      <div className="grid gap-4 xl:grid-cols-2">
        <Card>
          <CardHeader>
            <div className="flex items-center gap-2"><Bot className="text-accent-fg" aria-hidden /><CardTitle className="text-base">Piggy intelligence</CardTitle></div>
            <p className="text-sm text-muted">Inference is deliberately isolated from the compute API.</p>
          </CardHeader>
          <CardContent className="flex flex-col gap-4">
            <label className="flex flex-col gap-1.5" htmlFor="piggy-model">
              <span className="text-sm font-medium">Model</span>
              <Input id="piggy-model" value={model} onChange={(event) => setModel(event.target.value)} />
              <span className="text-xs text-muted">Nemotron runs tool calls with reasoning disabled to prevent think-aloud truncation.</span>
            </label>
            <label className="flex flex-col gap-1.5" htmlFor="inference-base">
              <span className="text-sm font-medium">Inference endpoint</span>
              <Input id="inference-base" type="url" value={inferenceBase} onChange={(event) => setInferenceBase(event.target.value)} />
            </label>
            <ToggleRow id="piggy-enabled" label="Piggy worker" description="Allow the configured worker to process queued tasks." checked={piggyEnabled} onCheckedChange={setPiggyEnabled} />
          </CardContent>
        </Card>

        <Card>
          <CardHeader>
            <div className="flex items-center gap-2"><RefreshCw className="text-accent-fg" aria-hidden /><CardTitle className="text-base">Prime inventory</CardTitle></div>
            <p className="break-all text-xs text-muted">Compute endpoint: {settings.primeComputeBase}</p>
          </CardHeader>
          <CardContent className="flex flex-col gap-4">
            <div className="flex flex-wrap items-center gap-2">
              <Badge tone={settings.primeApiKey.configured ? 'positive' : 'warning'}>{settings.primeApiKey.configured ? 'Credential configured' : 'Credential missing'}</Badge>
              {settings.primeApiKey.source ? <Badge>{settings.primeApiKey.source} source</Badge> : null}
              {settings.primeApiKey.updatedAt ? <span className="text-xs text-muted">updated {relativeTime(settings.primeApiKey.updatedAt)}</span> : null}
            </div>
            <label className="flex flex-col gap-1.5" htmlFor="prime-api-key">
              <span className="text-sm font-medium">Replace Prime API key</span>
              <Input id="prime-api-key" type="password" autoComplete="new-password" value={primeApiKey} onChange={(event) => { setPrimeApiKey(event.target.value); setClearKey(false); }} placeholder="Enter a new key; existing material is never shown" disabled={!settings.primeApiKey.encryptionReady} />
              <span className="text-xs text-muted">{settings.primeApiKey.encryptionReady ? 'Encrypted with AES-256-GCM before it reaches the database.' : 'Set PIG_SETTINGS_ENCRYPTION_KEY on the server to enable credential writes.'}</span>
            </label>
            {settings.primeApiKey.source === 'database' ? <Button type="button" variant={clearKey ? 'danger' : 'outline'} size="sm" onClick={() => { setClearKey((value) => !value); setPrimeApiKey(''); }}>{clearKey ? 'Credential will be cleared' : 'Clear stored credential'}</Button> : null}
            <div className="grid gap-3 sm:grid-cols-[1fr_9rem] sm:items-end">
              <ToggleRow id="prime-sync" label="Inventory sync" description="Continuously refresh Prime availability and pricing." checked={syncEnabled} onCheckedChange={setSyncEnabled} />
              <label className="flex flex-col gap-1.5" htmlFor="sync-interval"><span className="text-sm font-medium">Every (minutes)</span><Input id="sync-interval" type="number" min="1" max="1440" value={interval} onChange={(event) => setIntervalValue(event.target.value)} /></label>
            </div>
          </CardContent>
        </Card>
      </div>
      {save.error ? <p role="alert" className="text-sm text-danger">{save.error.message}</p> : null}
      {message ? <p className="flex items-center gap-2 text-sm text-positive"><Check aria-hidden />{message}</p> : null}
      <div><Button type="submit" variant="primary" disabled={save.isPending}>{save.isPending ? 'Saving…' : 'Save runtime settings'}</Button></div>
    </form>
  );
}

function ToggleRow({ id, label, description, checked, onCheckedChange }: { id: string; label: string; description: string; checked: boolean; onCheckedChange(value: boolean): void }) {
  return <div className="flex min-w-0 items-center justify-between gap-4 rounded-xl border border-border p-3"><div className="min-w-0"><Label htmlFor={id}>{label}</Label><p className="mt-1 text-xs text-muted">{description}</p></div><Switch id={id} checked={checked} onCheckedChange={onCheckedChange} /></div>;
}

function InviteManager() {
  const queryClient = useQueryClient();
  const { data = [] } = useQuery({ queryKey: ['admin-invites'], queryFn: () => get<Invite[]>('/api/admin/invites') });
  const [email, setEmail] = useState('');
  const [team, setTeam] = useState<Team | 'any'>('any');
  const [role, setRole] = useState<TeamRole>('member');
  const [uses, setUses] = useState('1');
  const [expiresAt, setExpiresAt] = useState('');
  const [issuedCode, setIssuedCode] = useState<string | null>(null);
  const create = useMutation({
    mutationFn: () => post<Invite & { code: string }>('/api/admin/invites', { ...(email ? { email } : {}), ...(team !== 'any' ? { team } : {}), role, usesRemaining: Number(uses), ...(expiresAt ? { expiresAt: new Date(expiresAt).toISOString() } : {}) }),
    onSuccess: (invite) => { setIssuedCode(invite.code); setEmail(''); void queryClient.invalidateQueries({ queryKey: ['admin-invites'] }); },
  });
  const revoke = useMutation({ mutationFn: (id: string) => api(`/api/admin/invites/${id}`, { method: 'DELETE' }), onSuccess: () => void queryClient.invalidateQueries({ queryKey: ['admin-invites'] }) });

  return <div className="grid gap-5 xl:grid-cols-[minmax(18rem,0.8fr)_minmax(0,1.2fr)]">
    <Card><CardHeader><div className="flex items-center gap-2"><UserPlus className="text-accent-fg" aria-hidden /><CardTitle className="text-base">Issue an invite</CardTitle></div><p className="text-sm text-muted">Codes gate PIG registration. They never open registration on the shared identity provider.</p></CardHeader><CardContent><form className="flex flex-col gap-4" onSubmit={(event) => { event.preventDefault(); setIssuedCode(null); create.mutate(); }}>
      <label className="flex flex-col gap-1.5"><span className="text-sm font-medium">Email, optional</span><Input type="email" value={email} onChange={(event) => setEmail(event.target.value)} placeholder="Pin to a known address" /></label>
      <div className="grid grid-cols-2 gap-3"><label className="flex flex-col gap-1.5"><span className="text-sm font-medium">Team</span><Select value={team} onValueChange={(value) => setTeam(value as Team | 'any')}><SelectTrigger><SelectValue /></SelectTrigger><SelectContent><SelectGroup><SelectItem value="any">Choose at signup</SelectItem>{TEAMS.map((value) => <SelectItem key={value} value={value}>{TEAM_LABELS[value]}</SelectItem>)}</SelectGroup></SelectContent></Select></label><label className="flex flex-col gap-1.5"><span className="text-sm font-medium">Role</span><Select value={role} onValueChange={(value) => setRole(value as TeamRole)}><SelectTrigger><SelectValue /></SelectTrigger><SelectContent><SelectGroup>{TEAM_ROLES.map((value) => <SelectItem key={value} value={value}>{value}</SelectItem>)}</SelectGroup></SelectContent></Select></label></div>
      <div className="grid grid-cols-2 gap-3"><label className="flex flex-col gap-1.5"><span className="text-sm font-medium">Uses</span><Input type="number" min="1" max="100" value={uses} onChange={(event) => setUses(event.target.value)} /></label><label className="flex flex-col gap-1.5"><span className="text-sm font-medium">Expires, optional</span><Input type="datetime-local" value={expiresAt} onChange={(event) => setExpiresAt(event.target.value)} /></label></div>
      {create.error ? <p role="alert" className="text-sm text-danger">{create.error.message}</p> : null}<Button type="submit" variant="primary" disabled={create.isPending}>{create.isPending ? 'Issuing…' : 'Issue invite'}</Button>
      {issuedCode ? <div className="rounded-xl border border-warning bg-warning/10 p-3"><p className="text-xs font-medium text-warning">Shown once. Send it through a secure channel.</p><div className="mt-2 flex min-w-0 items-center gap-2"><code className="min-w-0 flex-1 break-all text-xs">{issuedCode}</code><Button type="button" size="icon" variant="ghost" aria-label="Copy invite code" onClick={() => void navigator.clipboard.writeText(issuedCode)}><Copy aria-hidden /></Button></div></div> : null}
    </form></CardContent></Card>
    <Card><CardHeader><CardTitle className="text-base">Invite ledger</CardTitle><p className="text-sm text-muted">Only metadata remains visible after issuance.</p></CardHeader><CardContent className="flex flex-col gap-2">{data.length === 0 ? <p className="py-8 text-center text-sm text-muted">No invites issued yet.</p> : data.map((invite) => <div key={invite.id} className="flex min-w-0 flex-col gap-3 rounded-xl border border-border p-3 sm:flex-row sm:items-center"><div className="min-w-0 flex-1"><div className="flex flex-wrap items-center gap-2"><p className="truncate text-sm font-medium">{invite.email ?? 'Workspace invite'}</p><Badge tone={invite.status === 'active' ? 'positive' : invite.status === 'expired' ? 'warning' : 'neutral'}>{invite.status}</Badge></div><p className="mt-1 text-xs text-muted">{invite.team ? TEAM_LABELS[invite.team] : 'Team chosen at signup'} · {invite.role} · {invite.usesRemaining} use{invite.usesRemaining === 1 ? '' : 's'} left</p></div>{invite.status === 'active' ? <Button type="button" size="sm" variant="outline" disabled={revoke.isPending} onClick={() => revoke.mutate(invite.id)}>Revoke</Button> : null}</div>)}</CardContent></Card>
  </div>;
}

function MemberManager() {
  const { data = [] } = useQuery({ queryKey: ['admin-members'], queryFn: () => get<Member[]>('/api/admin/members') });
  return <div className="flex flex-col gap-3"><div className="flex items-center gap-2"><Users className="text-accent-fg" aria-hidden /><div><h3 className="font-semibold">Team and role administration</h3><p className="text-sm text-muted">Roles are team-scoped. Platform administration is a separate grant.</p></div></div>{data.map((member) => <MemberAccess key={`${member.id}:${JSON.stringify(member.memberships)}:${member.isPlatformAdmin}`} member={member} />)}</div>;
}

function MemberAccess({ member }: { member: Member }) {
  const queryClient = useQueryClient();
  const [isPlatformAdmin, setIsPlatformAdmin] = useState(member.isPlatformAdmin);
  const [roles, setRoles] = useState<Partial<Record<Team, TeamRole>>>(() => Object.fromEntries(member.memberships.map(({ team, role }) => [team, role])));
  const save = useMutation({ mutationFn: () => patch(`/api/admin/members/${member.id}/access`, { isPlatformAdmin, memberships: TEAMS.flatMap((team) => roles[team] ? [{ team, role: roles[team] }] : []) }), onSuccess: () => void queryClient.invalidateQueries({ queryKey: ['admin-members'] }) });
  return <Card><CardContent className="p-4 sm:p-5"><div className="flex flex-col gap-4 xl:flex-row xl:items-center"><div className="min-w-0 xl:w-64"><div className="flex flex-wrap items-center gap-2"><p className="truncate font-medium">{member.name}</p>{member.isPlatformAdmin ? <Badge tone="warning"><KeyRound aria-hidden />Platform admin</Badge> : null}</div><p className="truncate text-sm text-muted">{member.email}</p></div><div className="grid min-w-0 flex-1 gap-2 sm:grid-cols-3">{TEAMS.map((team) => <label key={team} className="flex flex-col gap-1"><span className="text-xs font-medium text-muted">{TEAM_LABELS[team]}</span><Select value={roles[team] ?? 'none'} onValueChange={(value) => setRoles((current) => ({ ...current, [team]: value === 'none' ? undefined : value as TeamRole }))}><SelectTrigger><SelectValue /></SelectTrigger><SelectContent><SelectGroup><SelectItem value="none">No access</SelectItem>{TEAM_ROLES.map((role) => <SelectItem key={role} value={role}>{role}</SelectItem>)}</SelectGroup></SelectContent></Select></label>)}</div><div className="flex items-center justify-between gap-3 xl:w-52"><div><Label htmlFor={`admin-${member.id}`}>Platform admin</Label>{member.adminSource === 'environment' ? <p className="text-xs text-muted">Pinned by environment</p> : null}</div><Switch id={`admin-${member.id}`} checked={isPlatformAdmin} disabled={member.adminSource === 'environment'} onCheckedChange={setIsPlatformAdmin} /></div><Button type="button" size="sm" variant="primary" disabled={save.isPending} onClick={() => save.mutate()}>{save.isPending ? 'Saving…' : 'Save access'}</Button></div>{save.error ? <p role="alert" className="mt-3 text-sm text-danger">{save.error.message}</p> : null}</CardContent></Card>;
}
