import { useCallback, useEffect, useMemo, useState } from "react";

import { listProjects } from "../api/projects";
import type { Project } from "../types";
import { listRepositories, type GitRepository } from "../api/git_repositories";
import {
  getUserSessions,
  type Session,
  checkInstanceHealth,
} from "../api/sessions";
import { listToolTypes, type ToolType } from "../api/tool_types";
import { getUserConfig, updateUserConfig } from "../api/settings";
import { ErrorState, LoadingState } from "../components/data-states";
import { CreateSessionForm } from "../components/create-session-form";
import { SessionList } from "../components/session-list";
import { SessionCard } from "../components/session-card";
import { useInstanceActions } from "../hooks/use-instance-actions";
import type { InstanceHealth } from "../api/sessions";

type SessionsStatus = "loading" | "ready" | "error";

export const SessionsPage = () => {
  const [status, setStatus] = useState<SessionsStatus>("loading");
  const [sessions, setSessions] = useState<Session[]>([]);
  const [lastSessionId, setLastSessionId] = useState<string | null>(null);

  const [projects, setProjects] = useState<Project[]>([]);
  const [repositories, setRepositories] = useState<GitRepository[]>([]);
  const [toolTypes, setToolTypes] = useState<ToolType[]>([]);
  const [selectedProject, setSelectedProject] = useState<string>("");

  const [tunnelHealth, setTunnelHealth] = useState<Record<string, InstanceHealth>>({});

  const loadSessions = useCallback(async () => {
    setStatus("loading");
    try {
      const [sessionsData, config] = await Promise.all([
        getUserSessions(),
        getUserConfig(),
      ]);
      setSessions(sessionsData);
      setLastSessionId(config.last_session_id ?? null);
      setStatus("ready");
    } catch {
      setStatus("error");
    }
  }, []);

  useEffect(() => {
    void loadSessions();
  }, [loadSessions]);

  useEffect(() => {
    const loadProjects = async () => {
      try {
        const data = await listProjects();
        setProjects(data);
      } catch {
        // ignore
      }
    };
    void loadProjects();
  }, []);

  useEffect(() => {
    const loadToolTypes = async () => {
      try {
        const data = await listToolTypes();
        setToolTypes(data);
      } catch {
        // ignore
      }
    };
    void loadToolTypes();
  }, []);

  const {
    loadingSessionId,
    dirtyDeleteSession,
    dirtyDeleteFiles,
    handleOpen,
    handleStart,
    handleStop,
    handleDelete,
    handleForceDelete,
    handleRecreateTunnel,
    clearDirtyDelete,
  } = useInstanceActions({ onRefresh: loadSessions });

  // Poll health every 30 seconds for active web-enabled instances
  useEffect(() => {
    const checkHealth = async () => {
      const activeSessions = sessions.filter(
        (s) => ["running", "starting", "unhealthy", "probing"].includes(s.status)
          && s.tool_type_interfaces?.includes("web")
      );
      for (const session of activeSessions) {
        try {
          const health = await checkInstanceHealth(
            session.project_id,
            session.repository_id,
            session.id
          );
          setTunnelHealth((prev) => ({
            ...prev,
            [session.id]: health,
          }));
        } catch {
          setTunnelHealth((prev) => ({
            ...prev,
            [session.id]: {
              healthy: false,
              container_status: "unknown",
              container_health: null,
              tunnel_status: "unreachable",
              tunnel_status_code: null,
              probe_status: "unknown",
              last_probe_output: null,
              error: "check failed",
            } as InstanceHealth,
          }));
        }
      }
    };

    // Check immediately and then every 30 seconds
    void checkHealth();
    const interval = setInterval(() => void checkHealth(), 30000);
    return () => clearInterval(interval);
  }, [sessions]);

  useEffect(() => {
    if (!selectedProject) {
      setRepositories([]);
      return;
    }
    const loadRepos = async () => {
      try {
        const data = await listRepositories(selectedProject);
        setRepositories(data);
      } catch {
        setRepositories([]);
      }
    };
    void loadRepos();
  }, [selectedProject]);

  const lastSession = useMemo(
    () => sessions.find((s) => s.id === lastSessionId) ?? null,
    [sessions, lastSessionId]
  );

  const handleCreateSuccess = async (instance: { id: string }) => {
    await updateUserConfig({ last_session_id: instance.id });
    setSelectedProject("");
    await loadSessions();
  };

  return (
    <section className="stack sessions-page">
      <div className="page-header">
        <h1>Sessions</h1>
      </div>

      {status === "loading" && <LoadingState message="Loading sessions..." />}

      {status === "error" && <ErrorState message="Failed to load sessions" onRetry={() => void loadSessions()} />}

      {status === "ready" && (
        <>
          {/* Last Session */}
          {lastSession && (
            <div className="last-session-section">
              <h2>Last Session</h2>
              <SessionCard
                session={lastSession}
                onOpen={handleOpen}
                onDelete={handleDelete}
                isBusy={loadingSessionId === lastSession.id}
                tunnelHealth={tunnelHealth[lastSession.id] || null}
              />
            </div>
          )}

          {/* Session List */}
          <div className="sessions-list-wrapper">
            <SessionList
              sessions={sessions}
              onOpen={handleOpen}
              onStart={handleStart}
              onStop={handleStop}
              onDelete={handleDelete}
              onRecreateTunnel={handleRecreateTunnel}
              actionBusyId={loadingSessionId}
              tunnelHealth={tunnelHealth}
            />
          </div>

          {/* Create Session */}
          <div className="create-session-section">
            <h2>Create New Session</h2>
            <CreateSessionForm
              projects={projects}
              repositories={repositories}
              toolTypes={toolTypes}
              onProjectChange={(projectId) => {
                setSelectedProject(projectId);
              }}
              onSuccess={handleCreateSuccess}
            />
          </div>

          {/* Dirty Delete Confirmation Modal */}
          {dirtyDeleteSession && (
            <div className="modal-overlay" onClick={clearDirtyDelete}>
              <div className="modal-content" onClick={(e) => e.stopPropagation()}>
                <h3>Uncommitted Changes</h3>
                <p>
                  The repository <strong>{dirtyDeleteSession.repository_name}</strong> has
                  uncommitted changes. Deleting this session will permanently lose these
                  changes.
                </p>
                <div className="changed-files-list">
                  <h4>Changed files:</h4>
                  <ul>
                    {dirtyDeleteFiles.map((file, idx) => (
                      <li key={idx}>{file}</li>
                    ))}
                  </ul>
                </div>
                <div className="modal-actions">
                  <button
                    className="secondary-button"
                    onClick={clearDirtyDelete}
                    type="button"
                  >
                    Cancel
                  </button>
                  <button
                    className="danger-button"
                    onClick={() => void handleForceDelete(dirtyDeleteSession)}
                    type="button"
                  >
                    Force Delete
                  </button>
                </div>
              </div>
            </div>
          )}
        </>
      )}
    </section>
  );
};
