import React, { useEffect, useLayoutEffect, useMemo, useRef, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { ListMusic, Plus } from 'lucide-react';
import { resolveAlbum, resolveMediaServerId, resolvePlaylist } from '@/features/offline';
import type { SubsonicPlaylist } from '@/lib/api/subsonicTypes';
import { usePlaylistStore } from '@/features/playlist';
import { showToast } from '../../utils/ui/toast';
import {
  confirmAddAllDuplicates,
  isSmartPlaylistName,
} from '../../utils/componentHelpers/contextMenuHelpers';

interface Props {
  albumIds: string[];
  onDone: () => void;
  triggerId?: string;
}

export function MultiAlbumToPlaylistSubmenu({ albumIds, onDone, triggerId: _triggerId }: Props) {
  const { t } = useTranslation();
  const [resolvedIds, setResolvedIds] = useState<string[] | null>(null);
  const [totalAlbums, setTotalAlbums] = useState(0);
  const [showLoading, setShowLoading] = useState(false);

  useEffect(() => {
    // React Compiler set-state-in-effect rule: state set from a timer/animation callback.
    // eslint-disable-next-line react-hooks/set-state-in-effect
    setTotalAlbums(albumIds.length);
    const loadingTimeout = setTimeout(() => setShowLoading(true), 300);
    (async () => {
      const serverId = resolveMediaServerId();
      const albumSongs = serverId
        ? await Promise.all(albumIds.map(id => resolveAlbum(serverId, id).then(r => r?.songs ?? []).catch(() => [])))
        : [];
      const allSongs = albumSongs.flat();
      setResolvedIds(allSongs.map(s => s.id));
    })().catch(() => setResolvedIds([]));
    return () => clearTimeout(loadingTimeout);
  }, [albumIds]);

  const handleAddWithToast = async (pl: SubsonicPlaylist, songIds: string[]) => {
    const { updatePlaylist } = await import('@/lib/api/subsonicPlaylists');
    const touchPlaylist = usePlaylistStore.getState().touchPlaylist;

    try {
      const serverId = resolveMediaServerId();
      if (!serverId) return;
      const resolved = await resolvePlaylist(serverId, pl.id);
      if (!resolved) return;
      const { songs: existingSongs } = resolved;
      const existingIds = new Set(existingSongs.map((s) => s.id));

      const newIds: string[] = [];
      const duplicateIds: string[] = [];

      for (const id of songIds) {
        if (existingIds.has(id)) duplicateIds.push(id);
        else newIds.push(id);
      }

      const addedCount = newIds.length;
      const duplicateCount = duplicateIds.length;

      if (addedCount > 0) {
        await updatePlaylist(pl.id, [...existingSongs.map((s) => s.id), ...newIds]);
        touchPlaylist(pl.id);
        if (duplicateCount > 0) {
          showToast(t('playlists.addPartial', { added: addedCount, skipped: duplicateCount, playlist: pl.name }), 4000, 'info');
        } else {
          showToast(t('playlists.addSuccess', { count: addedCount, playlist: pl.name }), 3000, 'info');
        }
      } else if (duplicateCount > 0) {
        const accepted = await confirmAddAllDuplicates(pl.name, duplicateCount, t);
        if (accepted) {
          await updatePlaylist(pl.id, [...existingSongs.map((s) => s.id), ...songIds]);
          touchPlaylist(pl.id);
          showToast(t('playlists.addedAsDuplicates', { count: duplicateCount, playlist: pl.name }), 3000, 'info');
        } else {
          showToast(t('playlists.addAllSkipped', { count: duplicateCount, playlist: pl.name }), 4000, 'info');
        }
      }
    } catch {
      showToast(t('playlists.addError'), 4000, 'error');
    }
    onDone();
  };

  // Custom AddToPlaylistSubmenu with toast notifications for multiple albums
  function MultiAddToPlaylistSubmenu({ songIds, onDone: innerOnDone }: { songIds: string[]; onDone: () => void }) {
    const subRef = useRef<HTMLDivElement>(null);
    const newNameRef = useRef<HTMLInputElement>(null);
    const [adding, setAdding] = useState<string | null>(null);
    const [creating, setCreating] = useState(false);
    const [newName, setNewName] = useState('');
    const [flipLeft, setFlipLeft] = useState(false);
    const [flipUp, setFlipUp] = useState(false);
    const [visible, setVisible] = useState(false);
    const storePlaylists = usePlaylistStore((s) => s.playlists);

    const playlists = useMemo(() => {
      return [...storePlaylists]
        .filter(p => !isSmartPlaylistName(p.name))
        .sort((a, b) => a.name.localeCompare(b.name));
    }, [storePlaylists]);

    useLayoutEffect(() => {
      if (subRef.current) {
        const rect = subRef.current.getBoundingClientRect();
        if (rect.right > window.innerWidth - 8) setFlipLeft(true);
        if (rect.bottom > window.innerHeight - 8) setFlipUp(true);
        setVisible(true);
      }
    }, []);

    useEffect(() => {
      if (creating) newNameRef.current?.focus();
    }, [creating]);

    const handleAdd = async (pl: SubsonicPlaylist) => {
      setAdding(pl.id);
      await handleAddWithToast(pl, songIds);
      setAdding(null);
    };

    const handleCreate = async () => {
      const name = newName.trim() || t('playlists.unnamed');
      try {
        const { createPlaylist } = await import('@/lib/api/subsonicPlaylists');
        const pl = await createPlaylist(name, songIds);
        if (pl?.id) {
          usePlaylistStore.getState().touchPlaylist(pl.id);
          showToast(t('playlists.createAndAddSuccess', { count: songIds.length, playlist: pl.name || name }), 3000, 'info');
        }
      } catch {
        showToast(t('playlists.createError'), 4000, 'error');
      }
      innerOnDone();
    };

    const subStyle: React.CSSProperties = flipLeft
      ? { right: '100%', left: 'auto', top: flipUp ? 'auto' : -4, bottom: flipUp ? 0 : 'auto' }
      : { left: '100%', right: 'auto', top: flipUp ? 'auto' : -4, bottom: flipUp ? 0 : 'auto' };

    return (
      <div className="context-submenu" ref={subRef} style={{ ...subStyle, visibility: visible ? 'visible' : 'hidden' }}>
        {!creating ? (
          <div className="context-menu-item context-submenu-new" onClick={e => { e.stopPropagation(); setCreating(true); }}>
            <Plus size={13} /> {t('playlists.newPlaylist')}
          </div>
        ) : (
          <div className="context-submenu-create" onClick={e => e.stopPropagation()}>
            <input
              ref={newNameRef}
              className="context-submenu-input"
              placeholder={t('playlists.createName')}
              value={newName}
              onChange={e => setNewName(e.target.value)}
              onKeyDown={e => {
                if (e.key === 'Enter') handleCreate();
                if (e.key === 'Escape') { setCreating(false); setNewName(''); }
              }}
            />
            <button className="context-submenu-create-btn" onClick={handleCreate}>
              <Plus size={13} />
            </button>
          </div>
        )}
        <div className="context-menu-divider" />
        {playlists.length === 0 && (
          <div className="context-submenu-empty">{t('playlists.empty')}</div>
        )}
        {playlists.map((pl) => (
          <div
            key={pl.id}
            className="context-menu-item"
            onClick={() => handleAdd(pl)}
            style={{ opacity: adding === pl.id ? 0.5 : 1, pointerEvents: adding ? 'none' : undefined }}
          >
            <ListMusic size={13} />
            <span style={{ overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{pl.name}</span>
          </div>
        ))}
      </div>
    );
  }

  if (resolvedIds === null) {
    if (!showLoading) {
      return <div className="context-submenu" style={{ minWidth: 190 }} />;
    }
    return (
      <div className="context-submenu" style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', padding: '0.75rem', gap: '0.5rem', minWidth: 190 }}>
        <div className="spinner" style={{ width: 16, height: 16 }} />
        <span style={{ fontSize: 12, color: 'var(--text-muted)' }}>
          {t('playlists.loadingAlbums', { count: totalAlbums })}
        </span>
      </div>
    );
  }
  if (resolvedIds.length === 0) return null;
  // React Compiler rule: component intentionally defined inline for closure access.
  // eslint-disable-next-line react-hooks/static-components
  return <MultiAddToPlaylistSubmenu songIds={resolvedIds} onDone={onDone} />;
}
