"use client";

import { Button } from "@giselle-internal/ui/button";
import {
	Dialog,
	DialogBody,
	DialogClose,
	DialogContent,
	DialogDescription,
	DialogFooter,
	DialogHeader,
	DialogTitle,
	DialogTrigger,
} from "@giselle-internal/ui/dialog";
import { Select, type SelectOption } from "@giselle-internal/ui/select";
import { Toggle } from "@giselle-internal/ui/toggle";
import * as Tooltip from "@radix-ui/react-tooltip";
import { CircleDot, Code, GitPullRequest, Plus, X } from "lucide-react";
import { useCallback, useMemo, useState, useTransition } from "react";
import { GlassButton } from "@/components/ui/glass-button";
import type { GitHubRepositoryContentType } from "@/db";
import { GITHUB_EMBEDDING_PROFILES } from "./github-embedding-profiles";
import type { ActionResult, InstallationWithRepos } from "./types";

type RepositoryRegistrationDialogProps = {
	installationsWithRepos: InstallationWithRepos[];
	registerRepositoryIndexAction: (
		owner: string,
		repo: string,
		installationId: number,
		contentTypes: {
			contentType: GitHubRepositoryContentType;
			enabled: boolean;
		}[],
		embeddingProfileIds?: number[],
	) => Promise<ActionResult>;
	disabled?: boolean;
	disabledReason?: string;
};

export function RepositoryRegistrationDialog({
	installationsWithRepos,
	registerRepositoryIndexAction,
	disabled = false,
	disabledReason,
}: RepositoryRegistrationDialogProps) {
	const [isOpen, setIsOpen] = useState(false);
	const [ownerId, setOwnerId] = useState<string>("");
	const [repositoryId, setRepositoryId] = useState<string>("");
	const [error, setError] = useState("");
	const [isPending, startTransition] = useTransition();
	const [contentConfig, setContentConfig] = useState({
		code: { enabled: true },
		issues: { enabled: false },
		pullRequests: { enabled: false },
	});
	const [selectedProfiles, setSelectedProfiles] = useState<number[]>([1]); // Default to OpenAI Small

	const selectedInstallation = useMemo(
		() =>
			installationsWithRepos.find((i) => String(i.installation.id) === ownerId),
		[installationsWithRepos, ownerId],
	);
	const repositoryOptions = useMemo(
		() => selectedInstallation?.repositories || [],
		[selectedInstallation],
	);

	// Convert installations to SelectOption format
	const ownerOptions: SelectOption[] = useMemo(
		() =>
			installationsWithRepos.map(({ installation }) => ({
				value: String(installation.id),
				label: installation.name,
			})),
		[installationsWithRepos],
	);

	// Convert repositories to SelectOption format
	const repoSelectOptions: SelectOption[] = useMemo(
		() =>
			repositoryOptions.map((repo) => ({
				value: String(repo.id),
				label: repo.name,
			})),
		[repositoryOptions],
	);

	const handleOwnerChange = useCallback((value: string) => {
		setOwnerId(value);
		setRepositoryId("");
	}, []);

	const handleRepositoryChange = useCallback((value: string) => {
		setRepositoryId(value);
	}, []);

	const handleToggleCode = useCallback((enabled: boolean) => {
		setContentConfig((prev) => ({ ...prev, code: { enabled } }));
	}, []);

	const handleToggleIssues = useCallback((enabled: boolean) => {
		setContentConfig((prev) => ({ ...prev, issues: { enabled } }));
	}, []);
	const handleTogglePullRequests = useCallback((enabled: boolean) => {
		setContentConfig((prev) => ({ ...prev, pullRequests: { enabled } }));
	}, []);

	const handleSubmit = useCallback(
		(e: React.FormEvent) => {
			e.preventDefault();
			setError("");

			if (!ownerId) {
				setError("Owner is required");
				return;
			}
			if (!repositoryId) {
				setError("Repository is required");
				return;
			}

			startTransition(async () => {
				const selectedRepo = repositoryOptions.find(
					(r) => String(r.id) === repositoryId,
				);
				if (!selectedRepo) {
					setError("Repository not found");
					return;
				}
				const owner = selectedRepo.owner;
				const repo = selectedRepo.name;
				const contentTypes: {
					contentType: GitHubRepositoryContentType;
					enabled: boolean;
				}[] = [
					{ contentType: "blob", enabled: contentConfig.code.enabled },
					{ contentType: "issue", enabled: contentConfig.issues.enabled },
					{
						contentType: "pull_request",
						enabled: contentConfig.pullRequests.enabled,
					},
				];

				const result = await registerRepositoryIndexAction(
					owner,
					repo,
					Number(ownerId),
					contentTypes,
					selectedProfiles,
				);
				if (result.success) {
					setIsOpen(false);
					setOwnerId("");
					setRepositoryId("");
					setContentConfig({
						code: { enabled: true },
						issues: { enabled: false },
						pullRequests: { enabled: false },
					});
					setSelectedProfiles([1]); // Reset to default
				} else {
					setError(result.error);
				}
			});
		},
		[
			ownerId,
			repositoryId,
			repositoryOptions,
			contentConfig,
			selectedProfiles,
			registerRepositoryIndexAction,
		],
	);

	if (disabled) {
		const disabledButton = (
			<GlassButton
				className="cursor-not-allowed opacity-60"
				disabled
				type="button"
			>
				<span className="grid size-4 place-items-center rounded-full bg-primary-200 opacity-50">
					<Plus className="size-3 text-link-muted" />
				</span>
				Register Repository
			</GlassButton>
		);

		if (!disabledReason) {
			return disabledButton;
		}

		return (
			<Tooltip.Provider delayDuration={200}>
				<Tooltip.Root>
					<Tooltip.Trigger asChild>{disabledButton}</Tooltip.Trigger>
					<Tooltip.Portal>
						<Tooltip.Content
							side="bottom"
							className="z-50 max-w-xs rounded-md border border-border-muted bg-surface px-3 py-2 text-xs text-inverse shadow-lg"
						>
							{disabledReason}
							<Tooltip.Arrow style={{ fill: "var(--color-surface)" }} />
						</Tooltip.Content>
					</Tooltip.Portal>
				</Tooltip.Root>
			</Tooltip.Provider>
		);
	}

	return (
		<Dialog open={isOpen} onOpenChange={setIsOpen}>
			<DialogTrigger asChild>
				<GlassButton className="whitespace-nowrap">
					<span className="grid size-4 place-items-center rounded-full bg-primary-200 opacity-50">
						<Plus className="size-3 text-link-muted" />
					</span>
					Register Repository
				</GlassButton>
			</DialogTrigger>
			<DialogContent
				variant="glass"
				className="max-w-[600px]"
				onEscapeKeyDown={() => setIsOpen(false)}
				onPointerDownOutside={() => setIsOpen(false)}
			>
				<DialogHeader>
					<div className="flex items-center justify-between">
						<DialogTitle className="font-sans text-[20px] font-medium tracking-tight text-inverse">
							Register GitHub Repository
						</DialogTitle>
						<DialogClose
							onClick={() => setIsOpen(false)}
							className="rounded-sm text-inverse opacity-70 hover:opacity-100 focus:outline-none"
						>
							<X className="h-5 w-5" />
							<span className="sr-only">Close</span>
						</DialogClose>
					</div>
					<DialogDescription className="font-geist mt-2 text-[14px] text-text-muted">
						Add a GitHub repository to your Vector Store to use it in GitHub
						Vector Store Nodes.
					</DialogDescription>
				</DialogHeader>
				<DialogBody className="mt-4">
					<form
						id="register-repository-form"
						onSubmit={handleSubmit}
						className="space-y-4"
						noValidate
					>
						<div className="flex flex-col gap-y-2">
							<label
								htmlFor="owner"
								className="text-text text-[14px] leading-[16.8px] font-sans"
							>
								Owner / Organization
							</label>
							<div className="relative">
								<Select
									options={ownerOptions}
									placeholder="Select owner"
									value={ownerId}
									onValueChange={handleOwnerChange}
									disabled={isPending}
									triggerClassName="bg-surface text-text text-[14px] font-geist"
									id="owner"
								/>
							</div>
						</div>

						<div className="flex flex-col gap-y-2">
							<label
								htmlFor="repository"
								className="text-text text-[14px] leading-[16.8px] font-sans"
							>
								Repository Name
							</label>
							<div className="relative">
								<Select
									options={repoSelectOptions}
									placeholder={
										!ownerId
											? "Select owner first"
											: repositoryOptions.length === 0
												? "No repositories available"
												: "Select repository"
									}
									value={repositoryId}
									onValueChange={handleRepositoryChange}
									disabled={isPending || !ownerId}
									triggerClassName="bg-surface text-text text-[14px] font-geist"
									id="repository"
								/>
							</div>
						</div>

						{/* Sources to Ingest Section */}
						<div className="flex flex-col gap-y-2">
							<div className="text-text text-[14px] leading-[16.8px] font-sans">
								Sources to Ingest
							</div>

							<div className="grid grid-cols-2 gap-3">
								{/* Code Configuration */}
								<div className="bg-[color-mix(in_srgb,var(--color-text-inverse,#fff)_5%,transparent)] rounded-lg p-4">
									<Toggle
										name="code-toggle"
										checked={contentConfig.code.enabled}
										onCheckedChange={handleToggleCode}
										disabled={true}
									>
										<div className="flex-1 mr-3">
											<div className="flex items-center gap-2 mb-1">
												<Code size={18} className="text-text-muted" />
												<span className="text-text font-medium">Code</span>
											</div>
											<p className="text-xs text-text-muted">
												Ingest source code files from the repository
											</p>
											<p className="text-xs text-text-muted/60 mt-1">
												(Required - cannot be disabled)
											</p>
										</div>
									</Toggle>
								</div>

								{/* Issues Configuration */}
								<div className="bg-inverse/5 rounded-lg p-4">
									<Toggle
										name="issues-toggle"
										checked={contentConfig.issues.enabled}
										onCheckedChange={handleToggleIssues}
									>
										<div className="flex-1 mr-3">
											<div className="flex items-center gap-2 mb-1">
												<CircleDot size={18} className="text-text-muted" />
												<span className="text-text font-medium">Issues</span>
											</div>
											<p className="text-xs text-text-muted">
												Index issue titles, descriptions, and comments
											</p>
										</div>
									</Toggle>
								</div>

								{/* Pull Requests Configuration */}
								<div className="bg-[color-mix(in_srgb,var(--color-text-inverse,#fff)_5%,transparent)] rounded-lg p-4">
									<Toggle
										name="pull-requests-toggle"
										checked={contentConfig.pullRequests.enabled}
										onCheckedChange={handleTogglePullRequests}
									>
										<div className="flex-1 mr-3">
											<div className="flex items-center gap-2 mb-1">
												<GitPullRequest size={18} className="text-text-muted" />
												<span className="text-text font-medium">
													Pull Requests
												</span>
											</div>
											<p className="text-xs text-text-muted">
												Ingest merged pull request content and discussions
											</p>
										</div>
									</Toggle>
								</div>
							</div>

							{/* Embedding Profiles Section */}
							<div className="mt-4">
								<div className="text-text text-[14px] leading-[16.8px] font-sans mb-2">
									Embedding Models
								</div>
								<div className="text-text-muted text-[12px] mb-3">
									Select at least one embedding model for indexing
								</div>
								<div className="space-y-2">
									{Object.entries(GITHUB_EMBEDDING_PROFILES).map(
										([id, profile]) => {
											const profileId = Number(id);
											const isSelected = selectedProfiles.includes(profileId);
											const isLastOne =
												selectedProfiles.length === 1 && isSelected;

											return (
												<label
													key={profileId}
													className="flex items-start gap-3 p-3 rounded-lg border border-border-muted hover:bg-[color-mix(in_srgb,var(--color-text-inverse,#fff)_5%,transparent)] transition-colors cursor-pointer"
												>
													<input
														type="checkbox"
														checked={isSelected}
														disabled={isPending || isLastOne}
														onChange={(e) => {
															if (e.target.checked) {
																setSelectedProfiles([
																	...selectedProfiles,
																	profileId,
																]);
															} else {
																setSelectedProfiles(
																	selectedProfiles.filter(
																		(id) => id !== profileId,
																	),
																);
															}
														}}
														className="mt-1 w-4 h-4 text-[#1663F3] bg-surface border-border rounded focus:ring-[#1663F3]/20"
													/>
													<div className="flex-1">
														<div className="text-text text-[14px] font-medium">
															{profile.name}
														</div>
														<div className="text-text-muted text-[12px] mt-1">
															Provider: {profile.provider} • Dimensions{" "}
															{profile.dimensions}
														</div>
													</div>
												</label>
											);
										},
									)}
								</div>
							</div>
						</div>

						{error && (
							<div className="mt-1 text-sm text-error-900">{error}</div>
						)}
					</form>
				</DialogBody>
				<DialogFooter>
					<div className="mt-6 flex justify-end gap-x-3">
						<Button
							type="button"
							variant="link"
							size="large"
							onClick={() => setIsOpen(false)}
							disabled={isPending}
							aria-label="Cancel"
						>
							Cancel
						</Button>
						<Button
							type="button"
							variant="primary"
							size="large"
							onClick={() => {
								const form = document.getElementById(
									"register-repository-form",
								) as HTMLFormElement | null;
								if (!form) return;
								if (typeof form.requestSubmit === "function") {
									form.requestSubmit();
								} else {
									form.submit();
								}
							}}
							disabled={isPending}
							aria-label="Register"
						>
							{isPending ? "Processing..." : "Register"}
						</Button>
					</div>
				</DialogFooter>
			</DialogContent>
		</Dialog>
	);
}
