/**
 * Mail page — folder tree + mail list + reading pane + compose.
 */

import React, { useState, useEffect, useCallback } from 'react';
import { useTranslation } from 'react-i18next';
import { Link } from 'react-router-dom';
import { Card } from '@/components/ui/Card';
import { Button } from '@/components/ui/Button';
import { useToast } from '@/components/ui/Toast';
import { EmptyState } from '@/components/ui/EmptyState';
import { MailFolderTree } from '@/components/mail/MailFolderTree';
import { MailList } from '@/components/mail/MailList';
import { MailDetail } from '@/components/mail/MailDetail';
import { ComposeModal, type ComposeMode } from '@/components/mail/ComposeModal';
import { SharedMailboxSelector } from '@/components/mail/SharedMailboxSelector';
import { MailSearchBar } from '@/components/mail/MailSearchBar';
import {
  fetchAccounts,
  fetchFolders,
  fetchMails,
  getMail,
  sendMail,
  replyMail,
  forwardMail,
  updateFlags,
  createEventFromMail,
  downloadAttachment,
  fetchSignatures,
  searchMails,
  type MailAccount,
  type MailFolder,
  type Mail,
  type MailSignature,
  type MailAttachment,
  type SendMailPayload,
  type ReplyPayload,
  type ForwardPayload,
  type CreateEventFromMailPayload,
} from '@/api/mail';

const PAGE_SIZE = 25;

export function MailPage() {
  const { t } = useTranslation();
  const toast = useToast();

  const [accounts, setAccounts] = useState<MailAccount[]>([]);
  const [selectedAccountId, setSelectedAccountId] = useState('');
  const [folders, setFolders] = useState<MailFolder[]>([]);
  const [selectedFolderId, setSelectedFolderId] = useState<string | null>(null);
  const [mails, setMails] = useState<Mail[]>([]);
  const [mailsTotal, setMailsTotal] = useState(0);
  const [mailsPage, setMailsPage] = useState(1);
  const [selectedMail, setSelectedMail] = useState<Mail | null>(null);
  const [loadingMail, setLoadingMail] = useState(false);
  const [loadingAccounts, setLoadingAccounts] = useState(true);
  const [loadingFolders, setLoadingFolders] = useState(false);
  const [loadingMails, setLoadingMails] = useState(false);
  const [error, setError] = useState<string | null>(null);
  const [signatures, setSignatures] = useState<MailSignature[]>([]);
  const [composeOpen, setComposeOpen] = useState(false);
  const [composeMode, setComposeMode] = useState<ComposeMode>('new');
  const [replyToMail, setReplyToMail] = useState<Mail | null>(null);
  const [forwardMailState, setForwardMailState] = useState<Mail | null>(null);
  const [downloadingAttachmentId, setDownloadingAttachmentId] = useState<string | null>(null);
  const [searchQuery, setSearchQuery] = useState('');

  // Load accounts
  const loadAccounts = useCallback(async () => {
    setLoadingAccounts(true);
    try {
      const accs = await fetchAccounts();
      setAccounts(accs);
      if (accs.length > 0 && !selectedAccountId) {
        setSelectedAccountId(accs[0].id);
      }
    } catch (err) {
      const msg = err instanceof Error ? err.message : String(err);
      setError(msg);
    }
    setLoadingAccounts(false);
  }, [selectedAccountId]);

  // Load signatures
  const loadSignatures = useCallback(async () => {
    try {
      const sigs = await fetchSignatures();
      setSignatures(sigs);
    } catch {
 // non-critical
    }
  }, []);

  useEffect(() => {
    loadAccounts();
    loadSignatures();
  }, [loadAccounts, loadSignatures]);

  // Load folders when account changes
  const loadFolders = useCallback(async () => {
    if (!selectedAccountId) return;
    setLoadingFolders(true);
    try {
      const folderList = await fetchFolders(selectedAccountId);
      setFolders(folderList);
      // Auto-select first folder
      if (folderList.length > 0 && !selectedFolderId) {
        setSelectedFolderId(folderList[0].id);
      }
    } catch (err) {
      const msg = err instanceof Error ? err.message : String(err);
      setError(msg);
    }
    setLoadingFolders(false);
  }, [selectedAccountId, selectedFolderId]);

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

  // Load mails when folder or page changes
  const loadMails = useCallback(async () => {
    if (!selectedFolderId) return;
    setLoadingMails(true);
    try {
      if (searchQuery.trim()) {
        const result = await searchMails(searchQuery);
        setMails(result.mails);
        setMailsTotal(result.total);
      } else {
        const result = await fetchMails(selectedFolderId, mailsPage);
        setMails(result.mails);
        setMailsTotal(result.total);
      }
    } catch (err) {
      const msg = err instanceof Error ? err.message : String(err);
      setError(msg);
      setMails([]);
    }
    setLoadingMails(false);
  }, [selectedFolderId, mailsPage, searchQuery]);

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

  // Handle folder selection
  const handleSelectFolder = useCallback((folderId: string) => {
    setSelectedFolderId(folderId);
    setMailsPage(1);
    setSearchQuery('');
    setSelectedMail(null);
  }, []);

  // Handle mail selection
  const handleSelectMail = useCallback(async (mail: Mail) => {
    setLoadingMail(true);
    try {
      const detail = await getMail(mail.id);
      setSelectedMail(detail);
      // Mark as seen if not seen
      if (!detail.is_seen) {
        await updateFlags(mail.id, { seen: true });
        setMails((prev) => prev.map((m) => (m.id === mail.id ? { ...m, is_seen: true } : m)));
      }
    } catch (err) {
      const msg = err instanceof Error ? err.message : String(err);
      toast.error(msg);
      setSelectedMail(mail);
    }
    setLoadingMail(false);
  }, [toast]);

  // Handle compose
  const handleCompose = useCallback(() => {
    setComposeMode('new');
    setReplyToMail(null);
    setForwardMailState(null);
    setComposeOpen(true);
  }, []);

  // Handle reply
  const handleReply = useCallback((mail: Mail) => {
    setComposeMode('reply');
    setReplyToMail(mail);
    setForwardMailState(null);
    setComposeOpen(true);
  }, []);

  // Handle forward
  const handleForward = useCallback((mail: Mail) => {
    setComposeMode('forward');
    setForwardMailState(mail);
    setReplyToMail(null);
    setComposeOpen(true);
  }, []);

  // Handle toggle flag
  const handleToggleFlag = useCallback(async (mail: Mail) => {
    try {
      await updateFlags(mail.id, { flagged: !mail.is_flagged });
      setSelectedMail((prev) => prev ? { ...prev, is_flagged: !mail.is_flagged } : prev);
      setMails((prev) => prev.map((m) => (m.id === mail.id ? { ...m, is_flagged: !mail.is_flagged } : m)));
    } catch (err) {
      toast.error(err instanceof Error ? err.message : String(err));
    }
  }, [toast]);

  // Handle create event from mail
  const handleCreateEvent = useCallback(async (mail: Mail) => {
    const title = mail.subject || t('mail.noSubject');
    const now = new Date();
    const start = now.toISOString();
    const end = new Date(now.getTime() + 60 * 60 * 1000).toISOString();
    const payload: CreateEventFromMailPayload = {
      title,
      start,
      end,
      description: mail.body_text.slice(0, 500),
    };
    try {
      await createEventFromMail(mail.id, payload);
      toast.success(t('mail.eventCreated'));
    } catch (err) {
      toast.error(err instanceof Error ? err.message : String(err));
    }
  }, [toast, t]);

  // Handle attachment download
  const handleDownloadAttachment = useCallback(async (mailId: string, attachment: MailAttachment) => {
    setDownloadingAttachmentId(attachment.id);
    try {
      const blob = await downloadAttachment(mailId, attachment.id);
      const url = window.URL.createObjectURL(blob);
      const a = window.document.createElement('a');
      a.href = url;
      a.download = attachment.filename;
      window.document.body.appendChild(a);
      a.click();
      window.document.body.removeChild(a);
      window.URL.revokeObjectURL(url);
    } catch (err) {
      toast.error(err instanceof Error ? err.message : String(err));
    } finally {
      setDownloadingAttachmentId(null);
    }
  }, [toast]);

  // Handle send (compose)
  const handleSend = useCallback(async (payload: SendMailPayload | ReplyPayload | ForwardPayload, mode: ComposeMode) => {
    try {
      if (mode === 'reply' && replyToMail) {
        await replyMail(replyToMail.id, payload as ReplyPayload);
      } else if (mode === 'forward' && forwardMailState) {
        await forwardMail(forwardMailState.id, payload as ForwardPayload);
      } else {
        await sendMail(payload as SendMailPayload);
      }
      toast.success(t('mail.sent'));
    } catch (err) {
      toast.error(err instanceof Error ? err.message : String(err));
      throw err;
    }
  }, [replyToMail, forwardMailState, toast, t]);

  // Handle search
  const handleSearch = useCallback((query: string) => {
    setSearchQuery(query);
    setMailsPage(1);
  }, []);

  // Handle account switch
  const handleAccountSwitch = useCallback((accountId: string) => {
    setSelectedAccountId(accountId);
    setSelectedFolderId(null);
    setSelectedMail(null);
    setMails([]);
    setMailsPage(1);
    setSearchQuery('');
  }, []);

  if (loadingAccounts) {
    return (
      <div className="flex items-center justify-center py-12" data-testid="mail-page-loading">
        <svg className="animate-spin h-6 w-6 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-secondary-500">{t('common.loading')}</span>
      </div>
    );
  }

  if (accounts.length === 0) {
    return (
      <div className="p-6 max-w-7xl mx-auto" data-testid="mail-page">
        <EmptyState
          title={t('mail.noAccounts')}
          description={t('mail.noAccountsDesc')}
          action={<Link to="/mail/settings" className="text-primary-600 hover:text-primary-700">{t('mail.configureAccount')}</Link>}
        />
      </div>
    );
  }

  return (
    <div className="flex flex-col h-full" data-testid="mail-page">
      {/* Top bar */}
      <div className="flex items-center gap-3 px-4 py-3 border-b border-secondary-200 bg-white">
        <SharedMailboxSelector
          accounts={accounts}
          selectedAccountId={selectedAccountId}
          onSelect={handleAccountSwitch}
        />
        <div className="flex-1 max-w-md">
          <MailSearchBar onSearch={handleSearch} />
        </div>
        <div className="flex items-center gap-2">
          <Button size="sm" onClick={handleCompose} data-testid="compose-btn">
            <svg className="w-4 h-4 mr-1" fill="none" viewBox="0 0 24 24" stroke="currentColor" aria-hidden="true">
              <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M12 4v16m8-8H4" />
            </svg>
            {t('mail.compose')}
          </Button>
          <Link to="/mail/settings" className="text-sm text-primary-600 hover:text-primary-700">
            {t('mail.settings')}
          </Link>
        </div>
      </div>

      {error && (
        <div className="mb-2 p-3 bg-danger-50 border border-danger-200 rounded-md" role="alert" data-testid="mail-error">
          <p className="text-sm text-danger-700">{error}</p>
        </div>
      )}

      {/* Three-pane layout */}
      <div className="flex flex-1 overflow-hidden">
        {/* Folder tree */}
        <div className="w-56 border-r border-secondary-200 overflow-y-auto bg-white" data-testid="mail-folder-pane">
          <div className="p-3">
            <h3 className="text-xs font-semibold text-secondary-500 uppercase mb-2">{t('mail.folders')}</h3>
            <MailFolderTree
              folders={folders}
              selectedFolderId={selectedFolderId}
              onSelect={handleSelectFolder}
              loading={loadingFolders}
            />
          </div>
        </div>

        {/* Mail list */}
        <div className="w-80 border-r border-secondary-200 overflow-y-auto bg-white" data-testid="mail-list-pane">
          <MailList
            mails={mails}
            selectedMailId={selectedMail?.id || null}
            onSelectMail={handleSelectMail}
            loading={loadingMails}
            currentPage={mailsPage}
            total={mailsTotal}
            pageSize={PAGE_SIZE}
            onPageChange={setMailsPage}
          />
        </div>

        {/* Reading pane */}
        <div className="flex-1 overflow-y-auto bg-white" data-testid="mail-detail-pane">
          <MailDetail
            mail={selectedMail}
            loading={loadingMail}
            onReply={handleReply}
            onForward={handleForward}
            onCreateEvent={handleCreateEvent}
            onToggleFlag={handleToggleFlag}
            onDownloadAttachment={handleDownloadAttachment}
            downloadingAttachmentId={downloadingAttachmentId}
          />
        </div>
      </div>

      <ComposeModal
        open={composeOpen}
        mode={composeMode}
        accountId={selectedAccountId}
        replyToMail={replyToMail}
        forwardMail={forwardMailState}
        signatures={signatures}
        onSend={handleSend}
        onClose={() => setComposeOpen(false)}
      />
    </div>
  );
}