import { NodeRect } from "./node-rect";
import {
	GithubNode,
	nodeIsConnectable,
	nodeLabel,
	useStateStore,
	useGithubService,
	useGithubRepositories,
	useGithubRepositoriesLoading,
	useGithubRepositoriesError,
	useFetchGithubRepositories,
	AppNode,
} from "@/lib/state";
import { useEffect, useMemo, useState } from "react";
import { z } from "zod";
import { DeepPartial, EventType, useForm } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
import { Form, FormControl, FormField, FormItem, FormMessage } from "./ui/form";
import { Handle, Position } from "@xyflow/react";
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "./ui/select";
import { useProjectId } from "@/lib/state";
import { Alert, AlertDescription } from "./ui/alert";
import { AlertCircle, LoaderCircle, RefreshCw } from "lucide-react";
import { Button } from "./ui/button";
import { NodeDetailsProps } from "@/lib/types";
import { ImportModal } from "./import-modal";

export function NodeGithub(node: GithubNode) {
	const { id, selected } = node;
	const isConnectable = useMemo(() => nodeIsConnectable(node, "repository"), [node]);
	return (
		<NodeRect id={id} selected={selected} node={node} state={node.data.state}>
			<div style={{ padding: "10px 20px" }}>
				{nodeLabel(node)}
				<Handle
					id="repository"
					type={"source"}
					position={Position.Right}
					isConnectableStart={isConnectable}
					isConnectableEnd={isConnectable}
					isConnectable={isConnectable}
				/>
			</div>
		</NodeRect>
	);
}

const schema = z.object({
	repositoryId: z.number().optional(),
});

export function NodeGithubDetails({ node, disabled }: NodeDetailsProps<GithubNode>) {
	const { id, data } = node;
	const store = useStateStore();
	const projectId = useProjectId();
	const githubService = useGithubService();

	const storeRepos = useGithubRepositories();
	const isLoadingRepos = useGithubRepositoriesLoading();
	const repoError = useGithubRepositoriesError();
	const fetchStoreRepositories = useFetchGithubRepositories();

	const [showImportModal, setShowImportModal] = useState(false);

	const form = useForm<z.infer<typeof schema>>({
		resolver: zodResolver(schema),
		mode: "onChange",
		defaultValues: {
			repositoryId: data.repository?.id,
		},
	});

	useEffect(() => {
		form.reset({ repositoryId: data.repository?.id });
	}, [data.repository?.id, form]);

	useEffect(() => {
		const sub = form.watch(
			(
				value: DeepPartial<z.infer<typeof schema>>,
				{ name, type }: { name?: keyof z.infer<typeof schema> | undefined; type?: EventType | undefined },
			) => {
				if (type !== "change") {
					return;
				}
				switch (name) {
					case "repositoryId":
						if (value.repositoryId) {
							const repo = storeRepos.find((r) => r.id === value.repositoryId);
							if (!repo) {
								return;
							}
							store.setNodes(
								store.nodes.map((n): AppNode => {
									if (n.type === "github" && n.id === id) {
										return {
											...n,
											data: {
												...n.data,
												repository: {
													id: repo.id,
													sshURL: repo.ssh_url,
													fullName: repo.full_name,
												},
											},
										};
									} else if (n.type === "app" && n.data.repository?.repoNodeId === id) {
										return {
											...n,
											data: { ...n.data, repository: { id: repo.id, repoNodeId: id } },
										};
									} else {
										return n;
									}
								}),
							);
						}
						break;
				}
			},
		);
		return () => sub.unsubscribe();
	}, [form, store, id, storeRepos]);

	return (
		<>
			<Form {...form}>
				<form className="space-y-2">
					<FormField
						control={form.control}
						name="repositoryId"
						render={({ field }) => (
							<FormItem>
								<div className="flex items-center gap-2 w-full">
									<div className="flex-grow">
										<Select
											onValueChange={(value) => field.onChange(Number(value))}
											value={field.value?.toString()}
											disabled={isLoadingRepos || !projectId || !githubService || disabled}
										>
											<FormControl>
												<SelectTrigger>
													<SelectValue
														placeholder={
															githubService
																? isLoadingRepos
																	? "Loading..."
																	: storeRepos.length === 0
																		? "No repositories found"
																		: "Select a repository"
																: "GitHub not configured"
														}
													/>
												</SelectTrigger>
											</FormControl>
											<SelectContent>
												{storeRepos.map((repo) => (
													<SelectItem key={repo.id} value={repo.id.toString()}>
														{repo.full_name}
														{repo.description && ` - ${repo.description}`}
													</SelectItem>
												))}
											</SelectContent>
										</Select>
									</div>
									{isLoadingRepos && (
										<Button variant="ghost" size="icon" disabled>
											<LoaderCircle className="h-5 w-5 animate-spin text-muted-foreground" />
										</Button>
									)}
									{!isLoadingRepos && githubService && (
										<Button
											variant="ghost"
											size="icon"
											onClick={fetchStoreRepositories}
											disabled={disabled}
											aria-label="Refresh repositories"
										>
											<RefreshCw className="h-5 w-5 text-muted-foreground" />
										</Button>
									)}
								</div>
								<FormMessage />
								{repoError && <p className="text-sm text-red-500 mt-1">{repoError}</p>}
								{!githubService && (
									<Alert variant="destructive" className="mt-2">
										<AlertCircle className="h-4 w-4" />
										<AlertDescription>
											Please configure Github Personal Access Token in the Integrations tab.
										</AlertDescription>
									</Alert>
								)}
							</FormItem>
						)}
					/>
				</form>
			</Form>
			<Button
				disabled={!data.repository?.sshURL || !githubService || disabled}
				onClick={() => setShowImportModal(true)}
			>
				Scan for services
			</Button>
			<ImportModal
				open={showImportModal}
				onOpenChange={setShowImportModal}
				initialRepositoryId={data.repository?.id}
			/>
		</>
	);
}
