/**
 * Mail folder tree sidebar component.
 * Shows accounts as top-level nodes with their folders nested underneath.
 * Folders come as a flat list with parent_id and are built into a tree.
 */

import React, { useState, useMemo } from 'react';
import clsx from 'clsx';
import { useTranslation } from 'react-i18next';
import type { MailAccount, MailFolder } from '@/api/mail';
import { Badge } from '@/components/ui/Badge';
import { EmptyState } from '@/components/ui/EmptyState';

/**
 * Map IMAP folder names to German display names.
 */
const FOLDER_NAME_MAP: Record<string, string> = {
  INBOX: 'Posteingang',
  'INBOX.Sent': 'Gesendet',
  'INBOX.Drafts': 'Entwürfe',
  'INBOX.Trash': 'Papierkorb',
  'INBOX.Archive': 'Archiv',
  'INBOX.spam': 'Spam',
  'INBOX.Spam': 'Spam',
  Sent: 'Gesendet',
  Drafts: 'Entwürfe',
  Spam: 'Spam',
  Junk: 'Spam',
  Trash: 'Papierkorb',
  'Sent Items': 'Gesendet',
  'Sent Mail': 'Gesendet',
  Draft: 'Entwürfe',
  Deleted: 'Papierkorb',
  'Deleted Items': 'Papierkorb',
  'Junk Email': 'Spam',
  'Junk E-mail': 'Spam',
  Archive: 'Archiv',
};

/**
 * Get the display name for a folder — uses the German name from the map
 * if the imap_name matches a known folder, otherwise uses the stored name.
 */
function getFolderDisplayName(folder: MailFolder): string {
  if (folder.imap_name && FOLDER_NAME_MAP[folder.imap_name]) {
    return FOLDER_NAME_MAP[folder.imap_name];
  }
  return folder.name;
}

export interface MailFolderTreeProps {
  accounts: MailAccount[];
  folders: MailFolder[];
  selectedFolderId: string | null;
  onSelect: (folderId: string) => void;
  loading: boolean;
}

/**
 * Build a hierarchical tree from a flat folder list for a given account.
 */
function buildFolderTree(folders: MailFolder[], accountId: string): MailFolder[] {
  const accountFolders = folders.filter((f) => f.account_id === accountId);
  const byId = new Map<string, MailFolder & { children: MailFolder[] }>();

  for (const f of accountFolders) {
    byId.set(f.id, { ...f, children: [] });
  }

  const roots: MailFolder[] = [];

  for (const f of accountFolders) {
    const node = byId.get(f.id)!;
    if (f.parent_id && byId.has(f.parent_id)) {
      byId.get(f.parent_id)!.children.push(node);
    } else {
      roots.push(node);
    }
  }

  return roots;
}

function ChevronIcon({ expanded }: { expanded: boolean }) {
  return (
    <svg
      className={clsx('w-3 h-3 transition-transform flex-shrink-0', expanded ? '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>
  );
}

function FolderIcon() {
  return (
    <svg className="w-4 h-4 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>
  );
}

function MailIcon() {
  return (
    <svg className="w-4 h-4 flex-shrink-0" fill="none" viewBox="0 0 24 24" stroke="currentColor" aria-hidden="true">
      <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M3 8l7-7 7 7M5 19h10a2 2 0 002-2V8l-5-5H5a2 2 0 00-2 2v12a2 2 0 002 2z" />
    </svg>
  );
}

function FolderNode({
  folder,
  selectedFolderId,
  onSelect,
  depth,
}: {
  folder: MailFolder;
  selectedFolderId: string | null;
  onSelect: (folderId: string) => void;
  depth: number;
}) {
  const [expanded, setExpanded] = useState(true);
  const isSelected = folder.id === selectedFolderId;
  const hasChildren = folder.children && folder.children.length > 0;

  return (
    <div role="treeitem" aria-selected={isSelected} aria-label={getFolderDisplayName(folder)}>
      <div className="flex items-center" style={{ paddingLeft: `${depth * 12}px` }}>
        {hasChildren ? (
          <button
            onClick={(e) => {
              e.stopPropagation();
              setExpanded(!expanded);
            }}
            className="flex-shrink-0 p-0.5 hover:bg-secondary-100 rounded"
            aria-label={expanded ? 'Collapse' : 'Expand'}
            data-testid={`folder-chevron-${folder.id}`}
          >
            <ChevronIcon expanded={expanded} />
          </button>
        ) : (
          <span className="w-4 flex-shrink-0" />
        )}
        <button
          onClick={() => onSelect(folder.id)}
          className={clsx(
            'flex-1 flex items-center gap-1.5 px-2 py-1 md:py-1 rounded-md text-sm min-h-touch',
            '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'
              : 'hover:bg-secondary-50 text-secondary-700',
          )}
          data-testid={`folder-${folder.id}`}
        >
          <FolderIcon />
          <span className="flex-1 truncate text-left">{getFolderDisplayName(folder)}</span>
          {folder.unread_count > 0 && (
            <Badge variant="primary" className="text-xs">{folder.unread_count}</Badge>
          )}
          {folder.total_count > 0 && folder.unread_count === 0 && (
            <span className="text-xs text-secondary-400">{folder.total_count}</span>
          )}
        </button>
      </div>
      {hasChildren && expanded && (
        <div role="group">
          {folder.children!.map((child) => (
            <FolderNode
              key={child.id}
              folder={child}
              selectedFolderId={selectedFolderId}
              onSelect={onSelect}
              depth={depth + 1}
            />
          ))}
        </div>
      )}
    </div>
  );
}

function AccountNode({
  account,
  folders,
  selectedFolderId,
  onSelect,
}: {
  account: MailAccount;
  folders: MailFolder[];
  selectedFolderId: string | null;
  onSelect: (folderId: string) => void;
}) {
  const [expanded, setExpanded] = useState(true);
  const accountFolders = useMemo(
    () => buildFolderTree(folders, account.id),
    [folders, account.id],
  );

  return (
    <div role="treeitem" aria-label={account.email}>
      <button
        onClick={() => setExpanded(!expanded)}
        className="w-full flex items-center gap-1 px-1 py-2 md:py-1.5 rounded-md text-sm font-semibold text-secondary-900 hover:bg-secondary-50 min-h-touch"
        data-testid={`account-${account.id}`}
      >
        <ChevronIcon expanded={expanded} />
        <span className="flex-1 truncate text-left">{account.display_name || account.email}</span>
      </button>
      {expanded && (
        <div role="group" className="ml-2">
          {accountFolders.map((folder) => (
            <FolderNode
              key={folder.id}
              folder={folder}
              selectedFolderId={selectedFolderId}
              onSelect={onSelect}
              depth={0}
            />
          ))}
        </div>
      )}
    </div>
  );
}

export function MailFolderTree({ accounts, folders, selectedFolderId, onSelect, loading }: MailFolderTreeProps) {
  const { t } = useTranslation();

  if (loading) {
    return (
      <div className="flex items-center justify-center py-8" data-testid="folder-tree-loading">
        <svg className="animate-spin h-5 w-5 text-secondary-400" fill="none" viewBox="0 0 24 24" aria-hidden="true">
          <circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4" />
          <path className="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z" />
        </svg>
        <span className="ml-2 text-sm text-secondary-500">{t('common.loading')}</span>
      </div>
    );
  }

  if (accounts.length === 0) {
    return (
      <EmptyState
        title={t('mail.noFolders')}
        description={t('mail.noFoldersDesc')}
        data-testid="folder-tree-empty"
      />
    );
  }

  return (
    <div className="space-y-1" role="tree" data-testid="folder-tree-list">
      {accounts.map((account) => (
        <AccountNode
          key={account.id}
          account={account}
          folders={folders}
          selectedFolderId={selectedFolderId}
          onSelect={onSelect}
        />
      ))}
    </div>
  );
}
