'use client';

import { useCallback, useEffect, useState } from 'react';
import { GripVertical, ChevronUp, ChevronDown } from 'lucide-react';
import { useTranslation } from '@/lib/localization/context';
import {
  getSidebarMenuConfig,
  setSidebarMenuConfig,
  DEFAULT_ORDER,
} from '@/lib/config/sidebarMenu';
import { cn } from '@/lib/utils';

interface MenuSettingsPanelProps {
  onMouseEnter: () => void;
  onMouseLeave: () => void;
  itemLabels: Record<string, string>;
}

export default function MenuSettingsPanel({
  onMouseEnter,
  onMouseLeave,
  itemLabels,
}: MenuSettingsPanelProps) {
  const { t } = useTranslation();
  const [config, setConfig] = useState(() => getSidebarMenuConfig());

  const refreshConfig = useCallback(() => {
    setConfig(getSidebarMenuConfig());
  }, []);

  useEffect(() => {
    const handler = () => refreshConfig();
    window.addEventListener('client-config-changed', handler);
    return () => window.removeEventListener('client-config-changed', handler);
  }, [refreshConfig]);

  const toggleVisible = (id: string) => {
    const next = { ...config.visible, [id]: !config.visible[id] };
    setSidebarMenuConfig({ ...config, visible: next });
    setConfig({ ...config, visible: next });
  };

  const mainIds = config.order.filter((id) => id !== 'profile' && id !== 'spaces');
  const hasSpaces = config.order.includes('spaces');
  const displayOrder = [...mainIds, ...(hasSpaces ? ['spaces'] : [])];

  const moveUp = (displayIndex: number) => {
    if (displayIndex <= 0) return;
    const idA = displayOrder[displayIndex - 1];
    const idB = displayOrder[displayIndex];
    const order = [...config.order];
    const idxA = order.indexOf(idA);
    const idxB = order.indexOf(idB);
    order[idxA] = idB;
    order[idxB] = idA;
    setSidebarMenuConfig({ ...config, order });
    setConfig({ ...config, order });
  };

  const moveDown = (displayIndex: number) => {
    if (displayIndex >= displayOrder.length - 1) return;
    const idA = displayOrder[displayIndex];
    const idB = displayOrder[displayIndex + 1];
    const order = [...config.order];
    const idxA = order.indexOf(idA);
    const idxB = order.indexOf(idB);
    order[idxA] = idB;
    order[idxB] = idA;
    setSidebarMenuConfig({ ...config, order });
    setConfig({ ...config, order });
  };

  const moveToIndex = (fromIndex: number, toIndex: number) => {
    if (fromIndex === toIndex || toIndex < 0 || toIndex >= displayOrder.length) return;
    const newDisplayOrder = [...displayOrder];
    const [removed] = newDisplayOrder.splice(fromIndex, 1);
    newDisplayOrder.splice(toIndex, 0, removed);
    const hasSpaces = config.order.includes('spaces');
    const newMainIds = newDisplayOrder.filter((id) => id !== 'profile' && id !== 'spaces');
    const newOrder = [...newMainIds, ...(hasSpaces ? ['spaces'] : []), 'profile'];
    setSidebarMenuConfig({ ...config, order: newOrder });
    setConfig({ ...config, order: newOrder });
  };

  const [draggedIndex, setDraggedIndex] = useState<number | null>(null);
  const [dragOverIndex, setDragOverIndex] = useState<number | null>(null);

  const handleDragStart = (e: React.DragEvent, index: number) => {
    e.dataTransfer.effectAllowed = 'move';
    e.dataTransfer.setData('text/plain', String(index));
    e.dataTransfer.setData('application/json', JSON.stringify({ index }));
    setDraggedIndex(index);
  };

  const handleDragOver = (e: React.DragEvent, index: number) => {
    e.preventDefault();
    e.dataTransfer.dropEffect = 'move';
    setDragOverIndex(index);
  };

  const handleDragLeave = () => {
    setDragOverIndex(null);
  };

  const handleDrop = (e: React.DragEvent, toIndex: number) => {
    e.preventDefault();
    const fromIndex = parseInt(e.dataTransfer.getData('text/plain'), 10);
    setDraggedIndex(null);
    setDragOverIndex(null);
    if (!Number.isNaN(fromIndex) && fromIndex !== toIndex) {
      moveToIndex(fromIndex, toIndex);
    }
  };

  const handleDragEnd = () => {
    setDraggedIndex(null);
    setDragOverIndex(null);
  };

  const resetToDefault = () => {
    const defaultConfig = {
      order: [...DEFAULT_ORDER],
      visible: Object.fromEntries(DEFAULT_ORDER.map((id) => [id, true])),
    };
    setSidebarMenuConfig(defaultConfig);
    setConfig(defaultConfig);
  };

  return (
    <div
      className="min-w-[180px] w-56 h-screen overflow-y-auto bg-light-secondary dark:bg-dark-secondary border border-light-200 dark:border-dark-200 shadow-xl py-2 z-[9999]"
      onMouseEnter={onMouseEnter}
      onMouseLeave={onMouseLeave}
    >
      <h3 className="text-sm font-medium text-black dark:text-white px-4 mb-1.5">
        {t('nav.sidebarSettings')}
      </h3>
      <p className="text-xs text-black/60 dark:text-white/60 px-4 mb-2">
        {t('nav.menuSettingsHint')}
      </p>
      <div className="flex flex-col gap-0.5 px-2">
        {displayOrder.map((id, index) => (
          <div
            key={id}
            onDragOver={(e) => handleDragOver(e, index)}
            onDragLeave={handleDragLeave}
            onDrop={(e) => handleDrop(e, index)}
            className={cn(
              'flex items-center gap-1.5 py-1 px-2',
              'hover:bg-light-200 dark:hover:bg-dark-200 transition-colors',
              dragOverIndex === index && 'bg-light-200 dark:bg-dark-200 ring-1 ring-inset ring-black/10 dark:ring-white/10',
            )}
          >
            <div
              draggable
              onDragStart={(e) => handleDragStart(e, index)}
              onDragEnd={handleDragEnd}
              className={cn(
                'flex items-center gap-0.5 cursor-grab active:cursor-grabbing touch-none',
                draggedIndex === index && 'opacity-50',
              )}
              title={t('nav.menuSettingsHint')}
            >
              <div className="flex flex-col gap-0.5">
              <button
                type="button"
                onClick={() => moveUp(index)}
                disabled={index === 0}
                className="p-0.5 rounded hover:bg-light-200 dark:hover:bg-dark-200 disabled:opacity-30 disabled:cursor-not-allowed"
                aria-label={t('nav.moveUp')}
              >
                <ChevronUp size={14} />
              </button>
              <button
                type="button"
                onClick={() => moveDown(index)}
                disabled={index === displayOrder.length - 1}
                className="p-0.5 rounded hover:bg-light-200 dark:hover:bg-dark-200 disabled:opacity-30 disabled:cursor-not-allowed"
                aria-label={t('nav.moveDown')}
              >
                <ChevronDown size={14} />
              </button>
              </div>
              <GripVertical size={14} className="text-black/40 dark:text-white/40 shrink-0" />
            </div>
            <span className="flex-1 text-sm text-black dark:text-white truncate min-w-0">
              {itemLabels[id] ?? id}
            </span>
            <button
              type="button"
              role="switch"
              aria-checked={config.visible[id] !== false}
              onClick={() => toggleVisible(id)}
              className={cn(
                'relative flex h-4 w-7 shrink-0 rounded-full transition-colors',
                config.visible[id] !== false
                  ? 'bg-black dark:bg-white'
                  : 'bg-light-300 dark:bg-dark-300',
              )}
            >
              <span
                className={cn(
                  'absolute top-0.5 h-3 w-3 rounded-full bg-white dark:bg-black transition-transform',
                  config.visible[id] !== false ? 'translate-x-3 left-0.5' : 'translate-x-0 left-0.5',
                )}
              />
            </button>
          </div>
        ))}
      </div>
      <button
        type="button"
        onClick={resetToDefault}
        className="mt-2 mx-4 py-1.5 px-4 text-xs text-black/60 dark:text-white/60 hover:text-black dark:hover:text-white hover:bg-light-200 dark:hover:bg-dark-200 transition-colors"
      >
        {t('nav.resetMenu')}
      </button>
    </div>
  );
}
