"use client";

import { useState, useEffect, useCallback, useRef } from "react";
import {
  getImapAccounts,
  createImapAccount,
  deleteImapAccount,
  testImapConnection,
  startImapImport,
  getImapProgress,
  triggerImapSync,
  updateImapInterval,
  updateImapAccount,
  type ImapAccount,
  type ImapFolder,
} from "@/lib/api";

export function useImapAccounts(user: unknown) {
  const [accounts, setAccounts] = useState<ImapAccount[]>([]);
  const [loading, setLoading] = useState(true);
  const [dialogOpen, setDialogOpen] = useState(false);
  const [deleteConfirm, setDeleteConfirm] = useState<number | null>(null);

  // Edit state
  const [editAccount, setEditAccount] = useState<ImapAccount | null>(null);
  const [editName, setEditName] = useState("");
  const [editHost, setEditHost] = useState("");
  const [editPort, setEditPort] = useState("993");
  const [editTls, setEditTls] = useState("ssl");
  const [editUsername, setEditUsername] = useState("");
  const [editPassword, setEditPassword] = useState("");
  const [editSaving, setEditSaving] = useState(false);
  const [editError, setEditError] = useState("");

  // Form state
  const [formName, setFormName] = useState("");
  const [formHost, setFormHost] = useState("");
  const [formPort, setFormPort] = useState("993");
  const [formTls, setFormTls] = useState("ssl");
  const [formUsername, setFormUsername] = useState("");
  const [formPassword, setFormPassword] = useState("");

  // Test state
  const [testing, setTesting] = useState(false);
  const [testError, setTestError] = useState("");
  const [testFolders, setTestFolders] = useState<ImapFolder[] | null>(null);
  const [excludedFolders, setExcludedFolders] = useState<Set<string>>(new Set());

  // Saving state
  const [saving, setSaving] = useState(false);

  // Import error state
  const [importError, setImportError] = useState<string>("");

  // Polling refs
  const pollingRefs = useRef<Map<number, ReturnType<typeof setInterval>>>(new Map());
  const pollErrorCount = useRef<Map<number, number>>(new Map());

  const loadAccounts = useCallback(async () => {
    try {
      const data = await getImapAccounts();
      setAccounts(data);
    } catch {
      // ignore
    } finally {
      setLoading(false);
    }
  }, []);

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

  // Start polling for running accounts (import or sync)
  useEffect(() => {
    for (const acc of accounts) {
      const isActive = acc.status === "running" || acc.sync_running;
      if (isActive && !pollingRefs.current.has(acc.id)) {
        pollErrorCount.current.set(acc.id, 0);
        const interval = setInterval(async () => {
          try {
            const updated = await getImapProgress(acc.id);
            pollErrorCount.current.set(acc.id, 0);
            setAccounts((prev) =>
              prev.map((a) => (a.id === updated.id ? updated : a))
            );
            if (updated.status !== "running" && !updated.sync_running) {
              clearInterval(pollingRefs.current.get(acc.id)!);
              pollingRefs.current.delete(acc.id);
              pollErrorCount.current.delete(acc.id);
            }
          } catch {
            // Only stop polling after 5 consecutive failures (tolerates brief network hiccups)
            const errors = (pollErrorCount.current.get(acc.id) ?? 0) + 1;
            pollErrorCount.current.set(acc.id, errors);
            if (errors >= 5) {
              clearInterval(pollingRefs.current.get(acc.id)!);
              pollingRefs.current.delete(acc.id);
              pollErrorCount.current.delete(acc.id);
            }
          }
        }, 2000);
        pollingRefs.current.set(acc.id, interval);
      }
    }
    // Cleanup intervals for accounts that are no longer active
    for (const [id, interval] of pollingRefs.current) {
      const acc = accounts.find((a) => a.id === id);
      if (!acc || (acc.status !== "running" && !acc.sync_running)) {
        clearInterval(interval);
        pollingRefs.current.delete(id);
      }
    }
  }, [accounts]);

  // Cleanup on unmount
  useEffect(() => {
    const refs = pollingRefs.current;
    return () => {
      for (const interval of refs.values()) {
        clearInterval(interval);
      }
    };
  }, []);

  const resetForm = useCallback(() => {
    setFormName("");
    setFormHost("");
    setFormPort("993");
    setFormTls("ssl");
    setFormUsername("");
    setFormPassword("");
    setTestFolders(null);
    setTestError("");
    setExcludedFolders(new Set());
  }, []);

  async function handleTest() {
    setTesting(true);
    setTestError("");
    setTestFolders(null);
    try {
      const result = await testImapConnection({
        host: formHost,
        port: parseInt(formPort, 10) || 993,
        tls: formTls,
        username: formUsername,
        password: formPassword,
      });
      if (result.ok && result.folders) {
        setTestFolders(result.folders);
        const excluded = new Set<string>();
        for (const f of result.folders) {
          if (f.excluded) excluded.add(f.name);
        }
        setExcludedFolders(excluded);
      } else {
        setTestError(result.error || "Verbindungstest fehlgeschlagen");
      }
    } catch (err) {
      setTestError(err instanceof Error ? err.message : "Verbindungstest fehlgeschlagen");
    } finally {
      setTesting(false);
    }
  }

  async function handleSave() {
    setSaving(true);
    try {
      await createImapAccount({
        name: formName,
        host: formHost,
        port: parseInt(formPort, 10) || 993,
        tls: formTls,
        username: formUsername,
        password: formPassword,
        excluded_folders: Array.from(excludedFolders),
      });
      setDialogOpen(false);
      resetForm();
      await loadAccounts();
    } catch (err) {
      setTestError(err instanceof Error ? err.message : "Speichern fehlgeschlagen");
    } finally {
      setSaving(false);
    }
  }

  async function handleStartImport(id: number) {
    setImportError("");
    try {
      const updated = await startImapImport(id);
      setAccounts((prev) => prev.map((a) => (a.id === updated.id ? updated : a)));
    } catch (err) {
      setImportError(err instanceof Error ? err.message : "Import konnte nicht gestartet werden.");
    }
  }

  async function handleDelete(id: number) {
    try {
      await deleteImapAccount(id);
      setAccounts((prev) => prev.filter((a) => a.id !== id));
    } catch (err) {
      alert("Fehler beim Löschen: " + (err instanceof Error ? err.message : String(err)));
    }
    setDeleteConfirm(null);
  }

  function openEdit(acc: ImapAccount) {
    setEditAccount(acc);
    setEditName(acc.name);
    setEditHost(acc.host);
    setEditPort(String(acc.port));
    setEditTls(acc.tls);
    setEditUsername(acc.username);
    setEditPassword("");
    setEditError("");
  }

  async function handleEditSave() {
    if (!editAccount) return;
    if (!editName || !editHost || !editUsername) {
      setEditError("Name, Host und Benutzername sind Pflichtfelder.");
      return;
    }
    setEditSaving(true);
    setEditError("");
    try {
      const updated = await updateImapAccount(editAccount.id, {
        name: editName,
        host: editHost,
        port: parseInt(editPort, 10),
        tls: editTls,
        username: editUsername,
        password: editPassword || undefined,
      });
      setAccounts((prev) => prev.map((a) => (a.id === updated.id ? updated : a)));
      setEditAccount(null);
    } catch (err) {
      setEditError(err instanceof Error ? err.message : String(err));
    } finally {
      setEditSaving(false);
    }
  }

  async function handleSyncNow(id: number) {
    try {
      const updated = await triggerImapSync(id);
      setAccounts((prev) => prev.map((a) => (a.id === updated.id ? updated : a)));
    } catch {
      // ignore — conflict means sync already running
    }
  }

  async function handleIntervalChange(id: number, value: string) {
    const intervalMin = parseInt(value, 10);
    try {
      const updated = await updateImapInterval(id, intervalMin);
      setAccounts((prev) => prev.map((a) => (a.id === updated.id ? updated : a)));
    } catch {
      // ignore
    }
  }

  function toggleExcluded(folderName: string) {
    setExcludedFolders((prev) => {
      const next = new Set(prev);
      if (next.has(folderName)) {
        next.delete(folderName);
      } else {
        next.add(folderName);
      }
      return next;
    });
  }

  return {
    accounts,
    loading,
    dialogOpen,
    setDialogOpen,
    deleteConfirm,
    setDeleteConfirm,
    // edit
    editAccount,
    setEditAccount,
    editName,
    setEditName,
    editHost,
    setEditHost,
    editPort,
    setEditPort,
    editTls,
    setEditTls,
    editUsername,
    setEditUsername,
    editPassword,
    setEditPassword,
    editSaving,
    editError,
    // form
    formName,
    setFormName,
    formHost,
    setFormHost,
    formPort,
    setFormPort,
    formTls,
    setFormTls,
    formUsername,
    setFormUsername,
    formPassword,
    setFormPassword,
    // test
    testing,
    testError,
    testFolders,
    excludedFolders,
    // saving
    saving,
    importError,
    // handlers
    resetForm,
    handleTest,
    handleSave,
    handleStartImport,
    handleDelete,
    openEdit,
    handleEditSave,
    handleSyncNow,
    handleIntervalChange,
    toggleExcluded,
  };
}
