"use client";
import { useState, useEffect } from "react";
import { useToast } from "@/components/ui/use-toast";
import { useRouter, useParams } from "next/navigation";
import { v4 as uuidv4 } from "uuid";

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

import {
  Form,
  FormControl,
  FormDescription,
  FormField,
  FormItem,
  FormLabel,
  FormMessage,
} from "@/components/ui/form";
import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogFooter,
  DialogHeader,
  DialogTitle,
  DialogTrigger,
} from "@/components/ui/dialog";
import { Button } from "@/components/ui/button";
import {
  ReloadIcon,
  TrashIcon,
  Pencil2Icon,
  PlusIcon,
} from "@radix-ui/react-icons";
import { Textarea } from "@/components/ui/textarea";
import {
  Card,
  CardContent,
  CardFooter,
  CardHeader,
  CardTitle,
} from "@/components/ui/card";
import { ScrollArea } from "@/components/ui/scroll-area";
import { FeatureCard } from "./feature-card";
import { Input } from "./ui/input";

const DIALOG_PAGES = {
  WELCOME: 0,
  QUESTIONS: 1,
  GENERATE_FEATURES: 2,
  GENERATED_FEATURES: 3,
  GENERATE_TASKS: 4,
  GENERATING_TASKS: 5,
  GENERATED_TASKS: 6,
};

const questionsFormSchema = z.object({
  questions: z.array(
    z.object({
      answer: z.string().optional(),
    })
  ),
});

type Question = {
  question: string;
  answer: string;
};

type Feature = {
  uid: string;
  name: string;
  description: string;
};

export function GenerateProject({
  project_name,
  project_description,
  project_stack,
}: {
  project_name: string;
  project_description: string;
  project_stack: string;
}) {
  const [questions, setQuestions] = useState<string[]>([]);
  const [features, setFeatures] = useState<Feature[]>([]);
  const [isAddingFeature, setIsAddingFeature] = useState(false);
  const [newFeatureName, setNewFeatureName] = useState("");
  const [newFeatureDescription, setNewFeatureDescription] = useState("");
  const [tasks, setTasks] = useState([]);
  const [qa, setQA] = useState<Question[]>([]);
  const [dialogOpen, setDialogOpen] = useState(false);
  const [loading, setLoading] = useState(false);
  const [dialogPage, setDialogPage] = useState(DIALOG_PAGES.WELCOME);
  const { toast } = useToast();
  const params = useParams();
  const router = useRouter();

  const form = useForm<z.infer<typeof questionsFormSchema>>({
    resolver: zodResolver(questionsFormSchema),
    mode: "all",
    defaultValues: {
      questions: [],
    },
  });

  const { fields, append, remove } = useFieldArray({
    name: "questions",
    control: form.control,
  });

  useEffect(() => {
    async function fetchFeatures() {
      try {
        console.log(params.projectID);
        const res = await fetch(
          `/w/${params.workspaceID}/p/${params.projectID}/features`
        );

        const data = await res.json();
        return data.features;
      } catch (err) {
        console.error(err);
        toast({
          variant: "destructive",
          title: "Failed to fetch features.",
          description: `${err}`,
        });
      }
    }

    fetchFeatures().then((features) => {
      if (features === undefined || features.length === 0) setDialogOpen(true);
      setFeatures(features);
    });
  }, [params.projectID, params.workspaceID, toast]);

  async function generateQuestions() {
    setLoading(true);
    try {
      const res = await fetch(
        `/w/${params.workspaceID}/p/${params.projectID}/gen`
      );
      const data = await res.json();
      console.log(data.questions);
      append(data.questions);
      setQuestions(data.questions);
      setDialogPage(DIALOG_PAGES.QUESTIONS);
      setLoading(false);
      return data.questions;
    } catch (err) {
      console.error(err);
    }
    setLoading(false);
  }

  async function generateFeatures() {
    setLoading(true);
    try {
      const res = await fetch(
        `/w/${params.workspaceID}/p/${params.projectID}/features/gen`,
        {
          method: "POST",
          body: JSON.stringify({
            project_name,
            project_description,
            project_stack,
            qa,
          }),
        }
      );
      const data = await res.json();
      console.log(data.features);
      setFeatures(data.features);
      setDialogPage(DIALOG_PAGES.GENERATED_FEATURES);
      setLoading(false);
      return data.features;
    } catch (err) {
      console.error(err);
    }
    setLoading(false);
  }

  async function generateTasks() {
    setLoading(true);
    try {
      const res = await fetch(
        `/w/${params.workspaceID}/p/${params.projectID}/features/gen/tasks`,
        {
          method: "POST",
          body: JSON.stringify({
            project_name,
            project_description,
            project_stack,
          }),
        }
      );
      const data = await res.json();
      console.log(data.tasks);
      setTasks(data.tasks);
      await addTasks(data.tasks);
      setDialogPage(DIALOG_PAGES.GENERATED_TASKS);
      setLoading(false);
      return data.tasks;
    } catch (err) {
      console.error(err);
    }
    setLoading(false);
  }

  async function addQuestions(values: z.infer<typeof questionsFormSchema>) {
    setLoading(true);
    try {
      const answer_arr = values.questions.map((q) => q.answer);
      const q_data: Question[] = answer_arr.map((a, i) => ({
        question: questions[i],
        answer: String(a),
      }));
      console.log(q_data);
      const res = await fetch(
        `/w/${params.workspaceID}/p/${params.projectID}/gen`,
        {
          method: "PUT",
          body: JSON.stringify(q_data),
        }
      );

      console.log(res);

      if (!res.ok) throw new Error(res.statusText);

      if (res.ok) {
        setQA(q_data);
        setDialogPage(DIALOG_PAGES.GENERATE_FEATURES);
      }
    } catch (err) {
      console.error(err);
    }
    setLoading(false);
  }

  async function addFeatures() {
    setLoading(true);
    try {
      const res = await fetch(
        `/w/${params.workspaceID}/p/${params.projectID}/features/add`,
        {
          method: "POST",
          body: JSON.stringify({
            features: features.map((feature) => ({
              name: feature.name,
              description: feature.description,
              project_id: params.projectID,
            })),
          }),
        }
      );

      if (!res.ok) throw new Error(res.statusText);

      const project_features = await fetch(
        `/w/${params.workspaceID}/p/${params.projectID}/features`
      );

      const data = await project_features.json();

      const deps = await fetch(
        `/w/${params.workspaceID}/p/${params.projectID}/features/gen/deps`,
        {
          method: "POST",
          body: JSON.stringify({
            project_name,
            project_description,
            project_stack,
            features: data.features,
          }),
        }
      );

      const deps_data = await deps.json();
      console.log(deps_data);

      if (res.ok) {
        setDialogPage(DIALOG_PAGES.GENERATE_TASKS);
      }
    } catch (err) {
      console.error(err);
    }
    setLoading(false);
  }

  async function addTasks(tasks: any[]) {
    try {
      const res = await fetch(
        `/w/${params.workspaceID}/p/${params.projectID}/tasks/add`,
        {
          method: "POST",
          body: JSON.stringify({
            tasks,
          }),
        }
      );

      if (!res.ok) throw new Error(res.statusText);
    } catch (err) {
      console.error(err);
    }
  }
  return (
    <Dialog open={dialogOpen} onOpenChange={setDialogOpen}>
      {dialogPage == DIALOG_PAGES.WELCOME && (
        <DialogContent>
          <DialogHeader>
            <DialogTitle>Welcome to your project!</DialogTitle>
            <DialogDescription>
              Skalara would like to learn more about your project. This will
              help in the rest of the project generation process.
            </DialogDescription>
          </DialogHeader>
          <DialogFooter>
            {!loading ? (
              <Button onClick={generateQuestions}>Generate Questions</Button>
            ) : (
              <Button disabled>
                <ReloadIcon className="mr-2 h-4 w-4 animate-spin" />
                Generating Questions...
              </Button>
            )}
          </DialogFooter>
        </DialogContent>
      )}
      {dialogPage == DIALOG_PAGES.QUESTIONS && (
        <DialogContent>
          <DialogHeader>
            <DialogTitle>Project Questions</DialogTitle>
            <DialogDescription>
              Answer any questions that you feel would help Skalara learn more
              about your project goals. All questions are optional.
            </DialogDescription>
          </DialogHeader>
          <Form {...form}>
            <form
              onSubmit={form.handleSubmit(addQuestions)}
              className="flex flex-col space-y-4"
            >
              {fields.map((field, index) => (
                <FormField
                  control={form.control}
                  key={field.id}
                  name={`questions.${index}.answer`}
                  render={({ field }) => (
                    <FormItem>
                      <FormLabel>Question {index + 1} </FormLabel>
                      <FormDescription>
                        <span className="text-gray-400">
                          {questions[index]}
                        </span>
                      </FormDescription>
                      <FormControl>
                        <Textarea {...field} />
                      </FormControl>
                      <FormMessage />
                    </FormItem>
                  )}
                />
              ))}
              <DialogFooter>
                {!loading ? (
                  <Button type="submit">Submit</Button>
                ) : (
                  <Button disabled>
                    <ReloadIcon className="mr-2 h-4 w-4 animate-spin" />
                    Loading...
                  </Button>
                )}
              </DialogFooter>
            </form>
          </Form>
        </DialogContent>
      )}
      {dialogPage == DIALOG_PAGES.GENERATE_FEATURES && (
        <DialogContent>
          <DialogHeader>
            <DialogTitle>Generate Features</DialogTitle>
            <DialogDescription>
              Skalara will now generate features for your project based on what
              you have provided so far.
            </DialogDescription>
          </DialogHeader>
          <DialogFooter>
            {!loading ? (
              <Button onClick={generateFeatures}>Generate Features</Button>
            ) : (
              <Button disabled>
                <ReloadIcon className="mr-2 h-4 w-4 animate-spin" />
                Generating Features...
              </Button>
            )}
          </DialogFooter>
        </DialogContent>
      )}
      {dialogPage == DIALOG_PAGES.GENERATED_FEATURES && (
        <DialogContent>
          <DialogHeader>
            <DialogTitle>Generated Features</DialogTitle>
            <DialogDescription>
              Skalara has generated the following features for your project:
            </DialogDescription>
          </DialogHeader>
          <ScrollArea className="max-h-[500px]">
            <div className="grid grid-cols-2 gap-4">
              {features.map(
                (
                  feature: { uid: string; name: string; description: string },
                  i
                ) => (
                  <FeatureCard
                    feature={feature}
                    features={features}
                    setFeatures={setFeatures}
                    key={feature.uid}
                  />
                )
              )}
              {!isAddingFeature ? (
                <Card className="shadow-none w-full h-[150px] flex justify-center items-center border-2 border-primary border-dashed">
                  <CardContent className="p-0 flex flex-col items-center gap-1">
                    <Button onClick={() => setIsAddingFeature(true)}>
                      <PlusIcon className="mr-2" />
                      <h1>Create Feature</h1>
                    </Button>
                  </CardContent>
                </Card>
              ) : (
                <Card>
                  <CardHeader>
                    <CardTitle>
                      <Input
                        type="text"
                        value={newFeatureName}
                        placeholder="Feature Name"
                        onChange={(e) => setNewFeatureName(e.target.value)}
                      />
                    </CardTitle>
                  </CardHeader>
                  <CardContent>
                    <Textarea
                      value={newFeatureDescription}
                      placeholder="Feature Description"
                      onChange={(e) => setNewFeatureDescription(e.target.value)}
                    />
                  </CardContent>
                  <CardFooter className="flex flex-row space-x-2">
                    <Button
                      variant="ghost"
                      onClick={() => {
                        setIsAddingFeature(false);
                        setNewFeatureName("");
                        setNewFeatureDescription("");
                      }}
                    >
                      Cancel
                    </Button>
                    <Button
                      onClick={() => {
                        setFeatures([
                          ...features,
                          {
                            name: newFeatureName,
                            description: newFeatureDescription,
                            uid: uuidv4(),
                          },
                        ]);
                        setNewFeatureName("");
                        setNewFeatureDescription("");
                        setIsAddingFeature(false);
                      }}
                    >
                      Create
                    </Button>
                  </CardFooter>
                </Card>
              )}
            </div>
          </ScrollArea>
          <DialogFooter>
            {!loading ? (
              <Button onClick={addFeatures}>Add Features to Project</Button>
            ) : (
              <Button disabled>
                <ReloadIcon className="mr-2 h-4 w-4 animate-spin" />
                Adding Features...
              </Button>
            )}
          </DialogFooter>
        </DialogContent>
      )}
      {dialogPage == DIALOG_PAGES.GENERATE_TASKS && (
        <DialogContent>
          <DialogHeader>
            <DialogTitle>Generate Tasks</DialogTitle>
            <DialogDescription>
              Skalara will now generate tasks for your project based on what you
              have provided so far.
            </DialogDescription>
          </DialogHeader>
          <DialogFooter>
            {!loading ? (
              <Button onClick={generateTasks}>Generate Tasks</Button>
            ) : (
              <Button disabled>
                <ReloadIcon className="mr-2 h-4 w-4 animate-spin" />
                Generating Tasks...
              </Button>
            )}
          </DialogFooter>
        </DialogContent>
      )}
      {dialogPage == DIALOG_PAGES.GENERATED_TASKS && (
        <DialogContent>
          <DialogHeader>
            <DialogTitle>Tasks Generated</DialogTitle>
            <DialogDescription>
              Skalara has generated tasks for your project.
            </DialogDescription>
          </DialogHeader>
          <DialogFooter>
            <Button
              onClick={() => {
                setDialogOpen(false);
                setDialogPage(DIALOG_PAGES.WELCOME);
                router.refresh();
              }}
            >
              Close
            </Button>
          </DialogFooter>
        </DialogContent>
      )}
    </Dialog>
  );
}