import { useCallback, useEffect, useMemo, useState } from "react";
import { useNavigate } from "react-router-dom";

import { listProjects } from "../api/projects";
import type { Project } from "../types";
import { listRepositories, type GitRepository } from "../api/git_repositories";
import {
  getUserSessions,
  type Session,
  deleteInstance,
  stopInstance,
  startInstance,
  checkInstanceHealth,
  recreateInstanceTunnel,
} from "../api/sessions";
import { listToolTypes, type ToolType } from "../api/tool_types";
import { createInstance } from "../api/sessions";
import { getUserConfig, updateUserConfig } from "../api/settings";
import { Icon } from "../components/icon";

type SessionsStatus = "loading" | "ready" | "error";
type CreateStatus = "idle" | "creating" | "error";

export const SessionsPage = () => {
  const navigate = useNavigate();
  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 [selectedRepo, setSelectedRepo] = useState<string>("");
  const [selectedToolType, setSelectedToolType] = useState<string>("");
  const [displayName, setDisplayName] = useState("");
  const [createStatus, setCreateStatus] = useState<CreateStatus>("idle");
  const [createError, setCreateError] = useState<string | null>(null);

  const [deleteConfirmId, setDeleteConfirmId] = useState<string | null>(null);
  const [stopConfirmId, setStopConfirmId] = useState<string | null>(null);
  const [tunnelHealth, setTunnelHealth] = useState<Record<string, {
    healthy: boolean;
    container_status: string;
    container_health: string | null;
    tunnel_status: string;
    tunnel_status_code: number | null;
    probe_status: string;
    last_probe_output: string | null;
    error: string | null;
  }>>({});
  const [recreatingId, setRecreatingId] = useState<string | null>(null);
  const [expandedProbeId, setExpandedProbeId] = useState<string | null>(null);

  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();
  }, []);

  // Poll health every 30 seconds for active instances
  useEffect(() => {
    const checkHealth = async () => {
      const activeSessions = sessions.filter(
        (s) => ["running", "starting", "unhealthy", "probing"].includes(s.status)
      );
      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",
            },
          }));
        }
      }
    };

    // 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 activeSessions = useMemo(
    () => sessions.filter((s) => ["running", "building", "pending", "starting", "probing", "unhealthy"].includes(s.status)),
    [sessions]
  );

  const recentSessions = useMemo(
    () => sessions.filter((s) => ["stopped", "error"].includes(s.status)).slice(0, 5),
    [sessions]
  );

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

  const handleCreate = async (e: React.FormEvent) => {
    e.preventDefault();
    setCreateError(null);

    if (!selectedProject || !selectedRepo || !selectedToolType) {
      setCreateError("Project, repository, and tool type are required");
      return;
    }

    setCreateStatus("creating");
    try {
      const instance = await createInstance(
        selectedProject,
        selectedRepo,
        selectedToolType,
        displayName || undefined
      );
      
      // Auto-start the instance
      await startInstance(selectedProject, selectedRepo, instance.id);
      
      await updateUserConfig({ last_session_id: instance.id });
      setCreateStatus("idle");
      setSelectedProject("");
      setSelectedRepo("");
      setSelectedToolType("");
      setDisplayName("");
      await loadSessions();
    } catch {
      setCreateStatus("error");
      setCreateError("Failed to create session");
    }
  };

  const handleStop = async (sessionId: string, projectId: string, repoId: string) => {
    try {
      await stopInstance(projectId, repoId, sessionId);
      setStopConfirmId(null);
      await loadSessions();
    } catch {
      setStopConfirmId(null);
    }
  };

  const handleDelete = async (sessionId: string, projectId: string, repoId: string) => {
    try {
      await deleteInstance(projectId, repoId, sessionId);
      setDeleteConfirmId(null);
      // Remove from local state immediately
      setSessions((prev) => prev.filter((s) => s.id !== sessionId));
    } catch {
      setDeleteConfirmId(null);
    }
  };

  const handleRecreateTunnel = async (session: Session) => {
    setRecreatingId(session.id);
    try {
      await recreateInstanceTunnel(
        session.project_id,
        session.repository_id,
        session.id
      );
      // Refresh sessions to get new URL
      await loadSessions();
    } catch {
      // ignore
    } finally {
      setRecreatingId(null);
    }
  };

  const handleOpen = (session: Session) => {
    if (session.url) {
      window.open(session.url, '_blank', 'noopener,noreferrer');
    } else if (session.tool_type_interfaces?.includes("terminal")) {
      navigate(`/instances/${session.id}/terminal`);
    } else {
      navigate(`/projects/${session.project_id}`);
    }
  };

  const handleResumeLast = async () => {
    if (!lastSession) return;
    // Find the project and repo IDs
    const project = projects.find((p) => p.name === lastSession.project_name);
    if (project) {
      navigate(`/projects/${project.id}`);
    }
  };

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

      {status === "loading" && <p className="muted">Loading sessions...</p>}

      {status === "error" && (
        <div className="card stack">
          <p>Failed to load sessions</p>
          <button className="secondary-button" onClick={() => void loadSessions()} type="button">
            <Icon name="refresh" size="sm" />
            Retry
          </button>
        </div>
      )}

      {status === "ready" && (
        <>
          {/* Last Session */}
          {lastSession && (
            <div className="last-session-section">
              <h2>Last Session</h2>
              <div className="card last-session-card">
                <div className="last-session-info">
                  <h3>{lastSession.display_name}</h3>
                  <p className="muted">
                    {lastSession.tool_type_name} · {lastSession.project_name} · {lastSession.repository_name}
                  </p>
                  {lastSession.url && (
                    <p className="session-url">
                      <a href={lastSession.url} target="_blank" rel="noopener noreferrer">
                        {lastSession.url}
                      </a>
                    </p>
                  )}
                  <span className={`status-badge ${lastSession.status}`}>{lastSession.status}</span>
                </div>
                <div className="last-session-actions">
                  {lastSession.url ? (
                    <a
                      href={lastSession.url}
                      target="_blank"
                      rel="noopener noreferrer"
                      className="primary-button"
                    >
                      <Icon name="external" size="sm" />
                      Open
                    </a>
                  ) : (
                    <button className="primary-button" onClick={handleResumeLast} type="button">
                      <Icon name="play" size="sm" />
                      Resume
                    </button>
                  )}
                </div>
              </div>
            </div>
          )}

          {/* Active Sessions */}
          <div className="active-sessions-section">
            <h2>
              Active Sessions
              {activeSessions.length > 0 && (
                <span className="badge">{activeSessions.length}</span>
              )}
            </h2>
            {activeSessions.length === 0 ? (
              <p className="muted">No active sessions</p>
            ) : (
              <div className="sessions-grid">
                {activeSessions.map((session) => (
                  <div className="card session-card" key={session.id}>
                    <div className="session-info">
                      <h4>{session.display_name}</h4>
                      <p className="muted">
                        {session.tool_type_name} · {session.project_name}
                      </p>
                      {session.url && (
                        <p className="session-url">
                          <a href={session.url} target="_blank" rel="noopener noreferrer">
                            {session.url}
                          </a>
                        </p>
                      )}
                      <span className={`status-badge ${session.status}`}>{session.status}</span>
                      {session.status === "starting" && (
                        <span className="status-badge starting">starting...</span>
                      )}
                      {session.status === "probing" && (
                        <span className="status-badge probing">checking...</span>
                      )}
                      {tunnelHealth[session.id] && tunnelHealth[session.id].tunnel_status === "unreachable" && (
                        <span className="status-badge error">tunnel error</span>
                      )}
                      {tunnelHealth[session.id] && tunnelHealth[session.id].tunnel_status === "error_response" && (
                        <span className="status-badge warning">app error ({tunnelHealth[session.id].tunnel_status_code})</span>
                      )}
                      {tunnelHealth[session.id]?.last_probe_output && (
                        <div className="probe-output-section">
                          <button
                            className="probe-toggle"
                            onClick={() => setExpandedProbeId(expandedProbeId === session.id ? null : session.id)}
                            type="button"
                          >
                            <Icon name="info" size="sm" />
                            {expandedProbeId === session.id ? "Hide probe output" : "Show probe output"}
                          </button>
                          {expandedProbeId === session.id && (
                            <pre className="probe-output">
                              {tunnelHealth[session.id].last_probe_output}
                            </pre>
                          )}
                        </div>
                      )}
                    </div>
                    <div className="session-actions">
                      {session.url ? (
                        <a
                          href={session.url}
                          target="_blank"
                          rel="noopener noreferrer"
                          className="secondary-button small"
                        >
                          <Icon name="external" size="sm" />
                          Open
                        </a>
                      ) : (
                        <button
                          className="secondary-button small"
                          onClick={() => handleOpen(session)}
                          type="button"
                        >
                          <Icon name="external" size="sm" />
                          Open
                        </button>
                      )}
                      {tunnelHealth[session.id] && tunnelHealth[session.id].tunnel_status === "unreachable" && (
                        <button
                          className="secondary-button small"
                          onClick={() => void handleRecreateTunnel(session)}
                          type="button"
                          disabled={recreatingId === session.id}
                        >
                          <Icon name="refresh" size="sm" />
                          {recreatingId === session.id ? "Recreating..." : "Recreate Tunnel"}
                        </button>
                      )}
                      {stopConfirmId === session.id ? (
                        <div className="stop-confirm-inline">
                          <span className="confirm-text">Stop?</span>
                          <button
                            className="danger-button small"
                            onClick={() =>
                              void handleStop(
                                session.id,
                                session.project_id,
                                session.repository_id
                              )
                            }
                            type="button"
                          >
                            Stop
                          </button>
                          <button
                            className="ghost-button small"
                            onClick={() => setStopConfirmId(null)}
                            type="button"
                          >
                            Cancel
                          </button>
                        </div>
                      ) : (
                        <button
                          className="secondary-button small"
                          onClick={() => setStopConfirmId(session.id)}
                          type="button"
                        >
                          <Icon name="stop" size="sm" />
                          Stop
                        </button>
                      )}
                      {deleteConfirmId === session.id ? (
                        <div className="delete-confirm-inline">
                          <button
                            className="danger-button small"
                            onClick={() =>
                              void handleDelete(
                                session.id,
                                session.project_id,
                                session.repository_id
                              )
                            }
                            type="button"
                          >
                            Delete
                          </button>
                          <button
                            className="ghost-button small"
                            onClick={() => setDeleteConfirmId(null)}
                            type="button"
                          >
                            Cancel
                          </button>
                        </div>
                      ) : (
                        <button
                          className="ghost-button small danger-text"
                          onClick={() => setDeleteConfirmId(session.id)}
                          type="button"
                        >
                          <Icon name="delete" size="sm" />
                        </button>
                      )}
                    </div>
                  </div>
                ))}
              </div>
            )}
          </div>

          {/* Recent Sessions */}
          {recentSessions.length > 0 && (
            <div className="recent-sessions-section">
              <h2>Recent Sessions</h2>
              <div className="recent-sessions-list">
                {recentSessions.map((session) => (
                  <div className="recent-session-item" key={session.id}>
                    <div className="recent-session-info">
                      <span className="recent-session-name">{session.display_name}</span>
                      <span className="muted">
                        {session.tool_type_name} · {session.project_name}
                      </span>
                    </div>
                    <div className="recent-session-actions">
                      {session.url ? (
                        <a
                          href={session.url}
                          target="_blank"
                          rel="noopener noreferrer"
                          className="ghost-button small"
                        >
                          Open
                        </a>
                      ) : (
                        <button
                          className="ghost-button small"
                          onClick={() => handleOpen(session)}
                          type="button"
                        >
                          Open
                        </button>
                      )}
                      {deleteConfirmId === session.id ? (
                        <div className="delete-confirm-inline">
                          <button
                            className="danger-button small"
                            onClick={() =>
                              void handleDelete(
                                session.id,
                                session.project_id,
                                session.repository_id
                              )
                            }
                            type="button"
                          >
                            Delete
                          </button>
                          <button
                            className="ghost-button small"
                            onClick={() => setDeleteConfirmId(null)}
                            type="button"
                          >
                            Cancel
                          </button>
                        </div>
                      ) : (
                        <button
                          className="ghost-button small danger-text"
                          onClick={() => setDeleteConfirmId(session.id)}
                          type="button"
                        >
                          <Icon name="delete" size="sm" />
                        </button>
                      )}
                    </div>
                  </div>
                ))}
              </div>
            </div>
          )}

          {/* Create Session */}
          <div className="create-session-section">
            <h2>Create New Session</h2>
            <form onSubmit={handleCreate} className="card stack create-session-form">
              <div className="form-row">
                <label className="form-field">
                  Project
                  <select
                    value={selectedProject}
                    onChange={(e) => {
                      setSelectedProject(e.target.value);
                      setSelectedRepo("");
                    }}
                  >
                    <option value="">Select project...</option>
                    {projects.map((p) => (
                      <option key={p.id} value={p.id}>
                        {p.name}
                      </option>
                    ))}
                  </select>
                </label>

                <label className="form-field">
                  Repository
                  <select
                    value={selectedRepo}
                    onChange={(e) => setSelectedRepo(e.target.value)}
                    disabled={!selectedProject}
                  >
                    <option value="">Select repository...</option>
                    {repositories.map((r) => (
                      <option key={r.id} value={r.id}>
                        {r.name}
                      </option>
                    ))}
                  </select>
                </label>

                <label className="form-field">
                  Tool Type
                  <select
                    value={selectedToolType}
                    onChange={(e) => setSelectedToolType(e.target.value)}
                  >
                    <option value="">Select tool...</option>
                    {toolTypes.map((t) => (
                      <option key={t.id} value={t.id}>
                        {t.display_name}
                      </option>
                    ))}
                  </select>
                </label>
              </div>

              <label className="form-field">
                Display Name (optional)
                <input
                  type="text"
                  value={displayName}
                  onChange={(e) => setDisplayName(e.target.value)}
                  placeholder="My Development Environment"
                />
              </label>

              {createError && <p className="error-text">{createError}</p>}

              <div className="form-actions">
                <button
                  className="primary-button"
                  type="submit"
                  disabled={createStatus === "creating"}
                >
                  {createStatus === "creating" ? (
                    <>
                      <Icon name="loading" size="sm" />
                      Creating...
                    </>
                  ) : (
                    <>
                      <Icon name="add" size="sm" />
                      Create Session
                    </>
                  )}
                </button>
              </div>
            </form>
          </div>
        </>
      )}
    </section>
  );
};
