"use client";

import { Button, Card, CardContent, CardDescription, CardHeader, CardTitle } from "@hexahost/ui";
import { zodResolver } from "@hookform/resolvers/zod";
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import { useTranslations } from "next-intl";
import { useEffect, useState } from "react";
import { useForm } from "react-hook-form";
import { z } from "zod";
import { ApiError } from "@/lib/api/auth";
import {
  getProperties,
  updateProperties,
  type Difficulty,
  type GameMode,
  type ServerProperties,
} from "@/lib/api/properties";

interface ServerPropertiesFormProps {
  serverId: string;
}

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 labelClassName = "text-sm font-medium text-zinc-700 dark:text-zinc-300";

const GAME_MODES: GameMode[] = ["survival", "creative", "adventure", "spectator"];
const DIFFICULTIES: Difficulty[] = ["peaceful", "easy", "normal", "hard"];

function createPropertiesSchema(messages: {
  motdMax: string;
  maxPlayersMin: string;
  maxPlayersMax: string;
}) {
  return z.object({
    motd: z.string().max(256, messages.motdMax),
    gamemode: z.enum(["survival", "creative", "adventure", "spectator"]),
    difficulty: z.enum(["peaceful", "easy", "normal", "hard"]),
    maxPlayers: z.coerce.number().int().min(1, messages.maxPlayersMin).max(200, messages.maxPlayersMax),
    pvp: z.boolean(),
    whitelist: z.boolean(),
    hardcore: z.boolean().optional(),
    onlineMode: z.boolean().optional(),
    enableCommandBlock: z.boolean().optional(),
    viewDistance: z.coerce.number().int().min(3).max(32).optional(),
    simulationDistance: z.coerce.number().int().min(3).max(32).optional(),
    spawnProtection: z.coerce.number().int().min(0).max(64).optional(),
    allowFlight: z.boolean().optional(),
  });
}

type PropertiesFormValues = z.infer<ReturnType<typeof createPropertiesSchema>>;

export function ServerPropertiesForm({ serverId }: ServerPropertiesFormProps) {
  const t = useTranslations("servers.properties");
  const tv = useTranslations("validation");
  const queryClient = useQueryClient();
  const [apiError, setApiError] = useState<string | null>(null);
  const [saved, setSaved] = useState(false);

  const schema = createPropertiesSchema({
    motdMax: tv("motdMax"),
    maxPlayersMin: tv("maxPlayersMin"),
    maxPlayersMax: tv("maxPlayersMax"),
  });

  const { data, isLoading, isError } = useQuery({
    queryKey: ["server-properties", serverId],
    queryFn: () => getProperties(serverId),
  });

  const {
    register,
    handleSubmit,
    reset,
    formState: { errors, isSubmitting, isDirty },
  } = useForm<PropertiesFormValues>({
    resolver: zodResolver(schema),
    defaultValues: {
      motd: "",
      gamemode: "survival",
      difficulty: "normal",
      maxPlayers: 20,
      pvp: true,
      whitelist: false,
      hardcore: false,
      onlineMode: true,
      enableCommandBlock: false,
      viewDistance: 10,
      simulationDistance: 10,
      spawnProtection: 16,
      allowFlight: false,
    },
  });

  useEffect(() => {
    if (data) {
      reset(mapPropertiesToForm(data));
    }
  }, [data, reset]);

  const saveMutation = useMutation({
    mutationFn: (values: PropertiesFormValues) => updateProperties(serverId, values),
    onSuccess: (result) => {
      setApiError(null);
      setSaved(true);
      reset(mapPropertiesToForm(result));
      void queryClient.invalidateQueries({ queryKey: ["server-properties", serverId] });
      setTimeout(() => setSaved(false), 2000);
    },
    onError: (error: unknown) => {
      setSaved(false);
      setApiError(error instanceof ApiError ? (error.detail ?? error.title) : t("errors.saveFailed"));
    },
  });

  async function onSubmit(values: PropertiesFormValues) {
    setApiError(null);
    await saveMutation.mutateAsync(values);
  }

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

  if (isError || !data) {
    return <p className="text-sm text-red-600 dark:text-red-400">{t("errors.loadFailed")}</p>;
  }

  return (
    <Card className="max-w-2xl">
      <CardHeader>
        <CardTitle>{t("title")}</CardTitle>
        <CardDescription>{t("description")}</CardDescription>
      </CardHeader>
      <CardContent>
        <form onSubmit={handleSubmit(onSubmit)} className="space-y-5">
          <div className="space-y-2">
            <label htmlFor="motd" className={labelClassName}>
              {t("motd")}
            </label>
            <input id="motd" type="text" className={inputClassName} {...register("motd")} />
            {errors.motd ? (
              <p className="text-sm text-red-600 dark:text-red-400">{errors.motd.message}</p>
            ) : null}
          </div>

          <div className="grid gap-4 sm:grid-cols-2">
            <div className="space-y-2">
              <label htmlFor="gamemode" className={labelClassName}>
                {t("gamemode")}
              </label>
              <select id="gamemode" className={inputClassName} {...register("gamemode")}>
                {GAME_MODES.map((mode) => (
                  <option key={mode} value={mode}>
                    {t(`gamemodes.${mode}`)}
                  </option>
                ))}
              </select>
            </div>

            <div className="space-y-2">
              <label htmlFor="difficulty" className={labelClassName}>
                {t("difficulty")}
              </label>
              <select id="difficulty" className={inputClassName} {...register("difficulty")}>
                {DIFFICULTIES.map((level) => (
                  <option key={level} value={level}>
                    {t(`difficulties.${level}`)}
                  </option>
                ))}
              </select>
            </div>
          </div>

          <div className="space-y-2">
            <label htmlFor="maxPlayers" className={labelClassName}>
              {t("maxPlayers")}
            </label>
            <input
              id="maxPlayers"
              type="number"
              min={1}
              max={200}
              className={inputClassName}
              {...register("maxPlayers")}
            />
            {errors.maxPlayers ? (
              <p className="text-sm text-red-600 dark:text-red-400">{errors.maxPlayers.message}</p>
            ) : null}
          </div>

          <div className="grid gap-3 sm:grid-cols-2">
            <label className="flex items-center gap-2 text-sm text-zinc-700 dark:text-zinc-300">
              <input type="checkbox" className="h-4 w-4 rounded border-zinc-300" {...register("pvp")} />
              {t("pvp")}
            </label>
            <label className="flex items-center gap-2 text-sm text-zinc-700 dark:text-zinc-300">
              <input
                type="checkbox"
                className="h-4 w-4 rounded border-zinc-300"
                {...register("whitelist")}
              />
              {t("whitelist")}
            </label>
            <label className="flex items-center gap-2 text-sm text-zinc-700 dark:text-zinc-300">
              <input
                type="checkbox"
                className="h-4 w-4 rounded border-zinc-300"
                {...register("hardcore")}
              />
              {t("hardcore")}
            </label>
            <label className="flex items-center gap-2 text-sm text-zinc-700 dark:text-zinc-300">
              <input
                type="checkbox"
                className="h-4 w-4 rounded border-zinc-300"
                {...register("onlineMode")}
              />
              {t("onlineMode")}
            </label>
            <label className="flex items-center gap-2 text-sm text-zinc-700 dark:text-zinc-300">
              <input
                type="checkbox"
                className="h-4 w-4 rounded border-zinc-300"
                {...register("enableCommandBlock")}
              />
              {t("enableCommandBlock")}
            </label>
            <label className="flex items-center gap-2 text-sm text-zinc-700 dark:text-zinc-300">
              <input
                type="checkbox"
                className="h-4 w-4 rounded border-zinc-300"
                {...register("allowFlight")}
              />
              {t("allowFlight")}
            </label>
          </div>

          <div className="grid gap-4 sm:grid-cols-3">
            <div className="space-y-2">
              <label htmlFor="viewDistance" className={labelClassName}>
                {t("viewDistance")}
              </label>
              <input
                id="viewDistance"
                type="number"
                min={3}
                max={32}
                className={inputClassName}
                {...register("viewDistance")}
              />
            </div>
            <div className="space-y-2">
              <label htmlFor="simulationDistance" className={labelClassName}>
                {t("simulationDistance")}
              </label>
              <input
                id="simulationDistance"
                type="number"
                min={3}
                max={32}
                className={inputClassName}
                {...register("simulationDistance")}
              />
            </div>
            <div className="space-y-2">
              <label htmlFor="spawnProtection" className={labelClassName}>
                {t("spawnProtection")}
              </label>
              <input
                id="spawnProtection"
                type="number"
                min={0}
                max={64}
                className={inputClassName}
                {...register("spawnProtection")}
              />
            </div>
          </div>

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

          {saved ? (
            <p className="text-sm text-green-600 dark:text-green-400">{t("saved")}</p>
          ) : null}

          <Button type="submit" disabled={isSubmitting || saveMutation.isPending || !isDirty}>
            {isSubmitting || saveMutation.isPending ? t("saving") : t("save")}
          </Button>
        </form>
      </CardContent>
    </Card>
  );
}

function mapPropertiesToForm(properties: ServerProperties): PropertiesFormValues {
  return {
    motd: properties.motd,
    gamemode: properties.gamemode,
    difficulty: properties.difficulty,
    maxPlayers: properties.maxPlayers,
    pvp: properties.pvp,
    whitelist: properties.whitelist,
    hardcore: properties.hardcore ?? false,
    onlineMode: properties.onlineMode ?? true,
    enableCommandBlock: properties.enableCommandBlock ?? false,
    viewDistance: properties.viewDistance ?? 10,
    simulationDistance: properties.simulationDistance ?? 10,
    spawnProtection: properties.spawnProtection ?? 16,
    allowFlight: properties.allowFlight ?? false,
  };
}
