import { useEffect, useRef, useState } from 'react';
import { RoomEvent, Track } from 'livekit-client';
import {
  ArrowLeftIcon,
  CheckIcon,
  CircleDotIcon,
  MonitorUpIcon,
  RadioTowerIcon,
  SparklesIcon,
  Volume2Icon,
  XIcon,
} from 'lucide-react';
import type { Room, RemoteTrack, RemoteTrackPublication, RemoteParticipant } from 'livekit-client';
import type { Pod } from '@podman/shared';
import { startBeat, type BeatHandle } from '../lib/beat.js';
import { useInterventions } from '../livekit/useInterventions.js';
import LiveWaveform from '@/components/ruixen/live-waveform';
import { Alert, AlertDescription, AlertTitle } from '@/components/ui/alert';
import { Avatar, AvatarBadge, AvatarFallback } from '@/components/ui/avatar';
import { Badge } from '@/components/ui/badge';
import { Button } from '@/components/ui/button';
import {
  Card,
  CardAction,
  CardContent,
  CardDescription,
  CardFooter,
  CardHeader,
  CardTitle,
} from '@/components/ui/card';
import {
  Empty,
  EmptyDescription,
  EmptyHeader,
  EmptyMedia,
  EmptyTitle,
} from '@/components/ui/empty';
import { Separator } from '@/components/ui/separator';
import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip';
import { cn } from '@/lib/utils';

interface PInfo {
  id: string;
  name: string;
  isLocal: boolean;
  speaking: boolean;
}

function snapshot(room: Room, fallbackName: string): PInfo[] {
  const lp = room.localParticipant;
  const local: PInfo = {
    id: lp.identity,
    name: lp.name || fallbackName,
    isLocal: true,
    speaking: lp.isSpeaking,
  };
  const remotes = Array.from(room.remoteParticipants.values()).map((p) => ({
    id: p.identity,
    name: p.name || p.identity,
    isLocal: false,
    speaking: p.isSpeaking,
  }));
  return [local, ...remotes];
}

export function PodView({
  team,
  me,
  room,
  devMode,
  onLeave,
}: {
  team: Pod;
  me: string;
  room: Room | null;
  devMode: boolean;
  onLeave: () => void;
}) {
  const [participants, setParticipants] = useState<PInfo[]>([]);
  const [sharing, setSharing] = useState(false);
  const [playingBeat, setPlayingBeat] = useState(false);
  const [note, setNote] = useState<string | null>(null);
  const { active, respond } = useInterventions(room);

  const audioRef = useRef<HTMLDivElement>(null);
  const beatRef = useRef<BeatHandle | null>(null);
  const screenTrackRef = useRef<MediaStreamTrack | null>(null);
  const onLeaveRef = useRef(onLeave);
  onLeaveRef.current = onLeave;

  useEffect(() => {
    if (!room) return;
    const refresh = () => setParticipants(snapshot(room, me));
    refresh();

    const onAudio = (track: RemoteTrack, _pub: RemoteTrackPublication, _p: RemoteParticipant) => {
      if (track.kind === Track.Kind.Audio && audioRef.current) {
        audioRef.current.appendChild(track.attach());
      }
    };
    const onAudioGone = (track: RemoteTrack) => track.detach().forEach((el) => el.remove());
    const onDisconnected = () => onLeaveRef.current();

    room
      .on(RoomEvent.ParticipantConnected, refresh)
      .on(RoomEvent.ParticipantDisconnected, refresh)
      .on(RoomEvent.ActiveSpeakersChanged, refresh)
      .on(RoomEvent.TrackSubscribed, onAudio)
      .on(RoomEvent.TrackUnsubscribed, onAudioGone)
      .on(RoomEvent.Disconnected, onDisconnected);

    return () => {
      room
        .off(RoomEvent.ParticipantConnected, refresh)
        .off(RoomEvent.ParticipantDisconnected, refresh)
        .off(RoomEvent.ActiveSpeakersChanged, refresh)
        .off(RoomEvent.TrackSubscribed, onAudio)
        .off(RoomEvent.TrackUnsubscribed, onAudioGone)
        .off(RoomEvent.Disconnected, onDisconnected);
    };
  }, [room, me]);

  useEffect(() => {
    return () => {
      beatRef.current?.stop();
      beatRef.current = null;
      screenTrackRef.current?.stop();
      screenTrackRef.current = null;
    };
  }, []);

  async function toggleBeat() {
    if (!room) return;
    setNote(null);
    try {
      if (playingBeat) {
        if (beatRef.current) await room.localParticipant.unpublishTrack(beatRef.current.track);
        beatRef.current?.stop();
        beatRef.current = null;
        setPlayingBeat(false);
      } else {
        await room.startAudio().catch(() => {});
        const handle = startBeat();
        beatRef.current = handle;
        await room.localParticipant.publishTrack(handle.track, { name: 'podman-beat' });
        setPlayingBeat(true);
      }
    } catch (e) {
      setNote(`Audio test failed: ${(e as Error).message}`);
    }
  }

  async function toggleScreen() {
    if (!room) return;
    setNote(null);
    try {
      if (sharing) {
        if (screenTrackRef.current)
          await room.localParticipant.unpublishTrack(screenTrackRef.current);
        screenTrackRef.current?.stop();
        screenTrackRef.current = null;
        setSharing(false);
        return;
      }
      if (!window.isSecureContext || !navigator.mediaDevices?.getDisplayMedia) {
        setNote('Screen capture needs HTTPS.');
        return;
      }
      const stream = await navigator.mediaDevices.getDisplayMedia({ video: true });
      const track = stream.getVideoTracks()[0];
      if (!track) return;
      track.onended = () => {
        screenTrackRef.current = null;
        setSharing(false);
      };
      await room.localParticipant.publishTrack(track, { source: Track.Source.ScreenShare });
      screenTrackRef.current = track;
      setSharing(true);
    } catch (e) {
      setNote(`Screen share stopped: ${(e as Error).message}`);
    }
  }

  const podmanPresent = participants.some((p) => p.name.toLowerCase() === 'podman');

  return (
    <div className="min-h-screen bg-background text-foreground">
      <div className="mx-auto flex min-h-screen w-full max-w-[1440px] flex-col gap-5 px-4 py-4 sm:px-6 lg:px-8">
        <header className="sticky top-0 z-10 -mx-4 flex flex-col gap-3 border-b bg-background/86 px-4 pb-4 pt-2 backdrop-blur-xl sm:-mx-6 sm:px-6 md:flex-row md:items-center md:justify-between lg:-mx-8 lg:px-8">
          <div className="flex min-w-0 items-center gap-3">
            <Tooltip>
              <TooltipTrigger asChild>
                <Button variant="ghost" size="icon" onClick={onLeave}>
                  <ArrowLeftIcon />
                  <span className="sr-only">Leave pod</span>
                </Button>
              </TooltipTrigger>
              <TooltipContent>Leave pod</TooltipContent>
            </Tooltip>
            <div className="min-w-0">
              <div className="flex items-center gap-2">
                <h1 className="truncate text-xl font-semibold tracking-tight">{team.name}</h1>
                <Badge variant={room ? 'default' : 'secondary'} className="rounded-md">
                  {room ? 'live' : 'local'}
                </Badge>
              </div>
              <p className="truncate font-mono text-xs text-muted-foreground">{team.repo}</p>
            </div>
          </div>

          <div className="grid grid-cols-2 gap-2 sm:flex sm:items-center">
            <Button variant="outline" onClick={toggleBeat} disabled={!room}>
              <Volume2Icon data-icon="inline-start" />
              {playingBeat ? 'Stop audio' : 'Test audio'}
            </Button>
            <Button onClick={toggleScreen} disabled={!room}>
              <MonitorUpIcon data-icon="inline-start" />
              {sharing ? 'Stop sharing' : 'Share screen'}
            </Button>
          </div>
        </header>

        {devMode && (
          <Alert>
            <RadioTowerIcon />
            <AlertTitle>Local mode</AlertTitle>
            <AlertDescription>LiveKit is not configured for this session.</AlertDescription>
          </Alert>
        )}

        {note && (
          <Alert>
            <CircleDotIcon />
            <AlertTitle>Room notice</AlertTitle>
            <AlertDescription>{note}</AlertDescription>
          </Alert>
        )}

        <main className="grid flex-1 gap-5 lg:grid-cols-[minmax(0,1fr)_360px]">
          <section className="flex min-w-0 flex-col gap-5">
            <div className="grid gap-3 sm:grid-cols-3">
              <Metric label="Participants" value={participants.length || 1} />
              <Metric label="Screen" value={sharing ? 'sharing' : 'idle'} />
              <Metric label="PodMan" value={podmanPresent ? 'online' : 'waiting'} />
            </div>

            <Card className="flex-1">
              <CardHeader>
                <CardTitle>Room state</CardTitle>
                <CardDescription>People and media currently visible to PodMan.</CardDescription>
              </CardHeader>
              <CardContent>
                {participants.length === 0 ? (
                  <Empty className="min-h-80">
                    <EmptyHeader>
                      <EmptyMedia variant="icon">
                        <RadioTowerIcon />
                      </EmptyMedia>
                      <EmptyTitle>Connecting</EmptyTitle>
                      <EmptyDescription>Waiting for LiveKit room state.</EmptyDescription>
                    </EmptyHeader>
                  </Empty>
                ) : (
                  <div className="grid gap-2 md:grid-cols-2">
                    {participants.map((p) => (
                      <Participant key={p.id} participant={p} />
                    ))}
                  </div>
                )}
              </CardContent>
              <CardFooter>
                <p className="truncate text-sm text-muted-foreground">
                  Roster: {team.members.join(', ') || 'No saved members'}
                </p>
              </CardFooter>
            </Card>
          </section>

          <aside className="flex flex-col gap-5">
            <Card>
              <CardHeader>
                <CardTitle>Intervention</CardTitle>
                <CardDescription>Card first, voice only for urgent escalation.</CardDescription>
                <CardAction>
                  <Badge variant={active ? 'default' : 'secondary'} className="rounded-md">
                    {active ? 'active' : 'clear'}
                  </Badge>
                </CardAction>
              </CardHeader>
              <CardContent>
                {active ? (
                  <div className="flex flex-col gap-4">
                    <div className="rounded-lg border bg-muted/35 p-3">
                      <p className="text-sm leading-6">{active.message}</p>
                    </div>
                    <div className="flex items-center justify-between gap-3 text-sm">
                      <span className="text-muted-foreground">Suggested action</span>
                      <Badge variant="outline">
                        {active.suggestedAction.kind.replaceAll('_', ' ')}
                      </Badge>
                    </div>
                  </div>
                ) : (
                  <Empty className="min-h-72 border-0 p-0">
                    <EmptyHeader>
                      <EmptyMedia variant="icon">
                        <SparklesIcon />
                      </EmptyMedia>
                      <EmptyTitle>No collision detected</EmptyTitle>
                      <EmptyDescription>
                        Share your screen when ready. PodMan will stay quiet until there is a useful
                        signal.
                      </EmptyDescription>
                    </EmptyHeader>
                  </Empty>
                )}
              </CardContent>
              {active && (
                <CardFooter className="justify-end gap-2">
                  <Button variant="outline" onClick={() => void respond('dismissed', false)}>
                    <XIcon data-icon="inline-start" />
                    Dismiss
                  </Button>
                  <Button onClick={() => void respond('accepted', true)}>
                    <CheckIcon data-icon="inline-start" />
                    Accept
                  </Button>
                </CardFooter>
              )}
            </Card>

            <Card>
              <CardHeader>
                <CardTitle>Status</CardTitle>
                <CardDescription>Connection, media, and agent presence.</CardDescription>
              </CardHeader>
              <CardContent>
                <LiveWaveform
                  processing={!!room}
                  active={false}
                  height={32}
                  barWidth={2}
                  barGap={3}
                  className="mb-4 px-3 py-2 text-muted-foreground"
                />
                <div className="flex flex-col gap-3">
                  <StatusLine label="LiveKit" value={room ? 'connected' : 'offline'} />
                  <StatusLine label="Screen" value={sharing ? 'published' : 'not shared'} />
                  <StatusLine label="Audio" value={playingBeat ? 'publishing' : 'ready'} />
                  <StatusLine label="Agent" value={podmanPresent ? 'watching' : 'waiting'} />
                </div>
              </CardContent>
            </Card>
          </aside>
        </main>
        <div ref={audioRef} className="hidden" />
      </div>
    </div>
  );
}

function Metric({ label, value }: { label: string; value: number | string }) {
  return (
    <Card size="sm">
      <CardContent>
        <p className="text-xs text-muted-foreground">{label}</p>
        <p className="mt-1 text-lg font-medium">{value}</p>
      </CardContent>
    </Card>
  );
}

function Participant({ participant }: { participant: PInfo }) {
  return (
    <div
      className={cn(
        'flex min-h-16 items-center justify-between gap-3 rounded-lg border bg-muted/20 px-3 transition',
        participant.speaking && 'bg-muted',
      )}
    >
      <div className="flex min-w-0 items-center gap-3">
        <Avatar>
          <AvatarFallback>{initials(participant.name)}</AvatarFallback>
          {participant.speaking && <AvatarBadge />}
        </Avatar>
        <div className="min-w-0">
          <p className="truncate text-sm font-medium">{participant.name}</p>
          <p className="text-xs text-muted-foreground">{participant.isLocal ? 'you' : 'remote'}</p>
        </div>
      </div>
      <Badge variant={participant.speaking ? 'default' : 'secondary'} className="rounded-md">
        {participant.speaking ? 'speaking' : 'connected'}
      </Badge>
    </div>
  );
}

function StatusLine({ label, value }: { label: string; value: string }) {
  return (
    <>
      <div className="flex items-center justify-between gap-3">
        <span className="text-sm text-muted-foreground">{label}</span>
        <span className="text-sm font-medium">{value}</span>
      </div>
      <Separator />
    </>
  );
}

function initials(name: string): string {
  return name
    .split(/\s+/)
    .map((w) => w[0] ?? '')
    .join('')
    .slice(0, 2)
    .toUpperCase();
}
