import { useApiHost } from "@/api";
import { useEffect, useMemo, useRef, useState } from "react";
import useSWR from "swr";
import ActivityIndicator from "../indicators/activity-indicator";
import { useResizeObserver } from "@/hooks/resize-observer";
import { isDesktop } from "react-device-detect";
import { cn } from "@/lib/utils";
import { useEnabledState } from "@/api/ws";

type CameraImageProps = {
  className?: string;
  camera: string;
  onload?: () => void;
  searchParams?: string;
};

export default function CameraImage({
  className,
  camera,
  onload,
  searchParams = "",
}: CameraImageProps) {
  const { data: config } = useSWR("config");
  const apiHost = useApiHost();
  const [imageLoaded, setImageLoaded] = useState(false);
  const containerRef = useRef<HTMLDivElement | null>(null);
  const imgRef = useRef<HTMLImageElement | null>(null);

  const cameraConfig = config?.cameras?.[camera];
  const { name } = cameraConfig ?? { name: camera };
  const { payload: enabledState } = useEnabledState(camera);
  const enabled = enabledState ? enabledState === "ON" : true;

  const [{ width: containerWidth, height: containerHeight }] =
    useResizeObserver(containerRef);

  const requestHeight = useMemo(() => {
    if (!cameraConfig || containerHeight == 0) {
      return 360;
    }

    return Math.min(
      cameraConfig.detect.height,
      Math.round(containerHeight * (isDesktop ? 1.1 : 1.25)),
    );
  }, [cameraConfig, containerHeight]);

  const [isPortraitImage, setIsPortraitImage] = useState(false);

  useEffect(() => {
    setImageLoaded(false);
    setIsPortraitImage(false);
  }, [camera]);

  useEffect(() => {
    if (!config || !imgRef.current) {
      return;
    }

    const newSrc = `${apiHost}api/${name}/latest.webp?height=${requestHeight}${
      searchParams ? `&${searchParams}` : ""
    }`;

    if (imgRef.current.src !== newSrc) {
      imgRef.current.src = newSrc;
    }
  }, [apiHost, name, searchParams, requestHeight, config, camera]);

  const handleImageLoad = () => {
    if (imgRef.current && containerWidth && containerHeight) {
      const { naturalWidth, naturalHeight } = imgRef.current;
      setIsPortraitImage(
        naturalWidth / naturalHeight < containerWidth / containerHeight,
      );
    }

    setImageLoaded(true);

    if (onload) {
      onload();
    }
  };

  return (
    <div className={className} ref={containerRef}>
      {enabled ? (
        <img
          ref={imgRef}
          className={cn(
            "object-contain",
            imageLoaded
              ? isPortraitImage
                ? "h-full w-auto"
                : "h-auto w-full"
              : "invisible",
            "rounded-lg md:rounded-2xl",
          )}
          onLoad={handleImageLoad}
          loading="lazy"
        />
      ) : (
        <div className="size-full rounded-lg border-2 border-muted bg-background_alt text-center md:rounded-2xl" />
      )}
      {!imageLoaded && enabled ? (
        <div className="absolute bottom-0 left-0 right-0 top-0 flex items-center justify-center">
          <ActivityIndicator />
        </div>
      ) : null}
    </div>
  );
}
