import { Button } from "@/components/ui/button";
import { useAuth } from "@/store/auth";
import { useVerify } from "@/store/verify";
import { User } from "lucide-react";
import { useCallback, useEffect, useRef, useState, type FC } from "react";
import { Link } from "react-router";

const VerifyAvatarPage: FC = () => {
  const profile = useAuth((s) => s.profile);

  const videoRef = useRef<HTMLVideoElement | null>(null);
  const canvasRef = useRef<HTMLCanvasElement | null>(null);
  const [stream, setStream] = useState<MediaStream | null>(null);
  const [avatar, setAvatar] = useState<string | null>(null);
  const [error, setError] = useState<string | null>(null);
  const [takingPicture, setTakingPicture] = useState(false);

  const fileInputRef = useRef<HTMLInputElement | null>(null);

  const uploadAvatar = useVerify((s) => s.uploadAvatar);
  const uploading = useVerify((s) => s.uploading);

  useEffect(() => {
    if (profile?.profile_picture) setAvatar(profile.profile_picture);
  }, [profile?.profile_picture]);

  // Request camera stream
  useEffect(() => {
    if (!takingPicture) return;
    if (!navigator.mediaDevices?.getUserMedia) {
      setError("Camera not supported on this device/browser.");
      return;
    }
    navigator.mediaDevices
      .getUserMedia({ video: true })
      .then((mediaStream) => {
        setStream(mediaStream);
        setError(null);
        if (videoRef.current) {
          videoRef.current.srcObject = mediaStream;
        }
      })
      .catch(() => setError("Unable to access camera."));
    return () => {
      // Clean up camera stream when component unmounts or stops taking picture
      if (stream) {
        stream.getTracks().forEach((track) => track.stop());
        setStream(null);
      }
    };
    // eslint-disable-next-line
  }, [takingPicture]);

  const handleTakePicture = useCallback(() => {
    setTakingPicture(true);
  }, []);

  const handleCapture = useCallback(() => {
    if (!videoRef.current || !canvasRef.current) return;
    const context = canvasRef.current.getContext("2d");
    if (!context) return;
    // Set canvas size to video size
    canvasRef.current.width = videoRef.current.videoWidth;
    canvasRef.current.height = videoRef.current.videoHeight;
    context.drawImage(
      videoRef.current,
      0,
      0,
      videoRef.current.videoWidth,
      videoRef.current.videoHeight,
    );
    const imageData = canvasRef.current.toDataURL("image/png");
    setAvatar(imageData);
    setTakingPicture(false);
  }, []);

  const handleSelectFromDevice = useCallback(() => {
    fileInputRef.current?.click();
  }, []);

  const handleFileChange = useCallback(
    (e: React.ChangeEvent<HTMLInputElement>) => {
      const file = e.target.files?.[0];
      if (!file) return;
      if (!file.type.startsWith("image/")) {
        setError("Please select an image file.");
        return;
      }
      const reader = new FileReader();
      reader.onload = (event) => {
        setAvatar(event.target?.result as string);
        setError(null);
      };
      reader.readAsDataURL(file);
    },
    [],
  );

  const handleRetake = useCallback(() => {
    setAvatar(null);
    setTakingPicture(false);
  }, []);

  const handleUpload = useCallback(async () => {
    if (!avatar) return;

    const res = await fetch(avatar);
    const blob = await res.blob();

    const file = new File([blob], "avatar.png", { type: blob.type });

    uploadAvatar(file);
  }, [avatar, uploadAvatar]);

  return (
    <div className="w-full sm:max-w-sm mx-auto p-4">
      <div className="flex flex-col gap-2 w-full max-w-xs mx-auto">
        <h1 className="text-xl font-medium dark:text-gray-200">
          Profile Picture
        </h1>
        <p className="dark:text-gray-400 mb-6">
          Please take a photo of yourself for your avatar in order to continue.
        </p>
        <div className="relative w-48 h-48 mx-auto rounded-full border-4 border-blue-500 overflow-hidden bg-gray-100 dark:bg-gray-800 flex items-center justify-center mb-6">
          {takingPicture ? (
            <video
              ref={videoRef}
              autoPlay
              playsInline
              className="w-full h-full object-cover rounded-lg bg-black"
            />
          ) : avatar ? (
            <img
              src={avatar}
              alt="Avatar"
              className="w-full h-full object-cover"
            />
          ) : (
            <span className="text-4xl text-gray-400">
              <User size={48} />
            </span>
          )}
        </div>
        {error && <div className="text-red-500 text-center">{error}</div>}

        {/* File input (hidden) */}
        <input
          ref={fileInputRef}
          type="file"
          accept="image/*"
          className="hidden"
          onChange={handleFileChange}
        />

        {!avatar && !takingPicture && (
          <Button onClick={handleTakePicture}>Take Photo</Button>
        )}
        {!avatar && !takingPicture && (
          <Button variant="outlined" onClick={handleSelectFromDevice}>
            Pick from Device
          </Button>
        )}

        {takingPicture && (
          <div className="flex flex-col items-center gap-2 w-full">
            <Button onClick={handleCapture}>Capture</Button>
            <Button variant="outlined" onClick={() => setTakingPicture(false)}>
              Cancel
            </Button>
          </div>
        )}

        {/* Hidden canvas for snapshot */}
        <canvas ref={canvasRef} style={{ display: "none" }} />

        {avatar && (
          <>
            <Link to="/verify/review" className="w-full">
              <Button
                className="w-full"
                loading={uploading}
                disabled={uploading}
                onClick={handleUpload}
              >
                Next
              </Button>
            </Link>
            <Button
              className="border-yellow-500 text-yellow-500 hover:border-yellow-600 hover:text-yellow-600"
              variant="outlined"
              onClick={handleRetake}
            >
              Retake/Choose Another
            </Button>
          </>
        )}
      </div>
    </div>
  );
};

export default VerifyAvatarPage;
