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';

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 = (path: string, cls = 'w-4 h-4') => (
  <svg className={cls} fill="none" viewBox="0 0 24 24" stroke="currentColor" aria-hidden="true">
    <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d={path} />
  </svg>
);

const chevron = (open: boolean) => (
  <svg
    className={clsx('w-3.5 h-3.5 transition-transform flex-shrink-0', open && 'rotate-90')}
    fill="none" viewBox="0 0 24 24" stroke="currentColor" aria-hidden="true"
  >
    <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 5l7 7-7 7" />
  </svg>
);

const ICONS = {
  all: 'M17 20h5v-2a3 3 0 00-5.356-1.857M17 20H7m10 0v-2c0-.656-.126-1.283-.356-1.857M7 20H2v-2a3 3 0 015.356-1.857M7 20v-2c0-.656.126-1.283.356-1.857m0 0a5.002 5.002 0 019.288 0M15 7a3 3 0 11-6 0 3 3 0 016 0zm6-3a2 2 0 11-4 0 2 2 0 014 0zM7 10a2 2 0 11-4 0 2 2 0 014 0z',
  company: 'M19 21V5a2 2 0 00-2-2H7a2 2 0 00-2 2v16m14 0h2m-2 0h-5m-9 0H3m2 0h5M9 7h1m-1 4h1m4-4h1m-1 4h1m-5 10v-5a1 1 0 011-1h2a1 1 0 011 1v5m-4 0h4',
  person: 'M16 7a4 4 0 11-8 0 4 4 0 018 0zM12 14a7 7 0 00-7 7h14a7 7 0 00-7-7z',
  tag: 'M7 7h.01M7 3h5a1.99 1.99 0 01.832.184l4 2A2 2 0 0118 7v10a2 2 0 01-2 2H7a2 2 0 01-2-2V5a2 2 0 012-2z',
  // Contact person icon (used instead of folder icon)
  folder: 'M17 20h5v-2a3 3 0 00-5.356-1.857M17 20H7m10 0v-2c0-.656-.126-1.283-.356-1.857M7 20H2v-2a3 3 0 015.356-1.857M7 20v-2c0-.656.126-1.283.356-1.857m0 0a5.002 5.002 0 019.288 0M15 7a3 3 0 11-6 0 3 3 0 016 0zm6-3a2 2 0 11-4 0 2 2 0 014 0zM7 10a2 2 0 11-4 0 2 2 0 014 0z',
  contactPerson: 'M16 7a4 4 0 11-8 0 4 4 0 018 0zM12 14a7 7 0 00-7 7h14a7 7 0 00-7-7z',
  edit: 'M11 5H6a2 2 0 00-2 2v11a2 2 0 002 2h11a2 2 0 002-2v-5m-1.414-9.414a2 2 0 112.828 2.828L11.828 15H9v-2.828l8.586-8.586z',
  trash: 'M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16',
  plus: 'M12 4v16m8-8H4',
};

// ── 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öschen', 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,
  contacts,
}: {
  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;
  contacts: { id: string; displayname: string; type: string; folder_id?: string | null }[];
}) {
  const [expanded, setExpanded] = useState(true);
  const folderKey = `folder:${node.id}` as ContactFilter;
  const isActive = selectedFilter === folderKey;
  const folderContacts = contacts.filter((c) => c.folder_id === node.id);

  return (
    <div>
      {/* Folder header — drop target */}
      <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)}
        {/* Contact person icon instead of folder icon */}
        {icon(ICONS.contactPerson, '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öschen"
        >
          {icon(ICONS.trash, 'w-3.5 h-3.5')}
        </button>
      </div>

      {/* Contacts inside folder (leaf nodes) */}
      {expanded && folderContacts.length > 0 && (
        <div>
          {folderContacts.map((contact) => (
            <div
              key={contact.id}
              draggable
              onDragStart={(e) => {
                e.dataTransfer.setData('text/plain', contact.id);
                e.dataTransfer.effectAllowed = 'move';
              }}
              onClick={() => onSelectFolder(node.id)}
              className={clsx(
                'group flex items-center gap-2 px-3 py-1 text-sm cursor-grab rounded-md hover:bg-secondary-100 min-h-touch',
              )}
              style={{ paddingLeft: depth * 12 + 32 }}
            >
              {icon(
                contact.type === 'company' ? ICONS.company : ICONS.person,
                'w-3.5 h-3.5 text-secondary-400 flex-shrink-0',
              )}
              <span className="flex-1 truncate text-secondary-600">{contact.displayname}</span>
            </div>
          ))}
        </div>
      )}

      {/* Child folders */}
      {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}
          contacts={contacts}
        />
      ))}
    </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 [dragContactId, setDragContactId] = 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öschen? 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 });
  };

  // Root drop zone (unassign from folder)
  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();
  };

  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>

      {/* Firmen */}
      <button
        onClick={() => onSelect('company')}
        className={itemCls(selectedFilter === 'company')}
        aria-current={selectedFilter === 'company' ? 'true' : undefined}
      >
        {icon(ICONS.company)}
        <span>{t('contacts.companies')}</span>
      </button>

      {/* Privatpersonen */}
      <button
        onClick={() => onSelect('person')}
        className={itemCls(selectedFilter === 'person')}
        aria-current={selectedFilter === 'person' ? 'true' : undefined}
      >
        {icon(ICONS.person)}
        <span>{t('contacts.persons')}</span>
      </button>

      {/* Folders section */}
      <div className="pt-1">
        <div className="flex items-center justify-between px-2 py-1">
          <span className="text-xs font-semibold text-secondary-500 uppercase tracking-wide">Ordner</span>
          <button
            onClick={handleNewFolder}
            className="text-secondary-400 hover:text-primary-600 p-0.5"
            title="Neuer Ordner"
          >
            {icon(ICONS.plus, 'w-3.5 h-3.5')}
          </button>
        </div>

        {tree.map((node) => (
          <FolderTreeItem
            key={node.id}
            node={node}
            depth={0}
            selectedFilter={selectedFilter}
            onSelectFolder={(folderId) => onSelect(`folder:${folderId}` as ContactFilter)}
            onContextMenu={handleContextMenu}
            isDragOver={dragOverFolderId === node.id}
            onDragOver={handleDragOver}
            onDragLeave={handleDragLeave}
            onDrop={handleDrop}
            contacts={contacts}
          />
        ))}

        {/* Root drop zone — unassign contact */}
        <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 — collapsible */}
      {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>
  );
}
