"use client";

import Image from "next/image";
import { useRouter } from "next/navigation";

import { z } from "zod";
import { useForm } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";

import { motion } from "framer-motion";

import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";

import axios from "axios";

import { Send } from "lucide-react";

import clsx from "clsx";

import PostgrestError, { ANIMATION_EASE } from "@/lib/config";
import { formatDate } from "@/lib/utils";
import { createClient } from "@/utils/supabase/client";
import { Tables } from "@/utils/supabase/database.types";

import {
  Form,
  FormControl,
  FormField,
  FormItem,
  FormMessage,
} from "@/components/ui/form";
import { Badge } from "@/components/ui/badge";
import { Input } from "@/components/ui/input";
import { Button } from "@/components/ui/button";

import Spinner from "@/components/spinner";
import { Card } from "@/components/ui/card";

type AskAgentCardProps = {
  agentId: string;
  disabled?: boolean;
};

export function AskAgentCard({ agentId, disabled = false }: AskAgentCardProps) {
  const {
    data: agentsData,
    isLoading,
    error,
  } = useQuery({
    retry: 0,
    queryKey: ["agents", agentId],
    queryFn: async ({ signal }) => {
      const supabase = createClient();

      const response = await supabase
        .from("agents")
        .select("*")
        .eq("id", parseInt(agentId))
        .limit(1)
        .single();

      if (response.error) throw new PostgrestError(response.error);

      return response;
    },
  });

  if (error) return <p className="text-center">{error.message}</p>;

  if (isLoading || !agentsData || !agentsData.data)
    return <Spinner className="mx-auto" />;

  return (
    <motion.div
      initial={{ opacity: 0, y: 20 }}
      animate={{ opacity: 1, y: 0 }}
      transition={{
        duration: 0.8,
        ease: ANIMATION_EASE,
      }}
    >
      <CardContent agent={agentsData.data} disabled={disabled} />
    </motion.div>
  );
}

const CardContent = ({
  agent,
  disabled,
}: {
  agent: Tables<"agents">;
  disabled: boolean;
}) => {
  const {
    id,
    image_url,
    name,
    model_type,
    description,
    conversation,
    last_conv,
  } = agent;

  const router = useRouter();

  const formSchema = z.object({
    question: z
      .string({
        required_error: "Question is required",
      })
      .min(2, {
        message: "Minimum Question is 2 characters.",
      }),
  });

  const form = useForm<z.infer<typeof formSchema>>({
    resolver: zodResolver(formSchema),
    defaultValues: {
      question: "",
    },
    mode: "onChange",
  });

  const queryClient = useQueryClient();

  const mutation = useMutation({
    mutationFn: async (values: z.infer<typeof formSchema>) => {
      const supabase = createClient();

      const { data: existingAgent, error: error1 } = await supabase
        .from("agents")
        .select("*")
        .eq("id", id);

      if (error1) throw new PostgrestError(error1);

      const { error: error2 } = await supabase
        .from("agents")
        .update({
          conversation: existingAgent ? existingAgent[0].conversation + 1 : 0,
          last_conv: new Date().toISOString(),
        })
        .eq("id", id)
        .select();

      if (error2) throw new PostgrestError(error2);

      const botResponseJson = await axios.get(
        encodeURI(
          `https://ai-endpoint-one.dev3vds1.link/deepinfra-ai/${name}/${model_type}/${description}/${values.question}`
        )
      );

      const { data, error: error3 } = await supabase
        .from("agent_responses")
        .upsert({
          agent_id: id,
          question: values.question,
          response: botResponseJson.data.response,
        })
        .select()
        .limit(1)
        .single();

      if (error3) throw new PostgrestError(error3);

      return data;
    },
    onSuccess: (data: Tables<"agent_responses">) => {
      router.push(`/agents/${id}/responses/${data.id}`);
      queryClient.invalidateQueries({
        queryKey: ["agents", id],
      });
    },
  });

  const onSubmit = (values: z.infer<typeof formSchema>) => {
    mutation.mutate(values);
  };

  return (
    <Card className="p-6 bg-transparent">
      <div className="flex flex-col-reverse sm:flex-row justify-between gap-3 mb-4">
        <div className="mr-auto">
          <div className="flex space-x-2 mb-2">
            <p className="text-primary text-sm ">
              <time dateTime={"2024-11-10"}>
                Last Active:{" "}
                <span className="font-bold">
                  {last_conv ? formatDate(last_conv) : "-"}
                </span>
              </time>
            </p>
            <div
              className="text-sm mb-2 text-white px-2 py-0.5 rounded-md"
              style={{
                background: "linear-gradient(90deg, #FF512F 0%, #F09819 100%)",
              }}
            >
              {conversation} chats
            </div>
          </div>
          <h1 className="text-primary font-bold text-xl mb-2">{name}</h1>
          <p className="text-gray-500 text-sm">{description}</p>
        </div>
        <figure className="relative h-[333px] min-w-full sm:h-[150px] sm:min-w-[250px] rounded-xl overflow-hidden">
          <Image
            src={image_url}
            fill={true}
            alt="test"
            className="object-cover"
          />
        </figure>
      </div>
      <div className="flex gap-3">
        <Form {...form}>
          <form
            onSubmit={form.handleSubmit(onSubmit)}
            className="w-full flex gap-3"
          >
            <FormField
              control={form.control}
              name="question"
              render={({ field }) => (
                <FormItem className="w-full">
                  <FormControl>
                    <Input
                      disabled={disabled}
                      placeholder="Ask our agent"
                      className={clsx(
                        "h-9",
                        form.formState.errors.question &&
                          "focus-visible:ring-destructive"
                      )}
                      {...field}
                    />
                  </FormControl>
                  <FormMessage />
                </FormItem>
              )}
            />
            <Button disabled={mutation.isPending || disabled} size={"sm"}>
              {mutation.isPending ? (
                <Spinner className="h-4 w-4" />
              ) : (
                <Send className="h-4 w-4" />
              )}
            </Button>
          </form>
        </Form>
      </div>
    </Card>
  );
};
