import {
  useCallback,
  useRef,
  useState,
} from 'react';

import type { Area, Point } from 'react-easy-crop';

export type AspectOption = {
  key: string;
  label: string;
  value: number | undefined;
};

export const ASPECT_OPTIONS: AspectOption[] = [
  { key: 'free', label: 'aspect_free', value: undefined },
  { key: '1:1', label: '1:1', value: 1 },
  { key: '4:3', label: '4:3', value: 4 / 3 },
  { key: '3:4', label: '3:4', value: 3 / 4 },
  { key: '16:9', label: '16:9', value: 16 / 9 },
];

const DEFAULT_ADJUST = {
  brightness: 100,
  contrast: 100,
  saturate: 100,
};

function deriveFileMeta(url: string, fallbackType: string) {
  let pathname = url;
  try {
    pathname = new URL(url, window.location.origin).pathname;
  } catch {
    pathname = url;
  }
  const rawName = pathname.split('/').pop() || 'image';
  const name = rawName.split('?')[0] || 'image';
  return { mimeType: fallbackType, fileName: name };
}

export function useImageEditor() {
  const [objectUrl, setObjectUrl] = useState<string | null>(null);
  const [loading, setLoading] = useState(false);
  const [processing, setProcessing] = useState(false);

  const [crop, setCrop] = useState<Point>({ x: 0, y: 0 });
  const [zoom, setZoom] = useState(1);
  const [rotation, setRotation] = useState(0);
  const [flipH, setFlipH] = useState(false);
  const [flipV, setFlipV] = useState(false);
  const [aspect, setAspect] = useState<number | undefined>(undefined);
  const [adjust, setAdjust] = useState(DEFAULT_ADJUST);
  const [croppedAreaPixels, setCroppedAreaPixels] = useState<Area | null>(null);

  const objectUrlRef = useRef<string | null>(null);
  const blobRef = useRef<Blob | null>(null);
  const fileMetaRef = useRef<{ mimeType: string; fileName: string }>({
    mimeType: 'image/png',
    fileName: 'image.png',
  });

  const resetTransforms = useCallback(() => {
    setCrop({ x: 0, y: 0 });
    setZoom(1);
    setRotation(0);
    setFlipH(false);
    setFlipV(false);
    setAspect(undefined);
    setAdjust(DEFAULT_ADJUST);
    setCroppedAreaPixels(null);
  }, []);

  const cleanup = useCallback(() => {
    if (objectUrlRef.current) {
      URL.revokeObjectURL(objectUrlRef.current);
      objectUrlRef.current = null;
    }
    blobRef.current = null;
    setObjectUrl(null);
    setLoading(false);
    setProcessing(false);
    resetTransforms();
  }, [resetTransforms]);

  const load = useCallback(
    async (imageUrl: string) => {
      if (objectUrlRef.current) {
        URL.revokeObjectURL(objectUrlRef.current);
        objectUrlRef.current = null;
      }
      blobRef.current = null;
      resetTransforms();
      setLoading(true);
      try {
        // Prefetch the bytes so both the preview and the canvas export can use
        // a same-origin blob: URL (no CORS taint, no crossOrigin needed).
        const response = await fetch(imageUrl, { mode: 'cors' });
        const blob = await response.blob();
        const url = URL.createObjectURL(blob);
        objectUrlRef.current = url;
        blobRef.current = blob;
        fileMetaRef.current = deriveFileMeta(imageUrl, blob.type || 'image/png');
        setObjectUrl(url);
      } catch {
        // Fetch blocked (e.g. cross-origin without CORS in dev): still show the
        // image via the raw URL so editing keeps working; export will attempt
        // crossOrigin and may fail if the server has no CORS headers.
        blobRef.current = null;
        objectUrlRef.current = null;
        fileMetaRef.current = deriveFileMeta(imageUrl, 'image/png');
        setObjectUrl(imageUrl);
      } finally {
        setLoading(false);
      }
    },
    [resetTransforms],
  );

  const onCropComplete = useCallback((_area: Area, areaPixels: Area) => {
    setCroppedAreaPixels(areaPixels);
  }, []);

  const rotate90 = useCallback(() => {
    setRotation((prev) => (prev + 90) % 360);
  }, []);

  const toggleFlipH = useCallback(() => setFlipH((prev) => !prev), []);
  const toggleFlipV = useCallback(() => setFlipV((prev) => !prev), []);

  const setBrightness = useCallback(
    (value: number) => setAdjust((prev) => ({ ...prev, brightness: value })),
    [],
  );
  const setContrast = useCallback(
    (value: number) => setAdjust((prev) => ({ ...prev, contrast: value })),
    [],
  );
  const setSaturate = useCallback(
    (value: number) => setAdjust((prev) => ({ ...prev, saturate: value })),
    [],
  );

  const selectAspect = useCallback((value: number | undefined) => {
    setAspect(value);
  }, []);

  return {
    objectUrl,
    blobRef,
    loading,
    processing,
    setProcessing,
    fileMeta: fileMetaRef,
    crop,
    setCrop,
    zoom,
    setZoom,
    rotation,
    setRotation,
    flipH,
    flipV,
    aspect,
    adjust,
    croppedAreaPixels,
    onCropComplete,
    rotate90,
    toggleFlipH,
    toggleFlipV,
    setBrightness,
    setContrast,
    setSaturate,
    selectAspect,
    reset: resetTransforms,
    load,
    cleanup,
  };
}

export type ImageEditorState = ReturnType<typeof useImageEditor>;
