import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import {
  ChevronIcon,
  TrashIcon,
  EditIcon,
  FolderIcon,
  ChevronsLeftIcon,
  LogoutIcon,
  ChevronDownIcon,
} from '../ui/icons';

import { getTagColorStyle } from '../utils/colors';

const FolderNode = ({
  node,
  depth,
  isSelected,
  onToggle,
  onSelect,
  onDrop,
  onDragOver,
  onDragLeave,
  onDelete,
  onRename,
  renderChildren,
  onFolderDragStart,
  onFolderDragEnd,
  draggingFolderId,
}) => {
  const isRoot = node.id === 'root';
  const hasChildren = Boolean(node.hasChildren);
  const canToggle = hasChildren || !node.loaded;
  const showChevron = canToggle;
  const icon = showChevron ? <ChevronIcon className="toggle-icon" /> : null;
  const canDrag = !isRoot;
  const isDragging = draggingFolderId === node.id;
  const isExpanded = Boolean(node.expanded);
  const rowClasses = ['folder-row'];
  if (isSelected) {
    rowClasses.push('active');
  }

  const handleToggleClick = (event) => {
    event.stopPropagation();
    if (canToggle) {
      onToggle(node.id);
    }
  };

  return (
    <li className={`folder-node${isDragging ? ' is-dragging' : ''}`}>
      <div
        className={rowClasses.join(' ')}
        draggable={canDrag}
        onClick={() => onSelect(node.id)}
        onDragOver={(event) => onDragOver(event, node.id)}
        onDragLeave={onDragLeave}
        onDrop={(event) => onDrop(event, node.id)}
        onDragStart={(event) => {
          if (!canDrag || !onFolderDragStart) return;
          onFolderDragStart(event, node.id);
        }}
        onDragEnd={(event) => {
          if (onFolderDragEnd) {
            onFolderDragEnd(event);
          }
        }}
      >
        <span
          className={`toggle${showChevron ? '' : ' invisible'}${isExpanded ? ' expanded' : ''}`}
          onClick={handleToggleClick}
        >
          {icon}
        </span>
        <span className="name">
          <FolderIcon className="folder-icon-image" size={16} />
          {node.name}
        </span>
        {node.id !== 'root' && (
          <div className="folder-row__actions">
            <button
              type="button"
              className="icon-button ghost"
              onClick={(event) => {
                event.stopPropagation();
                if (!onRename) return;
                const nextName = window.prompt('Rename folder', node.name || '');
                if (!nextName) {
                  return;
                }
                const trimmed = nextName.trim();
                if (!trimmed || trimmed === node.name) {
                  return;
                }
                onRename(node.id, trimmed);
              }}
              title="Rename folder"
              aria-label={`Rename folder ${node.name}`}
            >
              <EditIcon className="icon-edit" size={18} />
            </button>
            <button
              type="button"
              className="icon-button ghost"
              onClick={(event) => {
                event.stopPropagation();
                onDelete(node.id);
              }}
              title="Delete folder"
              aria-label={`Delete folder ${node.name}`}
            >
              <TrashIcon className="icon-trash" size={18} />
            </button>
          </div>
        )}
      </div>
      {isExpanded && node.children.length > 0 && (
        <ul className={`folder-children${depth === 0 ? ' folder-children--level1' : ''}`}>
          {renderChildren(node.children, depth + 1)}
        </ul>
      )}
    </li>
  );
};

const Sidebar = ({
  folderNodes,
  onToggle,
  onSelect,
  onDrop,
  onDragOver,
  onDragLeave,
  onDeleteFolder,
  onRenameFolder,
  selectedFolder,
  onFolderDragStart,
  onFolderDragEnd,
  draggedFolderId,
  tags = [],
  activeTagIds = [],
  onToggleTagFilter,
  correspondents = [],
  activeCorrespondentIds = [],
  onToggleCorrespondentFilter,
  onManageTags,
  onManageCorrespondents,
  searchQuery = '',
  onSearchChange,
  onSearchSubmit,
  onSearchClear,
  isFilterActive,
  appStatus,
  loading,
  previewActive,
  onLogout,
  status,
  onCollapse,
  tenantSlug,
  tenants = [],
  activeTenantId = null,
  onSelectTenant,
}) => {
  const sortedCorrespondents = useMemo(
    () =>
      [...correspondents].sort((a, b) =>
        (a?.name || '').localeCompare(b?.name || '', undefined, { sensitivity: 'base' }),
      ),
    [correspondents],
  );
  const activeCorrespondentSet = useMemo(
    () => new Set(activeCorrespondentIds || []),
    [activeCorrespondentIds],
  );
  const handleToggleTag = onToggleTagFilter || (() => {});
  const activeTagSet = new Set(activeTagIds);
  const handleManageTags = onManageTags || (() => {});
  const handleManageCorrespondents = onManageCorrespondents || (() => {});
  const handleSearchInputChange = useCallback(
    (event) => {
      onSearchChange?.(event.target.value);
    },
    [onSearchChange],
  );
  const handleSearchFormSubmit = useCallback(
    (event) => {
      event.preventDefault();
      onSearchSubmit?.();
    },
    [onSearchSubmit],
  );
  const handleSearchClear = useCallback(() => {
    onSearchClear?.();
  }, [onSearchClear]);
  const tenantButtonRef = useRef(null);
  const tenantMenuRef = useRef(null);
  const [tenantMenuOpen, setTenantMenuOpen] = useState(false);

  const toggleTenantMenu = useCallback(() => {
    const next = !tenantMenuOpen;
    setTenantMenuOpen(next);
    if (next && tenants.length === 0 && onSelectTenant) {
      onSelectTenant(null, { refreshOnly: true });
    }
  }, [tenantMenuOpen, tenants.length, onSelectTenant]);

  useEffect(() => {
    if (!tenantMenuOpen) {
      return undefined;
    }
    const handlePointer = (event) => {
      const menuNode = tenantMenuRef.current;
      const buttonNode = tenantButtonRef.current;
          if (!menuNode) return;
          if (menuNode.contains(event.target)) return;
          if (buttonNode && buttonNode.contains(event.target)) return;
          setTenantMenuOpen(false);
    };
    const handleKeyDown = (event) => {
      if (event.key === 'Escape') {
        setTenantMenuOpen(false);
      }
    };
    document.addEventListener('mousedown', handlePointer);
    document.addEventListener('touchstart', handlePointer);
    document.addEventListener('keydown', handleKeyDown);
    return () => {
      document.removeEventListener('mousedown', handlePointer);
      document.removeEventListener('touchstart', handlePointer);
      document.removeEventListener('keydown', handleKeyDown);
    };
  }, [tenantMenuOpen]);

  const handleTenantSelect = useCallback(
    (tenant) => {
      const targetId = tenant?.tenant_id || tenant?.tenantId || tenant?.id || null;
      if (!targetId) {
        return;
      }
      setTenantMenuOpen(false);
      onSelectTenant?.(tenant);
    },
    [onSelectTenant],
  );

  const handleLogoutFromMenu = useCallback(() => {
    setTenantMenuOpen(false);
    onLogout?.();
  }, [onLogout]);

  const renderNodes = useCallback(
    (ids, depth) =>
      ids.map((id) => {
        const node = folderNodes.get(id);
        if (!node) return null;
        return (
          <FolderNode
            key={id}
            node={node}
            depth={depth}
            isSelected={selectedFolder === id}
            onToggle={() => onToggle(id)}
            onSelect={onSelect}
            onDrop={onDrop}
            onDragOver={onDragOver}
            onDragLeave={onDragLeave}
            onDelete={onDeleteFolder}
            onRename={onRenameFolder}
            renderChildren={renderNodes}
            onFolderDragStart={onFolderDragStart}
            onFolderDragEnd={onFolderDragEnd}
            draggingFolderId={draggedFolderId}
          />
        );
      }),
    [
      folderNodes,
      selectedFolder,
      onToggle,
      onSelect,
      onDrop,
      onDragOver,
      onDragLeave,
      onDeleteFolder,
      onRenameFolder,
      onFolderDragStart,
      onFolderDragEnd,
      draggedFolderId,
    ],
  );

  const rootNode = folderNodes.get('root');
  return (
    <aside className="sidebar">
      <div className="panel-header sidebar__header">
        <div className="panel-actions">
          <button
            type="button"
            className={`sidebar__title-button${tenantMenuOpen ? ' is-open' : ''}`}
            onClick={toggleTenantMenu}
            aria-haspopup="true"
            aria-expanded={tenantMenuOpen}
            ref={tenantButtonRef}
          >
            <span className="sidebar__title">
              Papercrate
              {tenantSlug ? <span className="sidebar__tenant"> / {tenantSlug}</span> : null}
            </span>
            <ChevronDownIcon
              className={`sidebar__title-chevron${tenantMenuOpen ? ' is-open' : ''}`}
              size={16}
            />
          </button>
          {tenantMenuOpen ? (
            <div className="menu" ref={tenantMenuRef} role="menu">
              <div className="menu__list">
                {tenants.length === 0 ? (
                  <span className="menu__empty">No tenants available.</span>
                ) : (
                  tenants.map((tenant) => {
                    const tenantId = tenant?.tenant_id || tenant?.tenantId || tenant?.id || null;
                    const isActive = tenantId === activeTenantId;
                    return (
                      <button
                        key={tenantId || tenant?.slug || tenant?.name}
                        type="button"
                        className={`menu__item${isActive ? ' active' : ''}`}
                        onClick={() => handleTenantSelect(tenant)}
                        role="menuitem"
                      >
                        <span className="menu__label">
                        {tenant?.slug || tenant?.name || tenantId || 'Tenant'}
                        </span>
                        {isActive ? <span className="menu__active-indicator">Active</span> : null}
                      </button>
                    );
                  })
                )}
              </div>
              <div className="menu__footer">
                <button
                  type="button"
                  className="menu__logout"
                  onClick={handleLogoutFromMenu}
                >
                  <LogoutIcon size={16} />
                  Log out
                </button>
              </div>
            </div>
          ) : null}
          <div className="spacer" />
          {onCollapse ? (
            <button
              type="button"
              className="icon-button ghost"
              onClick={onCollapse}
              aria-label="Collapse sidebar"
              title="Collapse sidebar"
            >
              <ChevronsLeftIcon />
            </button>
          ) : null}
        </div>
      </div>
      <div className="panel-body sidebar__body">
        {status && (
          <div className="sidebar__status">
            <div className={`status-banner ${status.variant}`}>{status.message}</div>
          </div>
        )}
        {onSearchChange && (
          <form className="sidebar__search" onSubmit={handleSearchFormSubmit}>
            <input
              type="search"
              value={searchQuery}
              onChange={handleSearchInputChange}
              placeholder="Search documents"
              aria-label="Search documents"
            />
            {isFilterActive && (
              <button type="button" onClick={handleSearchClear}>
                Clear
              </button>
            )}
          </form>
        )}
        <div className="sidebar-section sidebar-section--folders">
          <div className="sidebar-section__header">
            <h3>Folders</h3>
          </div>
          <ul className="folder-tree">
            {rootNode && renderNodes([rootNode.id], 0)}
          </ul>
        </div>
        <div className="sidebar-section">
          <div className="sidebar-section__header">
            <button
              type="button"
              className="sidebar-section__title"
              onClick={handleManageTags}
            >
              <h3>Tags</h3>
              <span className="meta">{tags.length}</span>
            </button>
          </div>
          <div
            className={`sidebar-tag-cloud${
              activeTagSet.size ? ' sidebar-tag-cloud--has-active' : ''
            }`}
            role="list"
          >
            {tags.map((tag) => {
              const isActive = activeTagSet.has(tag.id);
              const style = getTagColorStyle(tag.color);
              const className = `sidebar-tag-pill${isActive ? ' active' : ''}`;
              return (
                <button
                  key={tag.id}
                  type="button"
                  role="listitem"
                  className={className}
                  style={style || undefined}
                  onClick={() => handleToggleTag(tag.id)}
                  aria-pressed={isActive}
                  draggable
                  onDragStart={(event) => {
                    try {
                      const payload = JSON.stringify({
                        id: tag.id,
                        label: tag.label,
                        color: tag.color || null,
                      });
                      event.dataTransfer.effectAllowed = 'copy';
                      event.dataTransfer.setData('application/x-papercrate-tag', payload);
                      event.dataTransfer.setData('text/papercrate-tag', payload);
                    } catch (
                      // eslint-disable-next-line no-empty
                      error
                    ) {}
                  }}
                >
                  {tag.label}
                </button>
              );
            })}
          </div>
        </div>
        <div className="sidebar-section">
          <div className="sidebar-section__header">
            <button
              type="button"
              className="sidebar-section__title"
              onClick={handleManageCorrespondents}
            >
              <h3>Correspondents</h3>
              <span className="meta">{correspondents.length}</span>
            </button>
          </div>
          <ul className="sidebar-correspondent-list">
            {sortedCorrespondents.map((correspondent) => {
              const isActive = activeCorrespondentSet.has(correspondent.id);
              const className = `sidebar-correspondent-item${isActive ? ' active' : ''}`;
              const label = correspondent.name || 'Unnamed';
              const handleSelect = () => {
                const nextId = isActive ? null : correspondent.id;
                onToggleCorrespondentFilter?.(nextId);
              };
              return (
                <li key={correspondent.id}>
                  <span
                    className={className}
                    role="button"
                    onClick={handleSelect}
                    onKeyDown={(event) => {
                      if (event.key === 'Enter' || event.key === ' ') {
                        event.preventDefault();
                        handleSelect();
                      }
                    }}
                  >
                    {label}
                  </span>
                </li>
              );
            })}
          </ul>
        </div>
      </div>
    </aside>
  );
};

export default Sidebar;
export { FolderNode };
