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

import { useStores } from '@/app/(root)/AppProviders';
import { toast } from '@/components/toast/Toast';
import logWebUserEvent from '@/logging/logWebUserEvent';
import { Clip } from '@/state/clipStore';
import { getClipTitle } from '@/utils/clip';
import { SUPER_MODAL_Z_INDEX } from '@/utils/constants';

interface UseSongRenameOptions {
  clip: Clip;
  editable: boolean;
  source?: string;
}

interface UseSongRenameReturn {
  isEditing: boolean;
  editedTitle: string;
  isSaving: boolean;
  inputRef: React.RefObject<HTMLInputElement | null>;
  measureRef: React.RefObject<HTMLSpanElement | null>;

  handleEditClick: (e: React.MouseEvent) => void;
  handleSave: (e?: React.MouseEvent) => Promise<void>;
  handleCancel: (e?: React.MouseEvent) => void;
  handleInputChange: (e: React.ChangeEvent<HTMLInputElement>) => void;
  handleInputKeyDown: (e: React.KeyboardEvent<HTMLInputElement>) => void;
  updateInputWidth: () => void;
}

export function useSongRename({
  clip,
  editable,
  source = 'unknown',
}: UseSongRenameOptions): UseSongRenameReturn {
  const { clips } = useStores();
  const [isEditing, setIsEditing] = useState(false);
  const [editedTitle, setEditedTitle] = useState('');
  const [isSaving, setIsSaving] = useState(false);
  const inputRef = useRef<HTMLInputElement>(null);
  const measureRef = useRef<HTMLSpanElement>(null);

  const updateInputWidth = useCallback(() => {
    if (measureRef.current && inputRef.current) {
      const width = measureRef.current.offsetWidth;
      inputRef.current.style.width = `${Math.max(width + 2, 50)}px`;
    }
  }, []);

  useEffect(() => {
    if (isEditing && inputRef.current) {
      inputRef.current.focus();
      inputRef.current.select();
      updateInputWidth();
    }
  }, [isEditing, updateInputWidth]);

  const handleCancel = useCallback((e?: React.MouseEvent) => {
    e?.stopPropagation();
    setIsEditing(false);
    setEditedTitle('');
    setIsSaving(false);
  }, []);

  const handleEditClick = useCallback(
    (e: React.MouseEvent) => {
      e.stopPropagation();
      if (clip && editable) {
        setEditedTitle(getClipTitle(clip));
        setIsEditing(true);
      }
    },
    [clip, editable]
  );

  const handleSave = useCallback(
    async (e?: React.MouseEvent) => {
      e?.stopPropagation();
      if (!clip || !editedTitle.trim() || isSaving) {
        setIsEditing(false);
        setEditedTitle('');
        setIsSaving(false);
        return;
      }

      const trimmedTitle = editedTitle.trim();

      // Don't save if title hasn't changed
      if (clip.title === trimmedTitle) {
        setIsEditing(false);
        return;
      }

      setIsSaving(true);

      try {
        const result = await clips.setMetadata({
          clipId: clip.id,
          title: trimmedTitle,
        });

        if (result?.success) {
          logWebUserEvent({
            actionName: 'SongEditTitleRenamed',
            principalObjectValue: clip.id,
            principalObjectType: 'song',
            context: {
              source: source ?? 'unknown',
              oldTitle: clip.title || '',
              newTitle: trimmedTitle,
            },
          });

          setIsEditing(false);
          setIsSaving(false);

          toast({
            title: 'Title updated',
            status: 'success',
            duration: 2000,
            containerStyle: {
              zIndex: SUPER_MODAL_Z_INDEX,
            },
          });
        } else {
          toast({
            title: 'Failed to update title',
            description: 'Please try again',
            status: 'error',
            duration: 3000,
            containerStyle: {
              zIndex: SUPER_MODAL_Z_INDEX,
            },
          });
          // Revert on failure
          setEditedTitle(getClipTitle(clip));
          setIsEditing(false);
          setIsSaving(false);
        }
      } catch (error) {
        console.error('Failed to update title:', error);
        toast({
          title: 'Failed to update title',
          description: 'Please try again',
          status: 'error',
          duration: 3000,
          containerStyle: {
            zIndex: SUPER_MODAL_Z_INDEX,
          },
        });
        // Revert on error
        setEditedTitle(getClipTitle(clip));
        setIsEditing(false);
        setIsSaving(false);
      }
    },
    [clip, editedTitle, isSaving, clips, source]
  );

  const handleInputChange = useCallback(
    (e: React.ChangeEvent<HTMLInputElement>) => {
      setEditedTitle(e.target.value);
      requestAnimationFrame(updateInputWidth);
    },
    [updateInputWidth]
  );

  const handleInputKeyDown = useCallback(
    (e: React.KeyboardEvent<HTMLInputElement>) => {
      if (e.key === 'Enter') {
        e.preventDefault();
        e.stopPropagation();
        handleSave();
      } else if (e.key === 'Escape') {
        e.preventDefault();
        e.stopPropagation();
        handleCancel();
      }
    },
    [handleSave, handleCancel]
  );

  return {
    isEditing,
    editedTitle,
    isSaving,
    inputRef,
    measureRef,
    handleEditClick,
    handleSave,
    handleCancel,
    handleInputChange,
    handleInputKeyDown,
    updateInputWidth,
  };
}
