import { useCallback, useEffect, useRef, useState } from "react";
import { Mic, MicOff, AlertCircle } from "lucide-react";

export interface AudioRecorderProps {
  onChunk: (chunk: ArrayBuffer) => void;
  onEndUtterance: () => void;
  disabled?: boolean;
}

type RecorderState = "idle" | "recording" | "unsupported";

const PREFERRED_MIME = [
  "audio/webm;codecs=opus",
  "audio/webm",
  "audio/ogg;codecs=opus",
  "audio/mp4",
];

function getSupportedMimeType(): string | null {
  if (typeof MediaRecorder === "undefined") return null;
  for (const mime of PREFERRED_MIME) {
    if (MediaRecorder.isTypeSupported(mime)) return mime;
  }
  return null;
}

export default function AudioRecorder({ onChunk, onEndUtterance, disabled }: AudioRecorderProps) {
  const [state, setState] = useState<RecorderState>("idle");
  const [permissionDenied, setPermissionDenied] = useState(false);

  const mediaRecorderRef = useRef<MediaRecorder | null>(null);
  const streamRef = useRef<MediaStream | null>(null);
  const mimeType = useRef<string | null>(null);

  // Check support on mount
  useEffect(() => {
    if (
      typeof navigator.mediaDevices?.getUserMedia === "undefined" ||
      getSupportedMimeType() === null
    ) {
      setState("unsupported");
    }
    mimeType.current = getSupportedMimeType();
  }, []);

  const startRecording = useCallback(async () => {
    if (state !== "idle" || disabled) return;
    try {
      const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
      streamRef.current = stream;

      const recorder = new MediaRecorder(stream, {
        mimeType: mimeType.current ?? undefined,
        audioBitsPerSecond: 16000,
      });

      recorder.ondataavailable = async (e) => {
        if (e.data.size > 0) {
          const buf = await e.data.arrayBuffer();
          onChunk(buf);
        }
      };

      recorder.start(100); // 100ms chunks
      mediaRecorderRef.current = recorder;
      setState("recording");
    } catch (err: unknown) {
      if (err instanceof DOMException && err.name === "NotAllowedError") {
        setPermissionDenied(true);
      }
    }
  }, [state, disabled, onChunk]);

  const stopRecording = useCallback(() => {
    if (state !== "recording") return;

    const recorder = mediaRecorderRef.current;
    if (recorder && recorder.state !== "inactive") {
      recorder.onstop = () => {
        onEndUtterance();
      };
      recorder.stop();
    }

    streamRef.current?.getTracks().forEach((t) => t.stop());
    streamRef.current = null;
    mediaRecorderRef.current = null;
    setState("idle");
  }, [state, onEndUtterance]);

  // Cleanup on unmount
  useEffect(() => {
    return () => {
      streamRef.current?.getTracks().forEach((t) => t.stop());
    };
  }, []);

  if (state === "unsupported") {
    return (
      <div className="flex items-center gap-1.5 text-slate-400 text-xs px-2">
        <AlertCircle className="w-3.5 h-3.5" />
        <span>Audio tidak didukung browser ini</span>
      </div>
    );
  }

  if (permissionDenied) {
    return (
      <div className="flex items-center gap-1.5 text-amber-500 text-xs px-2">
        <MicOff className="w-3.5 h-3.5" />
        <span>Izin mikrofon ditolak</span>
      </div>
    );
  }

  const isRecording = state === "recording";

  return (
    <button
      onPointerDown={startRecording}
      onPointerUp={stopRecording}
      onPointerLeave={stopRecording}
      disabled={disabled}
      title={isRecording ? "Lepas untuk kirim" : "Tahan untuk merekam"}
      className={`relative flex items-center justify-center w-9 h-9 rounded-full transition-all duration-200 flex-shrink-0 ${
        isRecording
          ? "bg-red-500 text-white scale-110 shadow-lg shadow-red-200"
          : disabled
          ? "bg-slate-100 text-slate-300 cursor-not-allowed"
          : "bg-emerald-50 text-emerald-600 hover:bg-emerald-100 hover:scale-105"
      }`}
    >
      {isRecording ? (
        <>
          {/* Pulse ring */}
          <span className="absolute inset-0 rounded-full bg-red-400 animate-ping opacity-50" />
          <Mic className="w-4 h-4 relative z-10" />
        </>
      ) : (
        <Mic className="w-4 h-4" />
      )}
    </button>
  );
}
