import { useCallback, useEffect, useMemo, useState } from "react";
import { api, type ManualTaskInput, type ServerRecord, type TaskRecord } from "../api/client";
import FilterBar, { type Filters } from "../components/FilterBar";
import ServerGroup from "../components/ServerGroup";
import TaskForm from "../components/TaskForm";

export default function Dashboard() {
  const [servers, setServers] = useState<ServerRecord[]>([]);
  const [tasks, setTasks] = useState<TaskRecord[]>([]);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);
  const [filters, setFilters] = useState<Filters>({
    serverId: undefined,
    scheduleType: undefined,
    search: "",
    includeStale: false,
  });
  const [formOpen, setFormOpen] = useState(false);
  const [editingTask, setEditingTask] = useState<TaskRecord | null>(null);

  const loadServers = useCallback(() => {
    return api.servers
      .list()
      .then((res) => setServers(res.servers))
      .catch((err) => setError(String(err)));
  }, []);

  const loadTasks = useCallback(() => {
    return api.tasks
      .list(filters)
      .then((res) => {
        setTasks(res.tasks);
        setError(null);
      })
      .catch((err) => setError(String(err)));
  }, [filters]);

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

  useEffect(() => {
    setLoading(true);
    const handle = setTimeout(() => {
      loadTasks().finally(() => setLoading(false));
    }, 200);
    return () => clearTimeout(handle);
  }, [loadTasks]);

  const groups = useMemo(() => {
    const byServer = new Map<number, { serverId: number; serverName: string; tasks: TaskRecord[] }>();
    for (const task of tasks) {
      const entry = byServer.get(task.serverId) ?? {
        serverId: task.serverId,
        serverName: task.serverName,
        tasks: [],
      };
      entry.tasks.push(task);
      byServer.set(task.serverId, entry);
    }
    return [...byServer.values()];
  }, [tasks]);

  function openAddForm() {
    setEditingTask(null);
    setFormOpen(true);
  }

  function openEditForm(task: TaskRecord) {
    setEditingTask(task);
    setFormOpen(true);
  }

  function closeForm() {
    setFormOpen(false);
    setEditingTask(null);
  }

  async function handleFormSubmit(data: ManualTaskInput) {
    if (editingTask) {
      await api.tasks.update(editingTask.id, data);
    } else {
      await api.tasks.create(data);
    }
    closeForm();
    await loadTasks();
  }

  async function handleDelete(task: TaskRecord) {
    if (!confirm(`Delete "${task.name}"?`)) return;
    try {
      await api.tasks.remove(task.id);
      await loadTasks();
    } catch (err) {
      setError(String(err));
    }
  }

  return (
    <div className="dashboard">
      <div className="dashboard-toolbar">
        <FilterBar servers={servers} filters={filters} onChange={setFilters} />
        <button className="btn btn-primary" onClick={openAddForm} disabled={servers.length === 0}>
          Add task
        </button>
      </div>

      {formOpen && (
        <TaskForm
          servers={servers}
          task={editingTask}
          defaultServerId={filters.serverId}
          onSubmit={handleFormSubmit}
          onCancel={closeForm}
        />
      )}

      {error && <div className="error-banner">{error}</div>}
      {loading && <div className="loading-inline">Loading tasks…</div>}
      {!loading && groups.length === 0 && (
        <div className="empty-state">
          No scheduled tasks found yet. Install the agent on a server to auto-report cron/systemd tasks, or use
          "Add task" above for things like Docker-based backup jobs.
        </div>
      )}
      {groups.map((group) => (
        <ServerGroup
          key={group.serverId}
          serverName={group.serverName}
          tasks={group.tasks}
          onEdit={openEditForm}
          onDelete={handleDelete}
        />
      ))}
    </div>
  );
}
