"use client";

import { useCallback, useEffect, useState } from "react";
import { useQuery } from "@tanstack/react-query";
import { useTranslations } from "next-intl";

import { Button } from "@hexahost/ui";

import {
  installAddon,
  listCatalogVersions,
  listInstalledAddons,
  removeAddon,
  searchCatalog,
  type CatalogProject,
  type CatalogVersion,
} from "@/lib/api/addons";
import { getServer } from "@/lib/api/servers";

interface ServerAddonsProps {
  serverId: string;
}

export function ServerAddons({ serverId }: ServerAddonsProps) {
  const t = useTranslations("servers.addons");
  const [query, setQuery] = useState("");
  const [results, setResults] = useState<CatalogProject[]>([]);
  const [selectedProject, setSelectedProject] = useState<CatalogProject | null>(null);
  const [versions, setVersions] = useState<CatalogVersion[]>([]);
  const [busy, setBusy] = useState(false);
  const [error, setError] = useState<string | null>(null);

  const { data: server } = useQuery({
    queryKey: ["server", serverId],
    queryFn: () => getServer(serverId),
  });

  const refreshInstalled = useCallback(async () => {
    const data = await listInstalledAddons(serverId);
    return data.addons;
  }, [serverId]);

  const [installed, setInstalled] = useState<Awaited<ReturnType<typeof refreshInstalled>>>([]);

  useEffect(() => {
    void refreshInstalled().then(setInstalled).catch(() => undefined);
  }, [refreshInstalled]);

  const supportsAddons =
    server &&
    ["PAPER", "PURPUR", "FABRIC", "FORGE", "NEOFORGE", "QUILT"].includes(
      server.softwareFamily,
    );

  async function handleSearch(event: React.FormEvent) {
    event.preventDefault();
    if (!server || !supportsAddons || !query.trim()) {
      return;
    }

    setBusy(true);
    setError(null);
    try {
      const response = await searchCatalog({
        q: query.trim(),
        gameVersion: server.minecraftVersion,
        softwareFamily: server.softwareFamily,
      });
      setResults(response.projects);
      setSelectedProject(null);
      setVersions([]);
    } catch (err) {
      setError(err instanceof Error ? err.message : t("searchError"));
    } finally {
      setBusy(false);
    }
  }

  async function handleSelectProject(project: CatalogProject) {
    setSelectedProject(project);
    setBusy(true);
    setError(null);
    try {
      const response = await listCatalogVersions(project.id, serverId);
      setVersions(response.versions.filter((version) => version.compatible));
    } catch (err) {
      setError(err instanceof Error ? err.message : t("versionsError"));
    } finally {
      setBusy(false);
    }
  }

  async function handleInstall(version: CatalogVersion) {
    if (!selectedProject) {
      return;
    }
    setBusy(true);
    setError(null);
    try {
      await installAddon(serverId, selectedProject.id, version.id);
      setInstalled(await refreshInstalled());
    } catch (err) {
      setError(err instanceof Error ? err.message : t("installError"));
    } finally {
      setBusy(false);
    }
  }

  async function handleRemove(addonId: string) {
    setBusy(true);
    setError(null);
    try {
      await removeAddon(serverId, addonId);
      setInstalled(await refreshInstalled());
    } catch (err) {
      setError(err instanceof Error ? err.message : t("removeError"));
    } finally {
      setBusy(false);
    }
  }

  if (!server) {
    return <p className="text-sm text-zinc-500">{t("loading")}</p>;
  }

  if (!supportsAddons) {
    return <p className="text-sm text-zinc-600 dark:text-zinc-400">{t("unsupported")}</p>;
  }

  if (server.status !== "STOPPED") {
    return <p className="text-sm text-zinc-600 dark:text-zinc-400">{t("stoppedHint")}</p>;
  }

  return (
    <div className="space-y-6">
      {error ? (
        <p className="rounded-md border border-red-200 bg-red-50 px-3 py-2 text-sm text-red-700 dark:border-red-900 dark:bg-red-950 dark:text-red-300">
          {error}
        </p>
      ) : null}

      <form onSubmit={(event) => void handleSearch(event)} className="flex gap-2">
        <input
          className="flex-1 rounded-md border border-zinc-300 bg-white px-3 py-2 text-sm dark:border-zinc-700 dark:bg-zinc-950"
          value={query}
          onChange={(event) => setQuery(event.target.value)}
          placeholder={t("searchPlaceholder")}
        />
        <Button type="submit" disabled={busy}>
          {t("search")}
        </Button>
      </form>

      {results.length > 0 ? (
        <ul className="divide-y divide-zinc-200 rounded-lg border border-zinc-200 dark:divide-zinc-800 dark:border-zinc-800">
          {results.map((project) => (
            <li key={project.id} className="flex items-center justify-between gap-3 px-4 py-3">
              <div>
                <p className="font-medium text-sm">{project.name}</p>
                <p className="text-xs text-zinc-500 line-clamp-2">{project.description}</p>
              </div>
              <Button
                size="sm"
                variant="secondary"
                onClick={() => void handleSelectProject(project)}
                disabled={busy}
              >
                {t("select")}
              </Button>
            </li>
          ))}
        </ul>
      ) : null}

      {selectedProject && versions.length > 0 ? (
        <div className="space-y-2">
          <h3 className="text-sm font-medium">{t("compatibleVersions", { name: selectedProject.name })}</h3>
          <ul className="divide-y divide-zinc-200 rounded-lg border border-zinc-200 dark:divide-zinc-800 dark:border-zinc-800">
            {versions.map((version) => (
              <li key={version.id} className="flex items-center justify-between px-4 py-3 text-sm">
                <span>{version.versionNumber}</span>
                <Button size="sm" onClick={() => void handleInstall(version)} disabled={busy}>
                  {t("install")}
                </Button>
              </li>
            ))}
          </ul>
        </div>
      ) : null}

      <div>
        <h3 className="mb-2 text-sm font-medium">{t("installed")}</h3>
        <ul className="divide-y divide-zinc-200 rounded-lg border border-zinc-200 dark:divide-zinc-800 dark:border-zinc-800">
          {installed.length === 0 ? (
            <li className="px-4 py-6 text-center text-sm text-zinc-500">{t("empty")}</li>
          ) : (
            installed.map((addon) => (
              <li key={addon.id} className="flex items-center justify-between gap-3 px-4 py-3 text-sm">
                <div>
                  <p className="font-medium">{addon.projectName}</p>
                  <p className="text-xs text-zinc-500">
                    {addon.versionNumber} · {addon.status}
                  </p>
                </div>
                {addon.status === "INSTALLED" ? (
                  <Button
                    size="sm"
                    variant="ghost"
                    onClick={() => void handleRemove(addon.id)}
                    disabled={busy}
                  >
                    {t("remove")}
                  </Button>
                ) : null}
              </li>
            ))
          )}
        </ul>
      </div>
    </div>
  );
}
