import { useEffect, useMemo, useRef, useState } from "react";
import { useNavigate } from "react-router-dom";
import { ArrowLeft, VideoOff } from "lucide-react";
import { WindowControls } from "@/components/window-controls";
import { Button } from "@/components/ui/button";
import { ScrollArea } from "@/components/ui/scroll-area";
import { Muted } from "@/components/ui/typography";
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from "@/components/ui/select";
import { AudioLevelBars } from "@/components/audio/audio-level-bars";
import { useAudioSource } from "@/components/audio/use-audio-source";
import { useMediaDevices } from "@/hooks/use-media-devices";
import {
  resolveEffectiveDeviceId,
  isSavedDeviceAvailable,
} from "@/hooks/use-effective-device-id";
import {
  useMediaDevicesStore,
  type SavedDevice,
} from "@/stores/media-devices-store";

const SYSTEM_DEFAULT = "__system_default__";

function usePreviewStream(
  enabled: boolean,
  micId: string | undefined,
  cameraId: string | undefined,
  cameraAvailable: boolean,
): { stream: MediaStream | null; error: string | null } {
  const [stream, setStream] = useState<MediaStream | null>(null);
  const [error, setError] = useState<string | null>(null);

  useEffect(() => {
    if (!enabled) {
      setStream(null);
      return;
    }

    let cancelled = false;
    let active: MediaStream | null = null;

    const audio: MediaTrackConstraints | boolean = micId
      ? { deviceId: { exact: micId } }
      : true;
    const video: MediaTrackConstraints | false = cameraAvailable
      ? cameraId
        ? { deviceId: { exact: cameraId }, aspectRatio: { ideal: 16 / 9 } }
        : { aspectRatio: { ideal: 16 / 9 } }
      : false;

    navigator.mediaDevices
      .getUserMedia({ audio, video })
      .then((s) => {
        if (cancelled) {
          s.getTracks().forEach((t) => t.stop());
          return;
        }
        active = s;
        setStream(s);
        setError(null);
      })
      .catch((err: unknown) => {
        if (cancelled) return;
        setStream(null);
        setError(err instanceof Error ? err.message : "Unable to access devices");
      });

    return () => {
      cancelled = true;
      active?.getTracks().forEach((t) => t.stop());
    };
  }, [enabled, micId, cameraId, cameraAvailable]);

  return { stream, error };
}

function deviceLabel(d: MediaDeviceInfo, index: number): string {
  if (d.label) return d.label;
  const kind = d.kind === "audioinput" ? "Microphone" : "Camera";
  return `${kind} ${index + 1}`;
}

function FieldLabel({ children }: { children: React.ReactNode }) {
  return (
    <label className="text-muted-foreground text-[11px] font-medium uppercase tracking-wider">
      {children}
    </label>
  );
}

function InlineLevelMeter({ stream }: { stream: MediaStream | null }) {
  const audioSource = useAudioSource(stream);
  if (!audioSource) {
    return (
      <div className="flex h-3 items-end gap-1">
        {[0, 1, 2].map((i) => (
          <div key={i} className="bg-muted h-1 w-1 rounded-full" />
        ))}
      </div>
    );
  }
  return (
    <div className="flex h-3 items-end">
      <div className="scale-[0.55] origin-right">
        <AudioLevelBars sourceNode={audioSource.sourceNode} />
      </div>
    </div>
  );
}

function CameraPreview({ stream }: { stream: MediaStream | null }) {
  const videoRef = useRef<HTMLVideoElement>(null);
  const hasVideoTrack = (stream?.getVideoTracks().length ?? 0) > 0;

  useEffect(() => {
    if (videoRef.current) {
      videoRef.current.srcObject = hasVideoTrack ? stream : null;
    }
  }, [stream, hasVideoTrack]);

  return (
    <div className="bg-muted/40 relative aspect-video w-full overflow-hidden rounded-md border">
      {hasVideoTrack ? (
        <video
          ref={videoRef}
          muted
          autoPlay
          playsInline
          className="h-full w-full -scale-x-100 object-cover"
        />
      ) : (
        <div className="absolute inset-0 flex flex-col items-center justify-center gap-1.5">
          <VideoOff className="text-muted-foreground size-4" />
          <Muted className="text-[11px]">No preview</Muted>
        </div>
      )}
    </div>
  );
}

function DeviceSelect({
  devices,
  saved,
  onChange,
  placeholder,
}: {
  devices: MediaDeviceInfo[];
  saved: SavedDevice | null;
  onChange: (d: SavedDevice | null) => void;
  placeholder: string;
}) {
  const value = saved?.deviceId ?? SYSTEM_DEFAULT;
  return (
    <Select
      value={value}
      onValueChange={(v) => {
        if (v === SYSTEM_DEFAULT) {
          onChange(null);
          return;
        }
        const match = devices.find((d) => d.deviceId === v);
        if (match) onChange({ deviceId: match.deviceId, label: match.label });
      }}
    >
      <SelectTrigger size="sm" className="w-full">
        <SelectValue placeholder={placeholder} />
      </SelectTrigger>
      <SelectContent>
        <SelectItem value={SYSTEM_DEFAULT}>System default</SelectItem>
        {devices.map((d, i) => (
          <SelectItem key={d.deviceId} value={d.deviceId}>
            {deviceLabel(d, i)}
          </SelectItem>
        ))}
      </SelectContent>
    </Select>
  );
}

export default function AudioVideoSettingsPage() {
  const navigate = useNavigate();
  const {
    audioInputs,
    videoInputs,
    permissionState,
    requestLabels,
    error: deviceError,
  } = useMediaDevices();

  const mic = useMediaDevicesStore((s) => s.mic);
  const camera = useMediaDevicesStore((s) => s.camera);
  const setMic = useMediaDevicesStore((s) => s.setMic);
  const setCamera = useMediaDevicesStore((s) => s.setCamera);

  const effectiveMicId = useMemo(
    () => resolveEffectiveDeviceId(mic, audioInputs),
    [mic, audioInputs],
  );
  const effectiveCameraId = useMemo(
    () => resolveEffectiveDeviceId(camera, videoInputs),
    [camera, videoInputs],
  );

  const cameraAvailable = videoInputs.length > 0;
  const permissionGranted = permissionState === "granted";

  const { stream, error: previewError } = usePreviewStream(
    permissionGranted,
    effectiveMicId,
    effectiveCameraId,
    cameraAvailable,
  );

  const micUnavailable =
    permissionGranted && !isSavedDeviceAvailable(mic, audioInputs);
  const cameraUnavailable =
    permissionGranted && !isSavedDeviceAvailable(camera, videoInputs);

  return (
    <div className="flex h-screen flex-col">
      <div className="drag-region flex items-center gap-3 border-b px-3 py-1">
        <WindowControls />
        <Button
          variant="ghost"
          size="sm"
          className="no-drag text-muted-foreground"
          onClick={() => navigate(-1)}
        >
          <ArrowLeft className="size-3.5" />
        </Button>
        <span className="text-sm font-medium">Audio & Video</span>
        <div className="flex-1" />
      </div>

      <ScrollArea className="min-h-0 flex-1">
        <div className="space-y-5 px-5 py-5">
          {!permissionGranted && (
            <div className="bg-muted/40 flex items-start justify-between gap-3 rounded-md border px-3 py-2.5">
              <div className="min-w-0">
                <p className="text-sm font-medium">Allow device access</p>
                <Muted className="text-[11px] leading-snug">
                  Grant permission to see device names and a live preview.
                </Muted>
              </div>
              <Button size="sm" onClick={() => requestLabels()}>
                Allow
              </Button>
            </div>
          )}

          {/* Microphone */}
          <div className="space-y-2">
            <div className="flex items-center justify-between">
              <FieldLabel>Microphone</FieldLabel>
              <InlineLevelMeter stream={permissionGranted ? stream : null} />
            </div>
            <DeviceSelect
              devices={audioInputs}
              saved={mic}
              onChange={setMic}
              placeholder="System default"
            />
            {micUnavailable && (
              <Muted className="text-[11px]">
                Saved mic unavailable — using system default.
              </Muted>
            )}
          </div>

          {/* Camera */}
          <div className="space-y-2">
            <FieldLabel>Camera</FieldLabel>
            <DeviceSelect
              devices={videoInputs}
              saved={camera}
              onChange={setCamera}
              placeholder={
                videoInputs.length === 0 ? "No cameras found" : "System default"
              }
            />
            <CameraPreview stream={permissionGranted ? stream : null} />
            {cameraUnavailable && (
              <Muted className="text-[11px]">
                Saved camera unavailable — using system default.
              </Muted>
            )}
          </div>

          {(previewError || (deviceError && permissionState === "denied")) && (
            <Muted className="text-destructive text-[11px]">
              {previewError ?? deviceError}
            </Muted>
          )}
        </div>
      </ScrollArea>

      <div className="flex items-center justify-end border-t px-5 py-3">
        <Button size="sm" onClick={() => navigate(-1)}>
          Done
        </Button>
      </div>
    </div>
  );
}
