/**
 * SourceTree - left sidebar directory tree for DMS.
 * Replaces FolderTree with a "sources" concept:
 *   ▼ Meine Dateien (local folders)
 *   ▼ Geteilte Ordner (shared files from other users)
 *   ▼ Externe Speicher (placeholder for future plugins)
 *
 * Folders are drop targets (accept files) and draggable (for reparenting).
 */

import React, { useState } from 'react';
import clsx from 'clsx';
import { useTranslation } from 'react-i18next';
import type { DmsFolder, DmsFile } from '@/api/dms';

interface SourceTreeFolderItemProps {
  folder: DmsFolder;
  level: number;
  selectedFolderId: string | null;
  onSelect: (folderId: string) => void;
  onDropFiles: (fileIds: string[], targetFolderId: string) => void;
  onDropFolder: (sourceFolderId: string, targetFolderId: string) => void;
}

function SourceTreeFolderItem({
  folder,
  level,
  selectedFolderId,
  onSelect,
  onDropFiles,
  onDropFolder,
}: SourceTreeFolderItemProps) {
  const { t } = useTranslation();
  const [expanded, setExpanded] = useState(true);
  const [isDropTarget, setIsDropTarget] = useState(false);
  const hasChildren = folder.children && folder.children.length > 0;
  const isSelected = selectedFolderId === folder.id;

  function handleDragOver(e: React.DragEvent) {
    e.preventDefault();
    e.stopPropagation();
    e.dataTransfer.dropEffect = 'move';
    if (!isDropTarget) setIsDropTarget(true);
  }

  function handleDragLeave(e: React.DragEvent) {
    e.stopPropagation();
    setIsDropTarget(false);
  }

  function handleDrop(e: React.DragEvent) {
    e.preventDefault();
    e.stopPropagation();
    setIsDropTarget(false);
    try {
      const data = JSON.parse(e.dataTransfer.getData('application/json'));
      if (data.type === 'files' && data.ids) {
        onDropFiles(data.ids, folder.id);
      } else if (data.type === 'folder' && data.id) {
        if (data.id !== folder.id) {
          onDropFolder(data.id, folder.id);
        }
      }
    } catch {
      // ignore invalid drop data
    }
  }

  function handleFolderDragStart(e: React.DragEvent) {
    e.stopPropagation();
    e.dataTransfer.setData('application/json', JSON.stringify({ type: 'folder', id: folder.id }));
    e.dataTransfer.effectAllowed = 'move';
  }

  return (
    <li role="treeitem" aria-expanded={hasChildren ? expanded : undefined} aria-selected={isSelected}>
      <div
        className={clsx(
          'flex items-center gap-1 px-2 py-1.5 rounded-md text-sm cursor-pointer',
          'hover:bg-secondary-100 motion-safe:transition-colors',
          'focus:outline-none focus-visible:ring-2 focus-visible:ring-primary-500',
          isSelected && 'bg-primary-50 text-primary-700 font-medium',
          isDropTarget && 'ring-2 ring-primary-400 bg-primary-50',
        )}
        style={{ paddingLeft: `${level * 12 + 8}px` }}
        onClick={() => onSelect(folder.id)}
        onKeyDown={(e) => {
          if (e.key === 'Enter' || e.key === ' ') {
            e.preventDefault();
            onSelect(folder.id);
          }
        }}
        tabIndex={0}
        role="button"
        aria-label={folder.name}
        draggable
        onDragStart={handleFolderDragStart}
        onDragOver={handleDragOver}
        onDragLeave={handleDragLeave}
        onDrop={handleDrop}
      >
        {hasChildren && (
          <button
            type="button"
            onClick={(e) => {
              e.stopPropagation();
              setExpanded((prev) => !prev);
            }}
            className="flex-shrink-0 w-4 h-4 flex items-center justify-center text-secondary-400 hover:text-secondary-600"
            aria-label={expanded ? t('dms.folders') : t('dms.folders')}
          >
            <svg className="w-3 h-3 transition-transform" fill="none" viewBox="0 0 24 24" stroke="currentColor" aria-hidden="true">
              <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d={expanded ? 'M19 9l-7 7-7-7' : 'M9 5l7 7-7 7'} />
            </svg>
          </button>
        )}
        {!hasChildren && <span className="w-4 flex-shrink-0" aria-hidden="true" />}
        <svg className={clsx('w-4 h-4 flex-shrink-0', isDropTarget ? 'text-primary-500' : 'text-warning-500')} fill="none" viewBox="0 0 24 24" stroke="currentColor" aria-hidden="true">
          <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M3 7v10a2 2 0 002 2h14a2 2 0 002-2V9a2 2 0 00-2-2h-6l-2-2H5a2 2 0 00-2 2z" />
        </svg>
        <span className="truncate">{folder.name}</span>
        {typeof folder.file_count === 'number' && folder.file_count > 0 && (
          <span className="ml-auto text-xs text-secondary-400">{folder.file_count}</span>
        )}
      </div>
      {hasChildren && expanded && (
        <ul role="group" className="space-y-0">
          {folder.children!.map((child) => (
            <SourceTreeFolderItem
              key={child.id}
              folder={child}
              level={level + 1}
              selectedFolderId={selectedFolderId}
              onSelect={onSelect}
              onDropFiles={onDropFiles}
              onDropFolder={onDropFolder}
            />
          ))}
        </ul>
      )}
    </li>
  );
}

interface SourceSectionProps {
  title: string;
  icon: React.ReactNode;
  selected: boolean;
  onClick: () => void;
  children?: React.ReactNode;
  defaultExpanded?: boolean;
}

function SourceSection({ title, icon, selected, onClick, children, defaultExpanded = true }: SourceSectionProps) {
  const [expanded, setExpanded] = useState(defaultExpanded);

  return (
    <div className="mb-1">
      <div
        className={clsx(
          'flex items-center gap-1 px-2 py-1.5 rounded-md text-sm font-semibold cursor-pointer',
          'hover:bg-secondary-100 motion-safe:transition-colors',
          'focus:outline-none focus-visible:ring-2 focus-visible:ring-primary-500',
          selected && 'bg-primary-50 text-primary-700',
        )}
        onClick={() => {
          onClick();
          setExpanded(true);
        }}
        onKeyDown={(e) => {
          if (e.key === 'Enter' || e.key === ' ') {
            e.preventDefault();
            onClick();
            setExpanded(true);
          }
        }}
        tabIndex={0}
        role="button"
        aria-label={title}
      >
        <button
          type="button"
          onClick={(e) => {
            e.stopPropagation();
            setExpanded((prev) => !prev);
          }}
          className="flex-shrink-0 w-4 h-4 flex items-center justify-center text-secondary-400 hover:text-secondary-600"
          aria-label={expanded ? 'Collapse' : 'Expand'}
        >
          <svg className="w-3 h-3 transition-transform" fill="none" viewBox="0 0 24 24" stroke="currentColor" aria-hidden="true">
            <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d={expanded ? 'M19 9l-7 7-7-7' : 'M9 5l7 7-7 7'} />
          </svg>
        </button>
        {icon}
        <span className="truncate">{title}</span>
      </div>
      {expanded && children && (
        <ul role="group" className="space-y-0 mt-0.5">
          {children}
        </ul>
      )}
    </div>
  );
}

export interface SourceTreeProps {
  folders: DmsFolder[];
  sharedFiles: DmsFile[];
  selectedFolderId: string | null;
  selectedSource: string | null;
  onSelectFolder: (folderId: string | null) => void;
  onSelectSource: (source: string) => void;
  loading?: boolean;
  onDropFiles: (fileIds: string[], targetFolderId: string | null) => void;
  onDropFolder: (sourceFolderId: string, targetFolderId: string | null) => void;
}

export function SourceTree({
  folders,
  sharedFiles,
  selectedFolderId,
  selectedSource,
  onSelectFolder,
  onSelectSource,
  loading = false,
  onDropFiles,
  onDropFolder,
}: SourceTreeProps) {
  const { t } = useTranslation();
  const [isRootDropTarget, setIsRootDropTarget] = useState(false);

  if (loading) {
    return (
      <div className="space-y-2 p-2" data-testid="source-tree-loading">
        {[1, 2, 3].map((i) => (
          <div key={i} className="h-8 bg-secondary-100 rounded animate-pulse" />
        ))}
      </div>
    );
  }

  const localSelected = selectedSource === 'local' || (selectedSource === null && selectedFolderId !== null);
  const sharedSelected = selectedSource === 'shared';
  const externalSelected = selectedSource === 'external';

  function handleRootDragOver(e: React.DragEvent) {
    e.preventDefault();
    e.dataTransfer.dropEffect = 'move';
    if (!isRootDropTarget) setIsRootDropTarget(true);
  }

  function handleRootDragLeave(e: React.DragEvent) {
    e.stopPropagation();
    setIsRootDropTarget(false);
  }

  function handleRootDrop(e: React.DragEvent) {
    e.preventDefault();
    setIsRootDropTarget(false);
    try {
      const data = JSON.parse(e.dataTransfer.getData('application/json'));
      if (data.type === 'files' && data.ids) {
        onDropFiles(data.ids, null);
      } else if (data.type === 'folder' && data.id) {
        onDropFolder(data.id, null);
      }
    } catch {
      // ignore invalid drop data
    }
  }

  return (
    <nav aria-label={t('dms.sources')} data-testid="source-tree" className="p-2">
      {/* All Files entry — also a drop target (move to root) */}
      <div
        className={clsx(
          'flex items-center gap-2 px-2 py-1.5 rounded-md text-sm cursor-pointer mb-1',
          'hover:bg-secondary-100 motion-safe:transition-colors',
          'focus:outline-none focus-visible:ring-2 focus-visible:ring-primary-500',
          selectedSource === null && selectedFolderId === null && 'bg-primary-50 text-primary-700 font-medium',
          isRootDropTarget && 'ring-2 ring-primary-400 bg-primary-50',
        )}
        onClick={() => {
          onSelectFolder(null);
          onSelectSource('local');
        }}
        onKeyDown={(e) => {
          if (e.key === 'Enter' || e.key === ' ') {
            e.preventDefault();
            onSelectFolder(null);
            onSelectSource('local');
          }
        }}
        onDragOver={handleRootDragOver}
        onDragLeave={handleRootDragLeave}
        onDrop={handleRootDrop}
        tabIndex={0}
        role="button"
        aria-label={t('dms.allFiles')}
      >
        <svg className="w-4 h-4 text-secondary-400" fill="none" viewBox="0 0 24 24" stroke="currentColor" aria-hidden="true">
          <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M4 6h16M4 12h16M4 18h16" />
        </svg>
        <span>{t('dms.allFiles')}</span>
      </div>

      {/* Meine Dateien section */}
      <SourceSection
        title={t('dms.myFiles')}
        selected={localSelected}
        onClick={() => {
          onSelectSource('local');
          if (!selectedFolderId) {
            onSelectFolder(null);
          }
        }}
        icon={
          <svg className="w-4 h-4 text-primary-500 flex-shrink-0" fill="none" viewBox="0 0 24 24" stroke="currentColor" aria-hidden="true">
            <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M3 7v10a2 2 0 002 2h14a2 2 0 002-2V9a2 2 0 00-2-2h-6l-2-2H5a2 2 0 00-2 2z" />
          </svg>
        }
      >
        {folders.length === 0 ? (
          <li className="px-2 py-1 text-xs text-secondary-400 italic">{t('dms.noFiles')}</li>
        ) : (
          folders.map((folder) => (
            <SourceTreeFolderItem
              key={folder.id}
              folder={folder}
              level={0}
              selectedFolderId={selectedFolderId}
              onSelect={onSelectFolder}
              onDropFiles={onDropFiles}
              onDropFolder={onDropFolder}
            />
          ))
        )}
      </SourceSection>

      {/* Geteilte Ordner section */}
      <SourceSection
        title={t('dms.sharedFolders')}
        selected={sharedSelected}
        onClick={() => {
          onSelectSource('shared');
          onSelectFolder(null);
        }}
        icon={
          <svg className="w-4 h-4 text-accent-500 flex-shrink-0" fill="none" viewBox="0 0 24 24" stroke="currentColor" aria-hidden="true">
            <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="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" />
          </svg>
        }
      >
        {sharedFiles.length === 0 ? (
          <li className="px-2 py-1 text-xs text-secondary-400 italic">{t('dms.noFiles')}</li>
        ) : (
          sharedFiles.map((file) => (
            <li key={file.id} role="treeitem" aria-selected={false}>
              <div
                className={clsx(
                  'flex items-center gap-1 px-2 py-1.5 rounded-md text-sm cursor-pointer',
                  'hover:bg-secondary-100 motion-safe:transition-colors',
                )}
                style={{ paddingLeft: '20px' }}
                onClick={() => onSelectSource('shared')}
                tabIndex={0}
                role="button"
                aria-label={file.name}
              >
                <svg className="w-4 h-4 text-secondary-400 flex-shrink-0" fill="none" viewBox="0 0 24 24" stroke="currentColor" aria-hidden="true">
                  <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M7 21h10a2 2 0 002-2V9.414a1 1 0 00-.293-.707l-5.414-5.414A1 1 0 0012.586 3H7a2 2 0 00-2 2v14a2 2 0 002 2z" />
                </svg>
                <span className="truncate">{file.name}</span>
              </div>
            </li>
          ))
        )}
      </SourceSection>

      {/* Externe Speicher section */}
      <SourceSection
        title={t('dms.externalStorage')}
        selected={externalSelected}
        onClick={() => {
          onSelectSource('external');
          onSelectFolder(null);
        }}
        icon={
          <svg className="w-4 h-4 text-secondary-400 flex-shrink-0" fill="none" viewBox="0 0 24 24" stroke="currentColor" aria-hidden="true">
            <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M5 12H3l9-9 9 9h-2M5 12v7a2 2 0 002 2h10a2 2 0 002-2v-7M9 21v-6h6v6" />
          </svg>
        }
        defaultExpanded={false}
      >
        <li className="px-2 py-1 text-xs text-secondary-400 italic" style={{ paddingLeft: '20px' }}>
          {t('dms.externalStorageHint')}
        </li>
      </SourceSection>
    </nav>
  );
}
