import { listen } from "@tauri-apps/api/event";
import { useEffect, useState } from "react";
import { useParams, Link, useNavigate } from "react-router-dom";
import { getProject, deleteProject, listTrackers, listProcessedTickets } from "../../lib/api";
import type { Project, WatchedTracker, ProcessedTicket } from "../../lib/types";
import TrackerList from "../trackers/TrackerList";
import ConfirmModal from "../ui/ConfirmModal";

type ActivityLevel = "info" | "success" | "error";

interface ActivityItem {
  id: string;
  level: ActivityLevel;
  message: string;
  at: string;
}

interface PollingPayload {
  project_id: string;
  tracker_id: string;
  tracker_label: string;
  source: "manual" | "scheduled";
  new_tickets_count?: number;
  error?: string;
  count?: number;
}

interface TicketProcessingPayload {
  project_id: string;
  ticket_id: string;
  artifact_id: number;
  step?: "analyst" | "developer";
  error?: string;
}

export default function ProjectDashboard() {
  const { projectId } = useParams();
  const navigate = useNavigate();
  const [project, setProject] = useState<Project | null>(null);
  const [trackers, setTrackers] = useState<WatchedTracker[]>([]);
  const [tickets, setTickets] = useState<ProcessedTicket[]>([]);
  const [activity, setActivity] = useState<ActivityItem[]>([]);
  const [activePolls, setActivePolls] = useState<Record<string, string>>({});
  const [activeAgents, setActiveAgents] = useState<Record<string, string>>({});
  const [isDeleteModalOpen, setIsDeleteModalOpen] = useState(false);

  function appendActivity(level: ActivityLevel, message: string) {
    const item: ActivityItem = {
      id: `${Date.now()}-${Math.random().toString(36).slice(2, 8)}`,
      level,
      message,
      at: new Date().toISOString(),
    };

    setActivity((prev) => [item, ...prev].slice(0, 30));
  }

  async function loadData() {
    if (!projectId) return;
    const [proj, trks, tkts] = await Promise.all([
      getProject(projectId),
      listTrackers(projectId),
      listProcessedTickets(projectId),
    ]);
    setProject(proj);
    setTrackers(trks);
    setTickets(tkts);
  }

  useEffect(() => {
    loadData();
  }, [projectId]);

  useEffect(() => {
    if (!projectId) return;

    let unlistenFns: Array<() => void> = [];
    let cancelled = false;

    async function setup() {
      try {
        const [unlistenPollingStarted, unlistenPollingFinished, unlistenPollingError, unlistenTicketsDetected, unlistenTicketStarted, unlistenTicketDone, unlistenTicketError] =
          await Promise.all([
            listen<PollingPayload>("polling-started", (event) => {
              const payload = event.payload;
              if (payload.project_id !== projectId) return;

              setActivePolls((prev) => ({
                ...prev,
                [payload.tracker_id]: payload.tracker_label,
              }));
              appendActivity(
                "info",
                `Polling ${payload.source === "manual" ? "manuel" : "auto"} lancé sur "${payload.tracker_label}".`
              );
            }),
            listen<PollingPayload>("polling-finished", (event) => {
              const payload = event.payload;
              if (payload.project_id !== projectId) return;

              setActivePolls((prev) => {
                const next = { ...prev };
                delete next[payload.tracker_id];
                return next;
              });

              appendActivity(
                "success",
                `Polling terminé sur "${payload.tracker_label}" (${payload.new_tickets_count ?? 0} nouveau(x) ticket(s)).`
              );
              void loadData();
            }),
            listen<PollingPayload>("polling-error", (event) => {
              const payload = event.payload;
              if (payload.project_id !== projectId) return;

              setActivePolls((prev) => {
                const next = { ...prev };
                delete next[payload.tracker_id];
                return next;
              });

              appendActivity(
                "error",
                `Erreur de polling sur "${payload.tracker_label}": ${payload.error ?? "erreur inconnue"}.`
              );
            }),
            listen<PollingPayload>("new-tickets-detected", (event) => {
              const payload = event.payload;
              if (payload.project_id !== projectId) return;
              appendActivity(
                "success",
                `${payload.count ?? 0} nouveau(x) ticket(s) détecté(s) dans "${payload.tracker_label}".`
              );
              void loadData();
            }),
            listen<TicketProcessingPayload>("ticket-processing-started", (event) => {
              const payload = event.payload;
              if (payload.project_id !== projectId) return;

              setActiveAgents((prev) => ({
                ...prev,
                [payload.ticket_id]: payload.step ?? "processing",
              }));
              appendActivity(
                "info",
                `Agent ${payload.step ?? "processing"} lancé pour le ticket #${payload.artifact_id}.`
              );
              void loadData();
            }),
            listen<TicketProcessingPayload>("ticket-processing-done", (event) => {
              const payload = event.payload;
              if (payload.project_id !== projectId) return;

              setActiveAgents((prev) => {
                const next = { ...prev };
                delete next[payload.ticket_id];
                return next;
              });
              appendActivity(
                "success",
                `Pipeline agent terminé pour le ticket #${payload.artifact_id}.`
              );
              void loadData();
            }),
            listen<TicketProcessingPayload>("ticket-processing-error", (event) => {
              const payload = event.payload;
              if (payload.project_id !== projectId) return;

              setActiveAgents((prev) => {
                const next = { ...prev };
                delete next[payload.ticket_id];
                return next;
              });
              appendActivity(
                "error",
                `Erreur agent sur le ticket #${payload.artifact_id}: ${payload.error ?? "erreur inconnue"}.`
              );
              void loadData();
            }),
          ]);

        if (cancelled) {
          unlistenPollingStarted();
          unlistenPollingFinished();
          unlistenPollingError();
          unlistenTicketsDetected();
          unlistenTicketStarted();
          unlistenTicketDone();
          unlistenTicketError();
          return;
        }

        unlistenFns = [
          unlistenPollingStarted,
          unlistenPollingFinished,
          unlistenPollingError,
          unlistenTicketsDetected,
          unlistenTicketStarted,
          unlistenTicketDone,
          unlistenTicketError,
        ];
      } catch (err) {
        appendActivity(
          "error",
          `Écoute des événements live indisponible: ${err instanceof Error ? err.message : String(err)}`
        );
      }
    }

    void setup();

    return () => {
      cancelled = true;
      for (const unlisten of unlistenFns) {
        unlisten();
      }
    };
  }, [projectId]);

  async function handleDelete() {
    if (!projectId) return;
    setIsDeleteModalOpen(false);
    await deleteProject(projectId);
    window.dispatchEvent(new Event("orchai:refresh-projects"));
    navigate("/");
  }

  function statusBadgeClass(status: string): string {
    switch (status) {
      case "Pending":
        return "bg-yellow-100 text-yellow-700";
      case "Done":
        return "bg-green-100 text-green-700";
      case "Error":
        return "bg-red-100 text-red-700";
      default:
        return "bg-blue-100 text-blue-700";
    }
  }

  if (!project) {
    return <div className="p-8 text-gray-400">Loading...</div>;
  }

  const recentTickets = tickets.slice(-10).reverse();
  const activePollList = Object.entries(activePolls);
  const activeAgentList = Object.values(activeAgents);

  return (
    <div className="p-8">
      <div className="flex items-center justify-between mb-6">
        <h2 className="text-xl font-bold">{project.name}</h2>
        <div className="flex gap-2">
          <Link
            to={`/projects/${project.id}/edit`}
            className="px-3 py-1 bg-gray-200 rounded text-sm hover:bg-gray-300"
          >
            Edit
          </Link>
          <button
            onClick={() => setIsDeleteModalOpen(true)}
            className="px-3 py-1 bg-red-100 text-red-700 rounded text-sm hover:bg-red-200"
          >
            Delete
          </button>
        </div>
      </div>

      <div className="bg-white rounded-lg border border-gray-200 p-4 space-y-3">
        <div>
          <span className="text-sm text-gray-500">Path:</span>
          <span className="ml-2 text-sm font-mono">{project.path}</span>
        </div>
        {project.cloned_from && (
          <div>
            <span className="text-sm text-gray-500">Cloned from:</span>
            <span className="ml-2 text-sm font-mono">{project.cloned_from}</span>
          </div>
        )}
        <div>
          <span className="text-sm text-gray-500">Base branch:</span>
          <span className="ml-2 text-sm font-mono">{project.base_branch}</span>
        </div>
        <div>
          <span className="text-sm text-gray-500">Created:</span>
          <span className="ml-2 text-sm">{new Date(project.created_at).toLocaleDateString()}</span>
        </div>
      </div>

      <div className="mt-8">
        <h3 className="text-lg font-semibold mb-4">Watched Trackers</h3>
        <TrackerList trackers={trackers} projectId={project.id} onRefresh={loadData} />
      </div>

      <ConfirmModal
        isOpen={isDeleteModalOpen}
        onCancel={() => setIsDeleteModalOpen(false)}
        onConfirm={() => void handleDelete()}
      />

      <div className="mt-8">
        <h3 className="text-lg font-semibold mb-4">Live Activity</h3>
        <div className="bg-white rounded-lg border border-gray-200 p-4 space-y-4">
          <div className="flex flex-wrap gap-3">
            <div className="text-sm rounded-full bg-blue-50 text-blue-700 px-3 py-1">
              Polling en cours: {activePollList.length}
            </div>
            <div className="text-sm rounded-full bg-purple-50 text-purple-700 px-3 py-1">
              Agents actifs: {activeAgentList.length}
            </div>
          </div>

          {(activePollList.length > 0 || activeAgentList.length > 0) && (
            <div className="text-xs text-gray-500 space-y-1">
              {activePollList.map(([trackerId, label]) => (
                <div key={`poll-${trackerId}`}>Polling: {label}</div>
              ))}
              {activeAgentList.map((step, i) => (
                <div key={`agent-${i}`}>Agent: {step}</div>
              ))}
            </div>
          )}

          {activity.length === 0 ? (
            <div className="text-sm text-gray-400">No live activity yet.</div>
          ) : (
            <div className="space-y-2 max-h-64 overflow-y-auto">
              {activity.map((item) => (
                <div
                  key={item.id}
                  className={`rounded border px-3 py-2 text-sm ${
                    item.level === "error"
                      ? "border-red-200 bg-red-50 text-red-700"
                      : item.level === "success"
                      ? "border-green-200 bg-green-50 text-green-700"
                      : "border-blue-200 bg-blue-50 text-blue-700"
                  }`}
                >
                  <div>{item.message}</div>
                  <div className="text-[11px] opacity-70 mt-0.5">
                    {new Date(item.at).toLocaleTimeString()}
                  </div>
                </div>
              ))}
            </div>
          )}
        </div>
      </div>

      <div className="mt-8">
        <div className="flex items-center justify-between">
          <h3 className="text-lg font-semibold">Recent Tickets</h3>
          {tickets.length > 0 && (
            <Link
              to={`/projects/${project.id}/tickets`}
              className="text-sm text-blue-600 hover:underline"
            >
              View all ({tickets.length})
            </Link>
          )}
        </div>
        {recentTickets.length === 0 ? (
          <div className="text-sm text-gray-400">No tickets processed yet.</div>
        ) : (
          <div className="mt-4 space-y-3">
            {recentTickets.map((ticket) => (
              <Link
                key={ticket.id}
                to={`/tickets/${ticket.id}`}
                className="bg-white rounded-lg border border-gray-200 p-4 flex items-center justify-between gap-4"
              >
                <div className="flex-1 min-w-0">
                  <div className="flex items-center gap-2">
                    <span className="text-xs text-gray-400 font-mono">#{ticket.artifact_id}</span>
                    <span className="text-sm font-medium truncate">{ticket.artifact_title}</span>
                  </div>
                </div>
                <span
                  className={`text-xs px-2 py-0.5 rounded-full font-medium shrink-0 ${statusBadgeClass(ticket.status)}`}
                >
                  {ticket.status}
                </span>
              </Link>
            ))}
          </div>
        )}
      </div>
    </div>
  );
}
