import { useProjectId, useGithubService, useStateStore, useGeminiService, useAnthropicService } from "@/lib/state";
import { Form, FormControl, FormField, FormItem, FormMessage } from "./components/ui/form";
import { Input } from "./components/ui/input";
import { useForm } from "react-hook-form";
import { z } from "zod";
import { zodResolver } from "@hookform/resolvers/zod";
import { Button } from "./components/ui/button";
import { useToast } from "@/hooks/use-toast";
import { CircleCheck, CircleX } from "lucide-react";
import { useState, useCallback } from "react";

const githubSchema = z.object({
	githubToken: z.string().min(1, "GitHub token is required"),
});

const geminiSchema = z.object({
	geminiApiKey: z.string().min(1, "Gemini API token is required"),
});

const anthropicSchema = z.object({
	anthropicApiKey: z.string().min(1, "Anthropic API token is required"),
});

export function Integrations() {
	const { toast } = useToast();
	const store = useStateStore();
	const projectId = useProjectId();
	const [isEditingGithub, setIsEditingGithub] = useState(false);
	const [isEditingGemini, setIsEditingGemini] = useState(false);
	const [isEditingAnthropic, setIsEditingAnthropic] = useState(false);
	const githubService = useGithubService();
	const geminiService = useGeminiService();
	const anthropicService = useAnthropicService();
	const [isSaving, setIsSaving] = useState(false);

	const githubForm = useForm<z.infer<typeof githubSchema>>({
		resolver: zodResolver(githubSchema),
		mode: "onChange",
	});

	const geminiForm = useForm<z.infer<typeof geminiSchema>>({
		resolver: zodResolver(geminiSchema),
		mode: "onChange",
	});

	const anthropicForm = useForm<z.infer<typeof anthropicSchema>>({
		resolver: zodResolver(anthropicSchema),
		mode: "onChange",
	});

	const onGithubSubmit = useCallback(
		async (data: z.infer<typeof githubSchema>) => {
			if (!projectId) return;

			setIsSaving(true);

			try {
				const response = await fetch(`/api/project/${projectId}/github-token`, {
					method: "POST",
					headers: {
						"Content-Type": "application/json",
					},
					body: JSON.stringify({ githubToken: data.githubToken }),
				});

				if (!response.ok) {
					throw new Error("Failed to save GitHub token");
				}

				await store.refreshEnv();
				setIsEditingGithub(false);
				githubForm.reset();
				toast({
					title: "GitHub token saved successfully",
				});
			} catch (error) {
				toast({
					variant: "destructive",
					title: "Failed to save GitHub token",
					description: error instanceof Error ? error.message : "Unknown error",
				});
			} finally {
				setIsSaving(false);
			}
		},
		[projectId, store, githubForm, toast, setIsEditingGithub, setIsSaving],
	);

	const onGeminiSubmit = useCallback(
		async (data: z.infer<typeof geminiSchema>) => {
			if (!projectId) return;
			setIsSaving(true);
			try {
				const response = await fetch(`/api/project/${projectId}/gemini-token`, {
					method: "POST",
					headers: {
						"Content-Type": "application/json",
					},
					body: JSON.stringify({ geminiApiKey: data.geminiApiKey }),
				});
				if (!response.ok) {
					throw new Error("Failed to save Gemini token");
				}
				await store.refreshEnv();
				setIsEditingGemini(false);
				geminiForm.reset();
				toast({
					title: "Gemini token saved successfully",
				});
			} catch (error) {
				toast({
					variant: "destructive",
					title: "Failed to save Gemini token",
					description: error instanceof Error ? error.message : "Unknown error",
				});
			} finally {
				setIsSaving(false);
			}
		},
		[projectId, store, geminiForm, toast, setIsEditingGemini, setIsSaving],
	);

	const onAnthropicSubmit = useCallback(
		async (data: z.infer<typeof anthropicSchema>) => {
			if (!projectId) return;
			setIsSaving(true);
			try {
				const response = await fetch(`/api/project/${projectId}/anthropic-token`, {
					method: "POST",
					headers: {
						"Content-Type": "application/json",
					},
					body: JSON.stringify({ anthropicApiKey: data.anthropicApiKey }),
				});
				if (!response.ok) {
					throw new Error("Failed to save Anthropic token");
				}
				await store.refreshEnv();
				setIsEditingAnthropic(false);
				anthropicForm.reset();
				toast({
					title: "Anthropic token saved successfully",
				});
			} catch (error) {
				toast({
					variant: "destructive",
					title: "Failed to save Anthropic token",
					description: error instanceof Error ? error.message : "Unknown error",
				});
			} finally {
				setIsSaving(false);
			}
		},
		[projectId, store, anthropicForm, toast, setIsEditingAnthropic, setIsSaving],
	);

	const handleCancelGithub = () => {
		setIsEditingGithub(false);
		githubForm.reset();
	};

	const handleCancelGemini = () => {
		setIsEditingGemini(false);
		geminiForm.reset();
	};

	const handleCancelAnthropic = () => {
		setIsEditingAnthropic(false);
		anthropicForm.reset();
	};

	return (
		<div className="px-4 py-1">
			<div className="flex flex-col gap-1">
				<div className="flex flex-row items-center gap-1">
					{githubService ? <CircleCheck /> : <CircleX />}
					<div>Github</div>
				</div>

				{!!githubService && !isEditingGithub && (
					<Button variant="outline" className="w-fit" onClick={() => setIsEditingGithub(true)}>
						Update Access Token
					</Button>
				)}

				{(!githubService || isEditingGithub) && (
					<div className="flex flex-row items-center gap-1 text-sm">
						<div>
							Follow the link to generate new PAT:{" "}
							<a href="https://github.com/settings/personal-access-tokens" target="_blank">
								https://github.com/settings/personal-access-tokens
							</a>
							<br />
							Grant following <b>Repository</b> permissions:
							<ul>
								<li>
									<b>Contents</b> - Read-only access so dodo can clone the repository
								</li>
								<li>
									<b>Metadata</b> - Read-only access so dodo can search for repositories
								</li>
								<li>
									<b>Webhooks</b> - Read and write access so dodo can register webhooks with Github
									and receive updates
								</li>
								<li>
									<b>Administration</b> - Read and write access so dodo automatically add deploy keys
									to repositories
								</li>
							</ul>
						</div>
					</div>
				)}
				{(!githubService || isEditingGithub) && (
					<Form {...githubForm}>
						<form className="space-y-2" onSubmit={githubForm.handleSubmit(onGithubSubmit)}>
							<FormField
								control={githubForm.control}
								name="githubToken"
								render={({ field }) => (
									<FormItem>
										<FormControl>
											<Input
												type="password"
												placeholder="Personal Access Token"
												className="w-1/4"
												{...field}
											/>
										</FormControl>
										<FormMessage />
									</FormItem>
								)}
							/>
							<div className="flex flex-row items-center gap-1">
								<Button type="submit" disabled={isSaving}>
									{isSaving ? "Saving..." : "Save"}
								</Button>
								{!!githubService && (
									<Button
										type="button"
										variant="outline"
										onClick={handleCancelGithub}
										disabled={isSaving}
									>
										Cancel
									</Button>
								)}
							</div>
						</form>
					</Form>
				)}
			</div>
			<div className="flex flex-col gap-1">
				<div className="flex flex-row items-center gap-1">
					{geminiService ? <CircleCheck /> : <CircleX />}
					<div>Gemini</div>
				</div>

				{!!geminiService && !isEditingGemini && (
					<Button variant="outline" className="w-fit" onClick={() => setIsEditingGemini(true)}>
						Update API Key
					</Button>
				)}

				{(!geminiService || isEditingGemini) && (
					<div className="flex flex-row items-center gap-1 text-sm">
						<div>
							Follow the link to generate new API Key:{" "}
							<a href="https://aistudio.google.com/app/apikey" target="_blank">
								https://aistudio.google.com/app/apikey
							</a>
						</div>
					</div>
				)}
				{(!geminiService || isEditingGemini) && (
					<Form {...geminiForm}>
						<form className="space-y-2" onSubmit={geminiForm.handleSubmit(onGeminiSubmit)}>
							<FormField
								control={geminiForm.control}
								name="geminiApiKey"
								render={({ field }) => (
									<FormItem>
										<FormControl>
											<Input
												type="password"
												placeholder="Gemini API Token"
												className="w-1/4"
												{...field}
											/>
										</FormControl>
										<FormMessage />
									</FormItem>
								)}
							/>
							<div className="flex flex-row items-center gap-1">
								<Button type="submit" disabled={isSaving}>
									{isSaving ? "Saving..." : "Save"}
								</Button>
								{!!geminiService && (
									<Button
										type="button"
										variant="outline"
										onClick={handleCancelGemini}
										disabled={isSaving}
									>
										Cancel
									</Button>
								)}
							</div>
						</form>
					</Form>
				)}
			</div>
			<div className="flex flex-col gap-1">
				<div className="flex flex-row items-center gap-1">
					{anthropicService ? <CircleCheck /> : <CircleX />}
					<div>Anthropic</div>
				</div>

				{!!anthropicService && !isEditingAnthropic && (
					<Button variant="outline" className="w-fit" onClick={() => setIsEditingAnthropic(true)}>
						Update API Key
					</Button>
				)}

				{(!anthropicService || isEditingAnthropic) && (
					<div className="flex flex-row items-center gap-1 text-sm">
						<div>
							Follow the link to generate new API Key:{" "}
							<a href="https://console.anthropic.com/settings/keys" target="_blank">
								https://console.anthropic.com/settings/keys
							</a>
						</div>
					</div>
				)}
				{(!anthropicService || isEditingAnthropic) && (
					<Form {...anthropicForm}>
						<form className="space-y-2" onSubmit={anthropicForm.handleSubmit(onAnthropicSubmit)}>
							<FormField
								control={anthropicForm.control}
								name="anthropicApiKey"
								render={({ field }) => (
									<FormItem>
										<FormControl>
											<Input
												type="password"
												placeholder="Anthropic API Token"
												className="w-1/4"
												{...field}
											/>
										</FormControl>
										<FormMessage />
									</FormItem>
								)}
							/>
							<div className="flex flex-row items-center gap-1">
								<Button type="submit" disabled={isSaving}>
									{isSaving ? "Saving..." : "Save"}
								</Button>
								{!!anthropicService && (
									<Button
										type="button"
										variant="outline"
										onClick={handleCancelAnthropic}
										disabled={isSaving}
									>
										Cancel
									</Button>
								)}
							</div>
						</form>
					</Form>
				)}
			</div>
		</div>
	);
}
