'use client';

import { useCallback, useEffect, useRef, useState } from 'react';
import { Loader2, Video, X } from 'lucide-react';
import { Button } from '@/components/ui/button';
import { Dialog, DialogContent, DialogHeader, DialogTitle } from '@/components/ui/dialog';
import { cn } from '@/lib/utils';

export type ChatVideoCaptureMode = 'video' | 'note';

const MAX_DURATION_MS: Record<ChatVideoCaptureMode, number> = {
  note: 60_000,
  video: 5 * 60_000
};

function pickRecorderMimeType() {
  const candidates = ['video/webm;codecs=vp9,opus', 'video/webm;codecs=vp8,opus', 'video/webm', 'video/mp4'];
  return candidates.find((type) => MediaRecorder.isTypeSupported(type)) ?? '';
}

function formatTimer(ms: number) {
  const total = Math.max(0, Math.floor(ms / 1000));
  const mins = Math.floor(total / 60);
  const secs = total % 60;
  return `${mins}:${secs.toString().padStart(2, '0')}`;
}

interface ChatVideoCaptureDialogProps {
  open: boolean;
  mode: ChatVideoCaptureMode;
  onClose: () => void;
  onCaptured: (file: File, durationMs: number) => void;
}

export function ChatVideoCaptureDialog({ open, mode, onClose, onCaptured }: ChatVideoCaptureDialogProps) {
  const videoRef = useRef<HTMLVideoElement | null>(null);
  const streamRef = useRef<MediaStream | null>(null);
  const recorderRef = useRef<MediaRecorder | null>(null);
  const chunksRef = useRef<BlobPart[]>([]);
  const startedAtRef = useRef<number | null>(null);
  const timerRef = useRef<number | null>(null);

  const [initializing, setInitializing] = useState(false);
  const [recording, setRecording] = useState(false);
  const [elapsedMs, setElapsedMs] = useState(0);
  const [error, setError] = useState<string | null>(null);

  const stopStream = useCallback(() => {
    streamRef.current?.getTracks().forEach((track) => track.stop());
    streamRef.current = null;
    if (videoRef.current) {
      videoRef.current.srcObject = null;
    }
  }, []);

  const cleanup = useCallback(() => {
    if (timerRef.current !== null) {
      window.clearInterval(timerRef.current);
      timerRef.current = null;
    }
    if (recorderRef.current && recorderRef.current.state !== 'inactive') {
      recorderRef.current.stop();
    }
    recorderRef.current = null;
    chunksRef.current = [];
    startedAtRef.current = null;
    setRecording(false);
    setElapsedMs(0);
    stopStream();
  }, [stopStream]);

  useEffect(() => {
    if (!open) {
      cleanup();
      setError(null);
      return;
    }

    let cancelled = false;
    setInitializing(true);
    setError(null);

    void (async () => {
      try {
        const stream = await navigator.mediaDevices.getUserMedia({
          video: { facingMode: mode === 'note' ? 'user' : 'environment' },
          audio: true
        });
        if (cancelled) {
          stream.getTracks().forEach((track) => track.stop());
          return;
        }
        streamRef.current = stream;
        if (videoRef.current) {
          videoRef.current.srcObject = stream;
          await videoRef.current.play();
        }
      } catch {
        if (!cancelled) {
          setError('Не удалось получить доступ к камере и микрофону');
        }
      } finally {
        if (!cancelled) setInitializing(false);
      }
    })();

    return () => {
      cancelled = true;
      cleanup();
    };
  }, [cleanup, mode, open]);

  function stopRecording() {
    recorderRef.current?.stop();
    recorderRef.current = null;
    if (timerRef.current !== null) {
      window.clearInterval(timerRef.current);
      timerRef.current = null;
    }
    setRecording(false);
  }

  function startRecording() {
    const stream = streamRef.current;
    if (!stream || recording) return;

    const mimeType = pickRecorderMimeType();
    const recorder = mimeType ? new MediaRecorder(stream, { mimeType }) : new MediaRecorder(stream);
    chunksRef.current = [];
    recorder.ondataavailable = (event) => {
      if (event.data.size > 0) chunksRef.current.push(event.data);
    };
    recorder.onstop = () => {
      const durationMs = startedAtRef.current ? Date.now() - startedAtRef.current : 0;
      startedAtRef.current = null;
      const blob = new Blob(chunksRef.current, { type: recorder.mimeType || 'video/webm' });
      const extension = blob.type.includes('mp4') ? 'mp4' : 'webm';
      const prefix = mode === 'note' ? 'video-note' : 'video';
      const file = new File([blob], `${prefix}-${Date.now()}.${extension}`, { type: blob.type || 'video/webm' });
      onCaptured(file, durationMs);
      onClose();
    };

    recorderRef.current = recorder;
    startedAtRef.current = Date.now();
    setElapsedMs(0);
    setRecording(true);
    recorder.start(250);

    timerRef.current = window.setInterval(() => {
      const startedAt = startedAtRef.current;
      if (!startedAt) return;
      const nextElapsed = Date.now() - startedAt;
      setElapsedMs(nextElapsed);
      if (nextElapsed >= MAX_DURATION_MS[mode]) {
        stopRecording();
      }
    }, 200);
  }

  const title = mode === 'note' ? 'Запись кружка' : 'Запись видео';
  const hint = mode === 'note' ? 'Короткое круглое видеосообщение до 1 минуты' : 'Видеосообщение до 5 минут';

  return (
    <Dialog open={open} onOpenChange={(next) => !next && onClose()}>
      <DialogContent className="overflow-hidden rounded-[24px] p-0 sm:max-w-[420px]">
        <div className="border-b border-[#eceef4] px-5 py-4">
          <DialogHeader className="mb-0">
            <DialogTitle>{title}</DialogTitle>
            <p className="text-sm text-[#667085]">{hint}</p>
          </DialogHeader>
        </div>

        <div className="space-y-4 px-5 py-5">
          {error ? (
            <p className="rounded-xl bg-red-50 px-3 py-2 text-sm text-red-700">{error}</p>
          ) : (
            <div className="flex justify-center">
              <div
                className={cn(
                  'relative overflow-hidden bg-black',
                  mode === 'note' ? 'h-[240px] w-[240px] rounded-full' : 'h-[280px] w-full max-w-[360px] rounded-2xl'
                )}
              >
                <video ref={videoRef} className="h-full w-full object-cover" playsInline muted />
                {initializing ? (
                  <div className="absolute inset-0 flex items-center justify-center bg-black/35">
                    <Loader2 className="h-8 w-8 animate-spin text-white" />
                  </div>
                ) : null}
              </div>
            </div>
          )}

          <div className="flex items-center justify-center gap-2 text-sm font-medium text-[#667085]">
            <Video className="h-4 w-4" />
            {recording ? formatTimer(elapsedMs) : 'Готовы к записи'}
          </div>
        </div>

        <div className="flex items-center justify-between border-t border-[#eceef4] px-5 py-3">
          <Button type="button" variant="ghost" onClick={onClose}>
            <X className="mr-1 h-4 w-4" />
            Отмена
          </Button>
          <Button
            type="button"
            disabled={Boolean(error) || initializing}
            className={cn(recording && 'bg-red-500 hover:bg-red-600')}
            onClick={() => (recording ? stopRecording() : startRecording())}
          >
            {recording ? 'Остановить' : 'Начать запись'}
          </Button>
        </div>
      </DialogContent>
    </Dialog>
  );
}
