import React, { useState, useEffect, useRef, useCallback } from 'react';
import clsx from 'clsx';
import { useTranslation } from 'react-i18next';
import {
  useContactFolders,
  useCreateContactFolder,
  useUpdateContactFolder,
  useDeleteContactFolder,
  useMoveContactToFolder,
} from '@/api/hooks';
import { buildFolderTree, type ContactFolderTreeNode } from '@/api/contactFolders';
import { ChevronRight, Folder, Pencil, Plus, Tag, Trash2, Users } from 'lucide-react';

export type ContactFilter = 'all' | 'company' | 'person' | `tag:${string}` | `folder:${string}`;

export interface ContactFolderTreeProps {
  selectedFilter: ContactFilter;
  onSelect: (filter: ContactFilter) => void;
  tags: string[];
  loading?: boolean;
  contacts?: { id: string; displayname: string; type: string; folder_id?: string | null }[];
}

// Icons

const icon = (IconComp: React.ElementType, cls = 'w-4 h-4') => (
  <IconComp className={cls} aria-hidden="true" strokeWidth={2} />
);

const chevron = (open: boolean) => (
  <ChevronRight className={clsx('w-3.5 h-3.5 transition-transform flex-shrink-0', open && 'rotate-90')} aria-hidden="true" strokeWidth={2} />
);

const ICONS = {
  all: Users,
  folder: Folder,
  tag: Tag,
  edit: Pencil,
  trash: Trash2,
  plus: Plus,
};

// Context Menu

interface ContextMenuState {
  x: number;
  y: number;
  type: 'folder' | 'root';
  id: string | null;
}

function ContextMenu({
  state, onClose, onRename, onDelete, onNewFolder, onNewSubfolder,
}: {
  state: ContextMenuState;
  onClose: () => void;
  onRename: (id: string) => void;
  onDelete: (id: string) => void;
  onNewFolder: () => void;
  onNewSubfolder: (parentId: string) => void;
}) {
  const ref = useRef<HTMLDivElement>(null);

  useEffect(() => {
    const handler = (e: MouseEvent) => {
      if (ref.current && !ref.current.contains(e.target as Node)) onClose();
    };
    document.addEventListener('mousedown', handler);
    return () => document.removeEventListener('mousedown', handler);
  }, [onClose]);

  const items: { label: string; action: () => void; danger?: boolean }[] = [];

  if (state.type === 'folder') {
    items.push({ label: 'Umbenennen', action: () => { onRename(state.id!); onClose(); } });
    items.push({ label: 'Neuer Unterordner', action: () => { onNewSubfolder(state.id!); onClose(); } });
    items.push({ label: 'L\u00f6schen', action: () => { onDelete(state.id!); onClose(); }, danger: true });
  } else {
    items.push({ label: 'Neuer Ordner', action: () => { onNewFolder(); onClose(); } });
  }

  return (
    <div
      ref={ref}
      className="fixed z-50 bg-white border border-secondary-200 rounded-lg shadow-lg py-1 min-w-[160px]"
      style={{ left: state.x, top: state.y }}
    >
      {items.map((item, i) => (
        <button
          key={i}
          onClick={item.action}
          className={clsx(
            'w-full text-left px-3 py-1.5 text-sm hover:bg-secondary-100',
            item.danger && 'text-red-600 hover:bg-red-50'
          )}
        >
          {item.label}
        </button>
      ))}
    </div>
  );
}

// Folder Tree Item

function FolderTreeItem({
  node,
  depth,
  selectedFilter,
  onSelectFolder,
  onContextMenu,
  isDragOver,
  onDragOver,
  onDragLeave,
  onDrop,
}: {
  node: ContactFolderTreeNode;
  depth: number;
  selectedFilter: ContactFilter;
  onSelectFolder: (folderId: string) => void;
  onContextMenu: (e: React.MouseEvent, type: 'folder' | 'root', id: string | null) => void;
  isDragOver: boolean;
  onDragOver: (e: React.DragEvent, folderId: string) => void;
  onDragLeave: (folderId: string) => void;
  onDrop: (e: React.DragEvent, folderId: string) => void;
}) {
  const [expanded, setExpanded] = useState(true);
  const folderKey = `folder:${node.id}` as ContactFilter;
  const isActive = selectedFilter === folderKey;

  return (
    <div>
      <div
        onDragOver={(e) => onDragOver(e, node.id)}
        onDragLeave={() => onDragLeave(node.id)}
        onDrop={(e) => onDrop(e, node.id)}
        onContextMenu={(e) => onContextMenu(e, 'folder', node.id)}
        className={clsx(
          'group flex items-center gap-1.5 px-2 py-1.5 text-sm font-medium rounded-md cursor-pointer min-h-touch',
          'transition-colors focus:outline-none focus-visible:ring-2 focus-visible:ring-primary-500',
          isDragOver
            ? 'bg-primary-100 ring-2 ring-primary-400'
            : isActive
            ? 'bg-primary-50 text-primary-700'
            : 'text-secondary-700 hover:bg-secondary-100',
        )}
        style={{ paddingLeft: depth * 12 + 8 }}
        onClick={() => {
          setExpanded(!expanded);
          onSelectFolder(node.id);
        }}
      >
        {chevron(expanded)}
        {icon(ICONS.folder, 'w-4 h-4 text-secondary-400')}
        <span className="flex-1 truncate">{node.name}</span>
        {node.contact_count > 0 && (
          <span className="text-xs text-secondary-400 tabular-nums">{node.contact_count}</span>
        )}
        <button
          onClick={(e) => { e.stopPropagation(); onContextMenu(e, 'folder', node.id); }}
          className="opacity-0 group-hover:opacity-100 text-secondary-400 hover:text-primary-600 p-0.5"
          title="Umbenennen"
        >
          {icon(ICONS.edit, 'w-3.5 h-3.5')}
        </button>
        <button
          onClick={(e) => { e.stopPropagation(); onContextMenu(e, 'folder', node.id); }}
          className="opacity-0 group-hover:opacity-100 text-secondary-400 hover:text-red-600 p-0.5"
          title="L\u00f6schen"
        >
          {icon(ICONS.trash, 'w-3.5 h-3.5')}
        </button>
      </div>

      {expanded && node.children.map((child) => (
        <FolderTreeItem
          key={child.id}
          node={child}
          depth={depth + 1}
          selectedFilter={selectedFilter}
          onSelectFolder={onSelectFolder}
          onContextMenu={onContextMenu}
          isDragOver={false}
          onDragOver={onDragOver}
          onDragLeave={onDragLeave}
          onDrop={onDrop}
        />
      ))}
    </div>
  );
}

// Main Component

export function ContactFolderTree({
  selectedFilter,
  onSelect,
  tags,
  loading,
  contacts = [],
}: ContactFolderTreeProps) {
  const { t } = useTranslation();
  const [tagsOpen, setTagsOpen] = useState(true);
  const [contextMenu, setContextMenu] = useState<ContextMenuState | null>(null);
  const [dragOverFolderId, setDragOverFolderId] = useState<string | null>(null);

  const { data: folders, isLoading: foldersLoading } = useContactFolders();
  const createFolderMut = useCreateContactFolder();
  const updateFolderMut = useUpdateContactFolder();
  const deleteFolderMut = useDeleteContactFolder();
  const moveContactMut = useMoveContactToFolder();

  const folderList = folders ?? [];
  const tree = buildFolderTree(folderList);

  const itemCls = (active: boolean) =>
    clsx(
      'flex items-center gap-2 w-full px-2 py-1.5 rounded-md text-sm font-medium min-h-touch text-left',
      'transition-colors focus:outline-none focus-visible:ring-2 focus-visible:ring-primary-500',
      active ? 'bg-primary-50 text-primary-700' : 'text-secondary-700 hover:bg-secondary-100',
    );

  const handleContextMenu = useCallback((e: React.MouseEvent, type: 'folder' | 'root', id: string | null) => {
    e.preventDefault();
    e.stopPropagation();
    setContextMenu({ x: e.clientX, y: e.clientY, type, id });
  }, []);

  const handleNewFolder = () => {
    const name = prompt('Ordnername:');
    if (!name) return;
    createFolderMut.mutate({ name });
  };

  const handleNewSubfolder = (parentId: string) => {
    const name = prompt('Unterordnername:');
    if (!name) return;
    createFolderMut.mutate({ name, parent_id: parentId });
  };

  const handleRename = (id: string) => {
    const folder = folderList.find((f) => f.id === id);
    const newName = prompt('Neuer Name:', folder?.name || '');
    if (!newName) return;
    updateFolderMut.mutate({ id, data: { name: newName } });
  };

  const handleDelete = (id: string) => {
    if (!confirm('Ordner l\u00f6schen? Kontakte bleiben erhalten, werden aber keinem Ordner mehr zugeordnet.')) return;
    deleteFolderMut.mutate(id);
  };

  const handleDragOver = (e: React.DragEvent, folderId: string) => {
    e.preventDefault();
    e.stopPropagation();
    setDragOverFolderId(folderId);
  };

  const handleDragLeave = (folderId: string) => {
    if (dragOverFolderId === folderId) setDragOverFolderId(null);
  };

  const handleDrop = (e: React.DragEvent, folderId: string) => {
    e.preventDefault();
    e.stopPropagation();
    setDragOverFolderId(null);
    const contactId = e.dataTransfer.getData('text/plain');
    if (!contactId) return;
    moveContactMut.mutate({ contactId, folderId });
  };

  const handleRootDrop = (e: React.DragEvent) => {
    e.preventDefault();
    const contactId = e.dataTransfer.getData('text/plain');
    if (!contactId) return;
    moveContactMut.mutate({ contactId, folderId: null });
  };

  const handleRootDragOver = (e: React.DragEvent) => {
    e.preventDefault();
  };

  const handleSelectFolder = useCallback((folderId: string) => {
    onSelect(`folder:${folderId}` as ContactFilter);
  }, [onSelect]);

  return (
    <nav className="space-y-0.5" aria-label={t('contacts.title')} data-testid="contact-folder-tree">
      {/* Alle Kontakte */}
      <button
        onClick={() => onSelect('all')}
        className={itemCls(selectedFilter === 'all')}
        aria-current={selectedFilter === 'all' ? 'true' : undefined}
      >
        {icon(ICONS.all)}
        <span>{t('contacts.allContacts')}</span>
      </button>

      {/* Folder tree */}
      <div
        onDragOver={handleRootDragOver}
        onDrop={handleRootDrop}
        onContextMenu={(e) => handleContextMenu(e, 'root', null)}
      >
        {tree.map((node) => (
          <FolderTreeItem
            key={node.id}
            node={node}
            depth={0}
            selectedFilter={selectedFilter}
            onSelectFolder={handleSelectFolder}
            onContextMenu={handleContextMenu}
            isDragOver={dragOverFolderId === node.id}
            onDragOver={handleDragOver}
            onDragLeave={handleDragLeave}
            onDrop={handleDrop}
          />
        ))}

        {/* Root drop zone */}
        <div
          onDragOver={handleRootDragOver}
          onDrop={handleRootDrop}
          className="min-h-[12px] mt-1 rounded-md transition-colors hover:bg-secondary-50"
          onContextMenu={(e) => handleContextMenu(e, 'root', null)}
        />

        {(foldersLoading || loading) && (
          <div className="px-2 py-1 text-xs text-secondary-400">{t('common.loading')}</div>
        )}
      </div>

      {/* Tags */}
      {tags.length > 0 && (
        <div className="pt-1">
          <button
            onClick={() => setTagsOpen(!tagsOpen)}
            className="flex items-center gap-1.5 w-full px-2 py-1.5 rounded-md text-xs font-semibold text-secondary-500 uppercase tracking-wide hover:bg-secondary-100 min-h-touch text-left"
            aria-expanded={tagsOpen}
          >
            {chevron(tagsOpen)}
            {icon(ICONS.tag, 'w-3.5 h-3.5')}
            <span>{t('tags.title')}</span>
          </button>
          {tagsOpen && (
            <div className="mt-0.5 space-y-0.5">
              {tags.map((tag) => {
                const key = `tag:${tag}` as ContactFilter;
                return (
                  <button
                    key={key}
                    onClick={() => onSelect(key)}
                    style={{ paddingLeft: '32px' }}
                    className={itemCls(selectedFilter === key)}
                    aria-current={selectedFilter === key ? 'true' : undefined}
                  >
                    {icon(ICONS.tag, 'w-3.5 h-3.5')}
                    <span className="truncate">{tag}</span>
                  </button>
                );
              })}
            </div>
          )}
        </div>
      )}

      {contextMenu && (
        <ContextMenu
          state={contextMenu}
          onClose={() => setContextMenu(null)}
          onRename={handleRename}
          onDelete={handleDelete}
          onNewFolder={handleNewFolder}
          onNewSubfolder={handleNewSubfolder}
        />
      )}
    </nav>
  );
}
