"use client";

import { Button, Card, CardContent, CardDescription, CardHeader, CardTitle } from "@hexahost/ui";
import { zodResolver } from "@hookform/resolvers/zod";
import { useMutation, useQuery } from "@tanstack/react-query";
import { useTranslations } from "next-intl";
import { useState } from "react";
import { useForm } from "react-hook-form";
import { Link, useRouter } from "@/i18n/navigation";
import { ApiError } from "@/lib/api/auth";
import { createServer, listPlans } from "@/lib/api/servers";
import {
  createServerSchema,
  MINECRAFT_VERSIONS,
  SOFTWARE_FAMILIES,
  type CreateServerFormValues,
} from "@/lib/schemas/server";

const inputClassName =
  "flex h-10 w-full rounded-md border border-zinc-300 bg-white px-3 text-sm text-zinc-900 placeholder:text-zinc-400 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-sky-500 dark:border-zinc-700 dark:bg-zinc-950 dark:text-zinc-100";

const STEPS = ["basics", "software", "review"] as const;
type WizardStep = (typeof STEPS)[number];

export function CreateServerWizard() {
  const t = useTranslations("servers");
  const tw = useTranslations("servers.wizard");
  const tv = useTranslations("validation");
  const router = useRouter();
  const [step, setStep] = useState<WizardStep>("basics");
  const [apiError, setApiError] = useState<string | null>(null);

  const { data: plansData, isLoading: plansLoading } = useQuery({
    queryKey: ["plans"],
    queryFn: listPlans,
    retry: false,
  });

  const schema = createServerSchema({
    nameRequired: tv("serverNameRequired"),
    nameMax: tv("serverNameMax"),
    planRequired: tv("planRequired"),
    planInvalid: tv("planInvalid"),
    versionRequired: tv("versionRequired"),
    softwareRequired: tv("softwareRequired"),
    eulaRequired: tv("eulaRequired"),
  });

  const form = useForm<CreateServerFormValues>({
    resolver: zodResolver(schema),
    defaultValues: {
      name: "",
      planId: "",
      minecraftVersion: MINECRAFT_VERSIONS[0],
      softwareFamily: "VANILLA",
      eulaAccepted: false,
    },
    mode: "onChange",
  });

  const {
    register,
    handleSubmit,
    trigger,
    watch,
    formState: { errors, isSubmitting },
  } = form;

  const createMutation = useMutation({
    mutationFn: createServer,
    onSuccess: (server) => {
      router.push(`/servers/${server.id}`);
    },
    onError: (error: unknown) => {
      setApiError(error instanceof ApiError ? (error.detail ?? error.title) : t("errors.generic"));
    },
  });

  const plans = plansData?.plans ?? [];
  const values = watch();
  const stepIndex = STEPS.indexOf(step);

  async function goNext() {
    setApiError(null);
    if (step === "basics") {
      const valid = await trigger(["name", "planId"]);
      if (valid) setStep("software");
      return;
    }
    if (step === "software") {
      const valid = await trigger(["softwareFamily", "minecraftVersion"]);
      if (valid) setStep("review");
    }
  }

  function goBack() {
    setApiError(null);
    if (step === "software") setStep("basics");
    if (step === "review") setStep("software");
  }

  async function onSubmit(formValues: CreateServerFormValues) {
    setApiError(null);
    await createMutation.mutateAsync({
      ...formValues,
      eulaAccepted: true,
    });
  }

  const selectedPlan = plans.find((plan) => plan.id === values.planId);

  return (
    <Card className="max-w-xl">
      <CardHeader>
        <CardTitle>{t("createTitle")}</CardTitle>
        <CardDescription>{t("createDescription")}</CardDescription>
        <ol className="mt-4 flex gap-2" aria-label={tw("stepsLabel")}>
          {STEPS.map((stepKey, index) => (
            <li
              key={stepKey}
              className={[
                "flex-1 rounded-full py-1 text-center text-xs font-medium",
                index <= stepIndex
                  ? "bg-sky-600 text-white dark:bg-sky-500"
                  : "bg-zinc-200 text-zinc-600 dark:bg-zinc-800 dark:text-zinc-400",
              ].join(" ")}
            >
              {tw(`steps.${stepKey}`)}
            </li>
          ))}
        </ol>
      </CardHeader>
      <CardContent>
        <form onSubmit={handleSubmit(onSubmit)} className="space-y-4" noValidate>
          {step === "basics" ? (
            <>
              <div className="space-y-2">
                <label htmlFor="name" className="text-sm font-medium text-zinc-900 dark:text-zinc-100">
                  {t("name")}
                </label>
                <input id="name" type="text" className={inputClassName} {...register("name")} />
                {errors.name ? (
                  <p className="text-sm text-red-600 dark:text-red-400">{errors.name.message}</p>
                ) : null}
              </div>
              <div className="space-y-2">
                <label htmlFor="planId" className="text-sm font-medium text-zinc-900 dark:text-zinc-100">
                  {t("plan")}
                </label>
                <select
                  id="planId"
                  className={inputClassName}
                  disabled={plansLoading}
                  {...register("planId")}
                >
                  <option value="">{plansLoading ? t("loading") : t("selectPlan")}</option>
                  {plans.map((plan) => (
                    <option key={plan.id} value={plan.id}>
                      {plan.name} ({plan.maxRamMb} MB)
                    </option>
                  ))}
                </select>
                {errors.planId ? (
                  <p className="text-sm text-red-600 dark:text-red-400">{errors.planId.message}</p>
                ) : null}
                {!plansLoading && plans.length === 0 ? (
                  <p className="text-sm text-amber-700 dark:text-amber-300">{t("noPlans")}</p>
                ) : null}
              </div>
            </>
          ) : null}

          {step === "software" ? (
            <>
              <div className="space-y-2">
                <label
                  htmlFor="softwareFamily"
                  className="text-sm font-medium text-zinc-900 dark:text-zinc-100"
                >
                  {t("software")}
                </label>
                <select id="softwareFamily" className={inputClassName} {...register("softwareFamily")}>
                  {SOFTWARE_FAMILIES.map((family) => (
                    <option key={family} value={family}>
                      {t(`softwareOptions.${family}`)}
                    </option>
                  ))}
                </select>
                {errors.softwareFamily ? (
                  <p className="text-sm text-red-600 dark:text-red-400">
                    {errors.softwareFamily.message}
                  </p>
                ) : null}
              </div>
              <div className="space-y-2">
                <label
                  htmlFor="minecraftVersion"
                  className="text-sm font-medium text-zinc-900 dark:text-zinc-100"
                >
                  {t("version")}
                </label>
                <select id="minecraftVersion" className={inputClassName} {...register("minecraftVersion")}>
                  {MINECRAFT_VERSIONS.map((version) => (
                    <option key={version} value={version}>
                      {version}
                    </option>
                  ))}
                </select>
                {errors.minecraftVersion ? (
                  <p className="text-sm text-red-600 dark:text-red-400">
                    {errors.minecraftVersion.message}
                  </p>
                ) : null}
              </div>
            </>
          ) : null}

          {step === "review" ? (
            <>
              <dl className="space-y-2 rounded-lg border border-zinc-200 p-4 text-sm dark:border-zinc-800">
                <div className="flex justify-between gap-4">
                  <dt className="text-zinc-600 dark:text-zinc-400">{t("name")}</dt>
                  <dd className="font-medium text-zinc-900 dark:text-zinc-50">{values.name}</dd>
                </div>
                <div className="flex justify-between gap-4">
                  <dt className="text-zinc-600 dark:text-zinc-400">{t("plan")}</dt>
                  <dd className="font-medium text-zinc-900 dark:text-zinc-50">
                    {selectedPlan?.name ?? "—"}
                  </dd>
                </div>
                <div className="flex justify-between gap-4">
                  <dt className="text-zinc-600 dark:text-zinc-400">{t("software")}</dt>
                  <dd className="font-medium text-zinc-900 dark:text-zinc-50">
                    {t(`softwareOptions.${values.softwareFamily}`)}
                  </dd>
                </div>
                <div className="flex justify-between gap-4">
                  <dt className="text-zinc-600 dark:text-zinc-400">{t("version")}</dt>
                  <dd className="font-medium text-zinc-900 dark:text-zinc-50">
                    {values.minecraftVersion}
                  </dd>
                </div>
              </dl>
              <div className="space-y-2">
                <label className="flex items-start gap-2 text-sm text-zinc-700 dark:text-zinc-300">
                  <input type="checkbox" className="mt-1" {...register("eulaAccepted")} />
                  <span>{t("eula")}</span>
                </label>
                {errors.eulaAccepted ? (
                  <p className="text-sm text-red-600 dark:text-red-400">
                    {errors.eulaAccepted.message}
                  </p>
                ) : null}
              </div>
            </>
          ) : null}

          {apiError ? (
            <p className="text-sm text-red-600 dark:text-red-400" role="alert">
              {apiError}
            </p>
          ) : null}

          <div className="flex gap-2">
            {step !== "basics" ? (
              <Button type="button" variant="secondary" onClick={goBack}>
                {tw("back")}
              </Button>
            ) : null}
            {step !== "review" ? (
              <Button type="button" onClick={() => void goNext()}>
                {tw("next")}
              </Button>
            ) : (
              <Button type="submit" isLoading={isSubmitting || createMutation.isPending}>
                {t("create")}
              </Button>
            )}
            <Link
              href="/servers"
              className="inline-flex h-10 items-center rounded-md border border-zinc-300 bg-white px-4 text-sm font-medium text-zinc-900 hover:bg-zinc-50 dark:border-zinc-700 dark:bg-zinc-900 dark:text-zinc-100 dark:hover:bg-zinc-800"
            >
              {t("cancel")}
            </Link>
          </div>
        </form>
      </CardContent>
    </Card>
  );
}
