/**
 * Dashboard Page - 3-column layout with project folder tree, project cards, and info panel
 */
import { useState, useEffect, useCallback, useMemo } from 'react';
import { useAuth } from '../contexts/AuthContext';
import { NotificationPanel } from '../components/NotificationPanel';
import { ShareDialog } from '../components/ShareDialog';
import TreeView from '../components/TreeView';
import type { TreeNode } from '../types/ui.types';
import {
  getProjects, deleteProject,
  getProjectFolders, createProjectFolder, renameProjectFolder, deleteProjectFolder,
  moveProjectToFolder, getProjectShares,
  type Project, type ProjectFolder, type ProjectShare,
} from '../services/api';

const API_BASE = import.meta.env.VITE_API_BASE || '';
const ROOT_FOLDER_ID = '__root__';

interface DashboardProps {
  onOpenProject: (projectId: string) => void;
}

export function Dashboard({ onOpenProject }: DashboardProps) {
  const { user, logout, token } = useAuth();
  const [projects, setProjects] = useState<Project[]>([]);
  const [allProjects, setAllProjects] = useState<Project[]>([]);
  const [folders, setFolders] = useState<ProjectFolder[]>([]);
  const [loading, setLoading] = useState(true);
  const [showCreate, setShowCreate] = useState(false);
  const [newName, setNewName] = useState('');
  const [newDesc, setNewDesc] = useState('');
  const [shareProjectId, setShareProjectId] = useState<string | null>(null);
  const [selectedFolderId, setSelectedFolderId] = useState<string | null>(ROOT_FOLDER_ID);
  const [selectedProjectId, setSelectedProjectId] = useState<string | null>(null);
  const [shares, setShares] = useState<ProjectShare[]>([]);
  const [sharesLoading, setSharesLoading] = useState(false);
  const [draggedProjectId, setDraggedProjectId] = useState<string | null>(null);
  const [contextMenu, setContextMenu] = useState<{ x: number; y: number; folderId: string | null } | null>(null);
  const [renamingFolderId, setRenamingFolderId] = useState<string | null>(null);
  const [renameValue, setRenameValue] = useState('');
  const [showCreateFolder, setShowCreateFolder] = useState(false);
  const [newFolderName, setNewFolderName] = useState('');
  const [newFolderParent, setNewFolderParent] = useState<string | null>(null);

  const fetchAll = useCallback(async () => {
    if (!token) return;
    setLoading(true);
    try {
      const [projs, fldrs] = await Promise.all([
        getProjects(token),
        getProjectFolders(token),
      ]);
      setAllProjects(projs);
      setFolders(fldrs);
    } catch {
      // ignore
    } finally {
      setLoading(false);
    }
  }, [token]);

  useEffect(() => {
    fetchAll();
  }, [fetchAll]);

  useEffect(() => {
    if (selectedFolderId === ROOT_FOLDER_ID) {
      setProjects(allProjects);
    } else if (selectedFolderId === null) {
      setProjects(allProjects.filter(p => p.folder_id === null));
    } else {
      setProjects(allProjects.filter(p => p.folder_id === selectedFolderId));
    }
  }, [allProjects, selectedFolderId]);

  useEffect(() => {
    if (!token || !selectedProjectId) {
      setShares([]);
      return;
    }
    setSharesLoading(true);
    getProjectShares(token, selectedProjectId)
      .then(s => setShares(s))
      .catch(() => setShares([]))
      .finally(() => setSharesLoading(false));
  }, [token, selectedProjectId]);

  const selectedProject = useMemo(
    () => allProjects.find(p => p.id === selectedProjectId) ?? null,
    [allProjects, selectedProjectId],
  );

  const treeNodes = useMemo((): TreeNode[] => {
    const rootProjectsCount = allProjects.filter(p => p.folder_id === null).length;
    const root: TreeNode = {
      id: ROOT_FOLDER_ID,
      name: 'Alle Projekte',
      count: allProjects.length,
      expanded: true,
      children: [
        { id: '__unfiled__', name: 'Ohne Ordner', count: rootProjectsCount },
      ],
    };
    const buildFolderNode = (folder: ProjectFolder): TreeNode => {
      const childFolders = folders.filter(f => f.parent_id === folder.id);
      const projCount = allProjects.filter(p => p.folder_id === folder.id).length;
      return {
        id: folder.id,
        name: folder.name,
        count: projCount,
        expanded: true,
        children: childFolders.map(buildFolderNode),
      };
    };
    const topFolders = folders.filter(f => f.parent_id === null);
    root.children!.push(...topFolders.map(buildFolderNode));
    return [root];
  }, [folders, allProjects]);

  const folderNameById = useMemo(() => {
    const map = new Map<string, string>();
    map.set(ROOT_FOLDER_ID, 'Alle Projekte');
    map.set('__unfiled__', 'Ohne Ordner');
    for (const f of folders) map.set(f.id, f.name);
    return map;
  }, [folders]);

  const handleCreate = async () => {
    if (!newName.trim() || !token) return;
    try {
      const folderId = selectedFolderId === ROOT_FOLDER_ID || selectedFolderId === '__unfiled__'
        ? null : selectedFolderId;
      const res = await fetch(`${API_BASE}/api/projects`, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${token}` },
        body: JSON.stringify({ name: newName, description: newDesc || null, folder_id: folderId }),
      });
      if (res.ok) {
        setNewName('');
        setNewDesc('');
        setShowCreate(false);
        fetchAll();
      }
    } catch {
      // ignore
    }
  };

  const handleDelete = async (id: string, e: React.MouseEvent) => {
    e.stopPropagation();
    if (!confirm('Projekt wirklich loeschen?')) return;
    if (!token) return;
    try {
      await deleteProject(token, id);
      if (selectedProjectId === id) setSelectedProjectId(null);
      fetchAll();
    } catch {
      // ignore
    }
  };

  const handleFolderSelect = (id: string) => {
    if (id === ROOT_FOLDER_ID) {
      setSelectedFolderId(ROOT_FOLDER_ID);
    } else if (id === '__unfiled__') {
      setSelectedFolderId(null);
    } else {
      setSelectedFolderId(id);
    }
  };

  const handleCreateFolder = async () => {
    if (!newFolderName.trim() || !token) return;
    const parentId = newFolderParent === ROOT_FOLDER_ID || newFolderParent === '__unfiled__'
      ? null : newFolderParent;
    try {
      await createProjectFolder(token, newFolderName, parentId);
      setNewFolderName('');
      setShowCreateFolder(false);
      setNewFolderParent(null);
      fetchAll();
    } catch {
      // ignore
    }
  };

  const handleRenameFolder = async (id: string) => {
    if (!renameValue.trim() || !token) return;
    try {
      await renameProjectFolder(token, id, renameValue);
      setRenamingFolderId(null);
      setRenameValue('');
      fetchAll();
    } catch {
      // ignore
    }
  };

  const handleDeleteFolder = async (id: string) => {
    if (!token) return;
    if (!confirm('Ordner loeschen? Projekte darin werden nach "Ohne Ordner" verschoben.')) return;
    try {
      await deleteProjectFolder(token, id);
      if (selectedFolderId === id) setSelectedFolderId(ROOT_FOLDER_ID);
      fetchAll();
    } catch {
      // ignore
    }
  };

  const handleProjectCardClick = (projectId: string) => {
    setSelectedProjectId(projectId);
  };

  const handleProjectDragStart = (e: React.DragEvent, projectId: string) => {
    setDraggedProjectId(projectId);
    e.dataTransfer.effectAllowed = 'move';
    e.dataTransfer.setData('text/plain', `project:${projectId}`);
  };

  const handleFolderDragOver = (e: React.DragEvent) => {
    if (!draggedProjectId) return;
    e.preventDefault();
    e.dataTransfer.dropEffect = 'move';
    (e.currentTarget as HTMLElement).classList.add('tree-drop-target');
  };

  const handleFolderDragLeave = (e: React.DragEvent) => {
    (e.currentTarget as HTMLElement).classList.remove('tree-drop-target');
  };

  const handleFolderDrop = async (e: React.DragEvent, folderId: string) => {
    e.preventDefault();
    e.stopPropagation();
    (e.currentTarget as HTMLElement).classList.remove('tree-drop-target');
    if (!draggedProjectId || !token) return;
    const targetFolderId = folderId === ROOT_FOLDER_ID || folderId === '__unfiled__' ? null : folderId;
    try {
      await moveProjectToFolder(token, draggedProjectId, targetFolderId);
      fetchAll();
    } catch {
      // ignore
    } finally {
      setDraggedProjectId(null);
    }
  };

  const handleContextMenu = (e: React.MouseEvent, folderId: string | null) => {
    e.preventDefault();
    e.stopPropagation();
    setContextMenu({ x: e.clientX, y: e.clientY, folderId });
  };

  const handleContextAction = (action: string, folderId: string | null) => {
    setContextMenu(null);
    if (action === 'new') {
      setNewFolderParent(folderId);
      setShowCreateFolder(true);
    } else if (action === 'rename' && folderId) {
      const folder = folders.find(f => f.id === folderId);
      if (folder) {
        setRenamingFolderId(folderId);
        setRenameValue(folder.name);
      }
    } else if (action === 'delete' && folderId) {
      handleDeleteFolder(folderId);
    }
  };

  const formatDate = (dateStr: string) => {
    return new Date(dateStr).toLocaleDateString('de-DE', {
      year: 'numeric', month: 'long', day: 'numeric',
      hour: '2-digit', minute: '2-digit',
    });
  };

  const renderFolderActions = (node: TreeNode) => {
    if (node.id === ROOT_FOLDER_ID || node.id === '__unfiled__') return null;
    return (
      <span className="folder-action-buttons">
        <button
          className="folder-action-btn"
          title="Umbenennen"
          onClick={(e) => {
            e.stopPropagation();
            setRenamingFolderId(node.id);
            const folder = folders.find(f => f.id === node.id);
            if (folder) setRenameValue(folder.name);
          }}
        >✎</button>
        <button
          className="folder-action-btn delete"
          title="Loeschen"
          onClick={(e) => {
            e.stopPropagation();
            handleDeleteFolder(node.id);
          }}
        >✕</button>
      </span>
    );
  };

  return (
    <div className="dashboard-page">
      <header className="dashboard-header">
        <div className="dashboard-brand">
          <h1>Web CAD</h1>
          <span className="dashboard-user">{user?.name} ({user?.role})</span>
        </div>
        <div className="dashboard-header-actions">
          {token && <NotificationPanel token={token} />}
          <button className="dashboard-logout" onClick={logout}>Abmelden</button>
        </div>
      </header>

      <div className="dashboard-3col">
        <div className="dashboard-treeview" onContextMenu={(e) => handleContextMenu(e, null)}>
          <div className="treeview-header">
            <h3>Ordner</h3>
            <button
              className="treeview-add-folder-btn"
              title="Neuer Ordner"
              onClick={() => { setNewFolderParent(null); setShowCreateFolder(true); }}
            >+</button>
          </div>

          {showCreateFolder && (
            <div className="folder-create-form">
              <input
                type="text"
                placeholder="Ordnername"
                value={newFolderName}
                onChange={e => setNewFolderName(e.target.value)}
                onKeyDown={e => { if (e.key === 'Enter') handleCreateFolder(); if (e.key === 'Escape') setShowCreateFolder(false); }}
                autoFocus
              />
              <div className="folder-create-actions">
                <button onClick={handleCreateFolder}>OK</button>
                <button onClick={() => { setShowCreateFolder(false); setNewFolderName(''); }}>×</button>
              </div>
            </div>
          )}

          <TreeView
            nodes={treeNodes}
            selectedId={selectedFolderId ?? undefined}
            onSelect={handleFolderSelect}
            renderActions={renderFolderActions}
          />

          {renamingFolderId && (
            <div className="folder-rename-form">
              <input
                type="text"
                value={renameValue}
                onChange={e => setRenameValue(e.target.value)}
                onKeyDown={e => { if (e.key === 'Enter') handleRenameFolder(renamingFolderId); if (e.key === 'Escape') { setRenamingFolderId(null); setRenameValue(''); } }}
                onBlur={() => { if (renameValue.trim()) handleRenameFolder(renamingFolderId); else { setRenamingFolderId(null); setRenameValue(''); } }}
                autoFocus
              />
            </div>
          )}

          <div className="treeview-drop-overlay">
            {folders.map(folder => (
              <div
                key={folder.id}
                className="treeview-drop-zone"
                onDragOver={handleFolderDragOver}
                onDragLeave={handleFolderDragLeave}
                onDrop={(e) => handleFolderDrop(e, folder.id)}
              />
            ))}
          </div>
        </div>

        <div className="dashboard-content">
          <div className="dashboard-section-header">
            <h2>{folderNameById.get(selectedFolderId ?? ROOT_FOLDER_ID) ?? 'Projekte'}</h2>
            <button className="dashboard-create-btn" onClick={() => setShowCreate(!showCreate)}>
              + Neues Projekt
            </button>
          </div>

          {showCreate && (
            <div className="dashboard-create-form">
              <input
                type="text"
                placeholder="Projektname"
                value={newName}
                onChange={e => setNewName(e.target.value)}
                onKeyDown={e => { if (e.key === 'Enter') handleCreate(); }}
                autoFocus
              />
              <input
                type="text"
                placeholder="Beschreibung (optional)"
                value={newDesc}
                onChange={e => setNewDesc(e.target.value)}
                onKeyDown={e => { if (e.key === 'Enter') handleCreate(); }}
              />
              <button onClick={handleCreate}>Erstellen</button>
              <button onClick={() => setShowCreate(false)}>Abbrechen</button>
            </div>
          )}

          {loading ? (
            <p className="dashboard-loading">Lade Projekte...</p>
          ) : projects.length === 0 ? (
            <p className="dashboard-empty">Keine Projekte in dieser Ansicht. Erstellen Sie ein neues Projekt.</p>
          ) : (
            <div className="dashboard-project-grid">
              {projects.map(project => (
                <div
                  key={project.id}
                  className={`dashboard-project-card${selectedProjectId === project.id ? ' selected' : ''}`}
                  onClick={() => handleProjectCardClick(project.id)}
                  draggable
                  onDragStart={(e) => handleProjectDragStart(e, project.id)}
                  onDragEnd={() => setDraggedProjectId(null)}
                >
                  <h3>{project.name}</h3>
                  {project.description && <p>{project.description}</p>}
                  <div className="dashboard-project-meta">
                    <span>{new Date(project.created_at).toLocaleDateString('de-DE')}</span>
                    <div className="dashboard-project-actions">
                      <button
                        className="dashboard-open-btn"
                        onClick={(e) => { e.stopPropagation(); onOpenProject(project.id); }}
                      >
                        Oeffnen
                      </button>
                      <button
                        className="dashboard-share-btn"
                        onClick={(e) => { e.stopPropagation(); setShareProjectId(project.id); }}
                      >
                        Teilen
                      </button>
                      <button
                        className="dashboard-delete-btn"
                        onClick={(e) => handleDelete(project.id, e)}
                      >
                        Loeschen
                      </button>
                    </div>
                  </div>
                </div>
              ))}
            </div>
          )}
        </div>

        <div className="dashboard-info-panel">
          {selectedProject ? (
            <>
              <h3 className="info-panel-title">{selectedProject.name}</h3>
              {selectedProject.description && (
                <p className="info-panel-description">{selectedProject.description}</p>
              )}
              <div className="info-panel-section">
                <h4>Metadaten</h4>
                <dl className="info-panel-meta">
                  <dt>Erstellt</dt>
                  <dd>{formatDate(selectedProject.created_at)}</dd>
                  <dt>Aktualisiert</dt>
                  <dd>{formatDate(selectedProject.updated_at)}</dd>
                  <dt>Owner</dt>
                  <dd>{selectedProject.owner_id}</dd>
                  <dt>Ordner</dt>
                  <dd>{selectedProject.folder_id ? (folderNameById.get(selectedProject.folder_id) ?? 'Unbekannt') : 'Ohne Ordner'}</dd>
                </dl>
              </div>
              <div className="info-panel-section">
                <h4>Sichtbarkeit / Freigaben</h4>
                {sharesLoading ? (
                  <p className="info-panel-loading">Lade Freigaben...</p>
                ) : shares.length === 0 ? (
                  <p className="info-panel-empty">Keine Freigaben</p>
                ) : (
                  <ul className="info-panel-shares">
                    {shares.map(share => (
                      <li key={share.id} className="info-panel-share-item">
                        <span className="info-panel-share-email">{share.shared_with_email}</span>
                        <span className="info-panel-share-perm">{share.permission}</span>
                      </li>
                    ))}
                  </ul>
                )}
              </div>
              <button
                className="info-panel-open-btn"
                onClick={() => onOpenProject(selectedProject.id)}
              >
                Projekt oeffnen
              </button>
            </>
          ) : (
            <div className="info-panel-placeholder">
              <p>Waehlen Sie ein Projekt aus, um Details zu sehen.</p>
            </div>
          )}
        </div>
      </div>

      {contextMenu && (
        <>
          <div className="context-menu-overlay" onClick={() => setContextMenu(null)} />
          <div
            className="context-menu"
            style={{ left: contextMenu.x, top: contextMenu.y }}
          >
            <button
              className="context-menu-item"
              onClick={() => handleContextAction('new', contextMenu.folderId)}
            >Neuer Ordner</button>
            {contextMenu.folderId && contextMenu.folderId !== ROOT_FOLDER_ID && contextMenu.folderId !== '__unfiled__' && (
              <>
                <button
                  className="context-menu-item"
                  onClick={() => handleContextAction('rename', contextMenu.folderId)}
                >Umbenennen</button>
                <button
                  className="context-menu-item danger"
                  onClick={() => handleContextAction('delete', contextMenu.folderId)}
                >Loeschen</button>
              </>
            )}
          </div>
        </>
      )}

      {token && (
        <ShareDialog
          token={token}
          projectId={shareProjectId ?? ''}
          open={!!shareProjectId}
          onClose={() => setShareProjectId(null)}
        />
      )}
    </div>
  );
}
