import { Server } from "../../types/Server.ts";
import { useEffect, useRef, useState } from "react";
import { IApp } from "../../types/App.ts";
import api from "../../utils/api.ts";
import { Session } from "../../types/Session.ts";
import { Client } from "../../types/Client.ts";
import useModalStore from "../../stores/useModalStore.ts";
import TableSelector from "../TableSelector.tsx";
import Input from "../Input.tsx";
import StartSessionIcon from "../icons/StartSessionIcon.tsx";
import Button from "../Button.tsx";
import ProjectSelector from "../ProjectSelector.tsx";
import { useQueryClient, useMutation, useQuery } from "@tanstack/react-query";

interface Props {
  targetServerId: string | null;
}

export default function CreateSessionModal({ targetServerId }: Props) {
  const { setModal } = useModalStore();
  const [name, setName] = useState<string | null>(null);
  const [phone, setPhone] = useState<string | null>(null);
  const [email, setEmail] = useState<string | null>(null);
  const [isSessionExists, setIsSessionExists] = useState(false);

  const queryClient = useQueryClient();

  const { data: servers } = useQuery({
    queryKey: ["servers"],
    queryFn: () => api.get("servers?withLastSession=true").json<Server[]>(),
    refetchInterval: 1000,
  });

  const targetServer = targetServerId
    ? servers?.find((server) => server.id === targetServerId) || null
    : null;

  const [selectedServer, setSelectedServer] = useState<Server | null>(
    targetServer
  );
  const [selectedApp, setSelectedApp] = useState<IApp | null>(null);

  useEffect(() => {
    setSelectedApp(
      selectedServer?.sessions?.[0]?.app ||
        selectedServer?.apps?.[0].app ||
        null
    );
  }, [selectedServer]);

  const { mutate: createClient } = useMutation({
    mutationFn: () => {
      return api
        .post("clients", {
          json: {
            name,
            phone,
            email,
          },
        })
        .json<Client>();
    },
  });

  const { mutate: createSession } = useMutation({
    mutationKey: ["create-session", selectedServer?.id],
    mutationFn: ({
      clientId,
      serverId,
      appId,
    }: {
      clientId: string;
      serverId: string;
      appId: string;
    }) =>
      api
        .post("sessions", {
          json: {
            clientId,
            serverId,
            appId,
          },
        })
        .json<Session>(),
    onMutate: () => {
      queryClient.invalidateQueries({ queryKey: ["sessions"] });
      queryClient.invalidateQueries({ queryKey: ["servers"] });
      setModal(null);
    },
  });

  const { mutate: endSession } = useMutation({
    mutationKey: ["sessions", selectedServer?.sessions?.[0]?.id],
    mutationFn: () =>
      api.put(`sessions/${selectedServer?.sessions?.[0]?.id}`, {
        json: { status: "ending" },
      }),
    onMutate: () => queryClient.invalidateQueries({ queryKey: ["sessions"] }),
  });

  async function handleClickCreateSession(e: React.FormEvent<HTMLFormElement>) {
    e.preventDefault();

    if (!name || !phone || !selectedServer || !selectedApp) return;

    if (selectedServer?.sessions?.[0]?.status !== "started") {
      createClient(undefined, {
        onSuccess: (client) => {
          createSession({
            clientId: client.id,
            serverId: selectedServer.id,
            appId: selectedApp.id,
          });
        },
      });
      return;
    }

    if (!isSessionExists) {
      setIsSessionExists(true);
      return;
    }

    endSession(undefined, {
      onError: (error) => {
        console.log("Ошибка при завершении сессии:", error);
      },
    });
  }

  useEffect(() => {
    if (
      selectedServer &&
      servers?.find((server) => server.id === selectedServer?.id)?.sessions?.[0]
        ?.status === "ended" &&
      selectedApp &&
      isSessionExists
    )
      createClient(undefined, {
        onSuccess: (client) => {
          createSession({
            clientId: client.id,
            serverId: selectedServer?.id,
            appId: selectedApp.id,
          });
        },
      });
  }, [
    selectedApp,
    servers,
    createClient,
    createSession,
    isSessionExists,
    selectedServer,
  ]);

  const ref = useRef<HTMLFormElement>(null);

  return (
    <form
      className="relative rounded-[2.222vw] w-[25vw] min-h-[calc(100dvh-2.222vw)] bg-[#F0F0F0] flex flex-col overflow-hidden"
      onSubmit={handleClickCreateSession}
      ref={ref}
    >
      <div className="w-full h-[4.861vw] flex items-center justify-center">
        <p className="title-s font-medium">Новый сеанс</p>
      </div>
      <div className="w-full h-[6.944vw] bg-[url(/images/Table.png)] bg-no-repeat bg-top bg-[length:9.306vw]" />
      <div className="bg-white rounded-t-[2.222vw] p-[1.389vw] flex flex-col gap-y-[1.667vw] flex-1 overflow-y-auto">
        <TableSelector
          tables={servers || []}
          selectedTable={selectedServer}
          onSelect={setSelectedServer}
        />
        <div className="flex flex-col gap-y-[0.833vw]">
          <p className="title-s font-medium">Укажите данные клиента</p>
          <div className="flex flex-col gap-y-[0.556vw]">
            <Input
              value={phone || ""}
              onChange={(e) => setPhone(e.target.value)}
              placeholder="Номер телефона"
              required
            />
            <Input
              value={name || ""}
              onChange={(e) => setName(e.target.value)}
              placeholder="Имя"
              required
            />
            <Input
              type="email"
              value={email || ""}
              onChange={(e) => setEmail(e.target.value)}
              placeholder="Электронная почта"
            />
          </div>
        </div>
        <div className="flex flex-col gap-y-[0.833vw]">
          <p className="title-s font-medium">Выберите параметры сеанса</p>
          {selectedServer &&
            selectedServer?.apps &&
            selectedServer?.apps?.length > 0 && (
              <ProjectSelector
                activeProject={
                  selectedServer?.sessions?.[0]?.status === "started"
                    ? selectedApp
                    : null
                }
                projects={selectedServer?.apps.map(({ app }) => app)}
                selectedProject={selectedApp}
                setSelectedProject={setSelectedApp}
              />
            )}
        </div>
        {isSessionExists && (
          <div className="absolute inset-0 top-[11.806vw] bg-[#FFFFFF] flex flex-col gap-[1.111vw] items-center justify-center h-[31.458vw]">
            <img
              src="/images/ghost.png"
              alt="ghost error"
              className="w-[13.889vw] h-[11.806vw]"
            />
            <div className="flex flex-col gap-[0.556vw] items-center">
              <h3 className="title-m font-medium">Есть текущий сеанс</h3>
              <p className="caption-s text-[#BDBDBD] text-center whitespace-pre-line">
                {`На выбранном столе есть текущий сеанс. 
              При запуске нового текущий будет завершен.`}
              </p>
            </div>
          </div>
        )}
        <div className="flex-1 flex flex-col justify-end">
          <Button
            type="submit"
            disabled={
              !ref.current?.checkValidity() ||
              !selectedServer ||
              !selectedApp ||
              servers?.find((server) => server.id === selectedServer?.id)
                ?.sessions?.[0]?.status === "ending"
            }
            variant="cta"
            size="large"
            className="sticky bottom-0"
          >
            <div className="size-[1.111vw]">
              <StartSessionIcon />
            </div>
            <span>Запустить сеанс</span>
          </Button>
        </div>
      </div>
    </form>
  );
}
