import { useState, useEffect } from "react";
import { Icon } from "../../icon";
import {
	createInstance,
	startInstance,
	type ToolInstance,
} from "../../../api/sessions";
import type { Project } from "../../../types";
import {
	listRepositoryBranches,
	type GitRepository,
	type Branch,
} from "../../../api/git-repositories";
import type { ToolType } from "../../../api/tool-types";
import { listSSHKeys, type SSHKey } from "../../../api/ssh-keys";
import {
	listConfigProfiles,
	type ConfigProfile,
} from "../../../api/config-profiles";

interface CreateSessionFormProps {
	projects: Project[];
	repositories: GitRepository[];
	toolTypes: ToolType[];
	fixedProjectId?: string;
	fixedRepoId?: string;
	projectName?: string;
	repoName?: string;
	showCloneMode?: boolean;
	showFixedFields?: boolean;
	onProjectChange?: (projectId: string) => void;
	onSuccess?: (instance: ToolInstance) => void;
	onCancel?: () => void;
	submitLabel?: string;
	className?: string;
}

export const CreateSessionForm = ({
	projects,
	repositories,
	toolTypes,
	fixedProjectId,
	fixedRepoId,
	projectName,
	repoName,
	showCloneMode = true,
	showFixedFields = true,
	onProjectChange,
	onSuccess,
	onCancel,
	submitLabel = "Create Session",
	className = "",
}: CreateSessionFormProps) => {
	const [selectedProject, setSelectedProject] = useState(fixedProjectId || "");
	const [selectedRepo, setSelectedRepo] = useState(fixedRepoId || "");
	const [selectedToolType, setSelectedToolType] = useState("");
	const [displayName, setDisplayName] = useState("");
	const [cloneMode, setCloneMode] = useState<"mount" | "clone">("mount");
	const [branch, setBranch] = useState("main");
	const [sshKeys, setSshKeys] = useState<SSHKey[]>([]);
	const [configProfiles, setConfigProfiles] = useState<ConfigProfile[]>([]);
	const [selectedConfigProfile, setSelectedConfigProfile] = useState("");
	const [selectedSshKeyIds, setSelectedSshKeyIds] = useState<string[]>([]);

	const [branches, setBranches] = useState<Branch[]>([]);
	const [isLoadingBranches, setIsLoadingBranches] = useState(false);
	const [isCreatingNewBranch, setIsCreatingNewBranch] = useState(false);
	const [newBranchName, setNewBranchName] = useState("");
	const [baseBranch, setBaseBranch] = useState("");

	const [isSubmitting, setIsSubmitting] = useState(false);
	const [error, setError] = useState<string | null>(null);

	// Load SSH keys
	useEffect(() => {
		const loadKeys = async () => {
			try {
				const keys = await listSSHKeys();
				setSshKeys(keys);
			} catch {
				// ignore
			}
		};
		void loadKeys();
	}, []);

	// Load config profiles when tool type is selected
	useEffect(() => {
		const projectId = fixedProjectId || selectedProject;
		if (!selectedToolType || !projectId) {
			setConfigProfiles([]);
			setSelectedConfigProfile("");
			return;
		}
		const loadProfiles = async () => {
			try {
				const profiles = await listConfigProfiles(projectId, selectedToolType);
				setConfigProfiles(profiles);
				// Auto-select default if available
				const defaultProfile = profiles.find((p) => p.is_default);
				if (defaultProfile) {
					setSelectedConfigProfile(defaultProfile.id);
				}
			} catch {
				// ignore
			}
		};
		void loadProfiles();
	}, [selectedToolType, selectedProject, fixedProjectId]);

	// Load branches when selected repo changes
	useEffect(() => {
		const projectId = fixedProjectId || selectedProject;
		if (!selectedRepo || !projectId || !showCloneMode) {
			setBranches([]);
			return;
		}
		const loadBranches = async () => {
			setIsLoadingBranches(true);
			try {
				const response = await listRepositoryBranches(projectId, selectedRepo);
				setBranches(response.branches);
				if (response.default_branch) {
					setBranch(response.default_branch);
					setBaseBranch(response.default_branch);
				}
			} catch {
				// ignore
			} finally {
				setIsLoadingBranches(false);
			}
		};
		void loadBranches();
	}, [selectedRepo, selectedProject, fixedProjectId, showCloneMode]);

	// Filter repositories by selected project
	const availableRepos = selectedProject
		? repositories.filter((r) => r.project_id === selectedProject)
		: [];

	const resetForm = () => {
		if (!fixedProjectId) setSelectedProject("");
		if (!fixedRepoId) setSelectedRepo("");
		setSelectedToolType("");
		setDisplayName("");
		setCloneMode("mount");
		setBranch("main");
		setIsCreatingNewBranch(false);
		setNewBranchName("");
		setBaseBranch("");
		setBranches([]);
		setSelectedSshKeyIds([]);
		setSelectedConfigProfile("");
	};

	const handleSubmit = async (event: React.FormEvent) => {
		event.preventDefault();
		setError(null);

		const projectId = fixedProjectId || selectedProject;
		const repoId = fixedRepoId || selectedRepo;

		if (!projectId || !repoId || !selectedToolType) {
			setError("Project, repository, and tool type are required");
			return;
		}

		if (showCloneMode && cloneMode === "clone") {
			const repo = repositories.find((r) => r.id === repoId);
			if (!repo?.ssh_key_id) {
				setError("Repository must have an SSH key assigned for clone mode");
				return;
			}
		}

		setIsSubmitting(true);

		try {
			const instance = await createInstance(
				projectId,
				repoId,
				selectedToolType,
				displayName || undefined,
				showCloneMode ? cloneMode : undefined,
				showCloneMode && cloneMode === "clone"
					? isCreatingNewBranch
						? baseBranch
						: branch
					: undefined,
				showCloneMode && cloneMode === "clone" && isCreatingNewBranch
					? newBranchName
					: undefined,
				selectedConfigProfile || undefined,
				selectedSshKeyIds.length > 0 ? selectedSshKeyIds : undefined,
			);

			await startInstance(
				projectId,
				repoId,
				instance.id,
				selectedConfigProfile || undefined,
				selectedSshKeyIds.length > 0 ? selectedSshKeyIds : undefined,
			);

			resetForm();
			onSuccess?.(instance);
		} catch {
			setError("Failed to create session");
		} finally {
			setIsSubmitting(false);
		}
	};

	const hasProject = !!(fixedProjectId || selectedProject);
	const hasRepo = !!(fixedRepoId || selectedRepo);
	const hasToolType = !!selectedToolType;

	return (
		<div className={`create-session-form-wrapper ${className}`}>
			<form onSubmit={handleSubmit} className="stack create-session-form">
				{/* Project */}
				<div className="form-field">
					<label>Project</label>
					{fixedProjectId && showFixedFields ? (
						<input
							type="text"
							value={
								projectName ||
								projects.find((p) => p.id === fixedProjectId)?.name ||
								""
							}
							disabled
							readOnly
						/>
					) : (
						<select
							value={selectedProject}
							onChange={(e) => {
								const value = e.target.value;
								setSelectedProject(value);
								setSelectedRepo("");
								setSelectedToolType("");
								setCloneMode("mount");
								setIsCreatingNewBranch(false);
								onProjectChange?.(value);
							}}
							disabled={isSubmitting}
						>
							<option value="">Select project...</option>
							{projects.map((p) => (
								<option key={p.id} value={p.id}>
									{p.name}
								</option>
							))}
						</select>
					)}
				</div>

				{/* Repository */}
				{hasProject && (
					<div className="form-field">
						<label>Repository</label>
						{fixedRepoId && showFixedFields ? (
							<input
								type="text"
								value={
									repoName ||
									repositories.find((r) => r.id === fixedRepoId)?.name ||
									""
								}
								disabled
								readOnly
							/>
						) : (
							<select
								value={selectedRepo}
								onChange={(e) => {
									setSelectedRepo(e.target.value);
									setSelectedToolType("");
									setCloneMode("mount");
									setIsCreatingNewBranch(false);
								}}
								disabled={!hasProject || isSubmitting}
							>
								<option value="">Select repository...</option>
								{availableRepos.map((r) => (
									<option key={r.id} value={r.id}>
										{r.name}
									</option>
								))}
							</select>
						)}
					</div>
				)}

				{/* Tool Type */}
				{hasRepo && (
					<div className="form-field">
						<label>Tool</label>
						<select
							value={selectedToolType}
							onChange={(e) => {
								setSelectedToolType(e.target.value);
								setCloneMode("mount");
								setIsCreatingNewBranch(false);
							}}
							disabled={!hasRepo || isSubmitting}
						>
							<option value="">Select tool...</option>
							{toolTypes.map((t) => (
								<option key={t.id} value={t.id}>
									{t.display_name}
								</option>
							))}
						</select>
					</div>
				)}

				{/* Config Profile */}
				{hasToolType && (
					<div className="form-field">
						<label>Config Profile (optional)</label>
						<select
							value={selectedConfigProfile}
							onChange={(e) => setSelectedConfigProfile(e.target.value)}
							disabled={!hasToolType || isSubmitting}
						>
							<option value="">No profile (use tool defaults)</option>
							{configProfiles.map((p) => (
								<option key={p.id} value={p.id}>
									{p.name} {p.is_default ? "(default)" : ""}
								</option>
							))}
						</select>
					</div>
				)}

				{/* SSH Keys */}
				{hasToolType && (
					<div className="form-field">
						<label>SSH Keys (optional)</label>
						<div style={{ display: "flex", flexWrap: "wrap", gap: "0.5rem" }}>
							{sshKeys.length === 0 && (
								<span className="muted">No SSH keys configured.</span>
							)}
							{sshKeys.map((key) => (
								<label
									key={key.id}
									className="checkbox-label"
									style={{
										display: "flex",
										alignItems: "center",
										gap: "0.25rem",
										padding: "0.375rem 0.75rem",
										background: "var(--panel)",
										borderRadius: "0.375rem",
										border: "1px solid var(--border)",
										cursor: "pointer",
									}}
								>
									<input
										type="checkbox"
										checked={selectedSshKeyIds.includes(key.id)}
										onChange={(e) => {
											if (e.target.checked) {
												setSelectedSshKeyIds((prev) => [...prev, key.id]);
											} else {
												setSelectedSshKeyIds((prev) =>
													prev.filter((id) => id !== key.id),
												);
											}
										}}
										disabled={isSubmitting}
									/>
									{key.name}
								</label>
							))}
						</div>
						<div className="hint" style={{ marginTop: "0.5rem" }}>
							Selected keys will be mounted into the container at ~/.ssh
						</div>
					</div>
				)}

				{/* Clone Mode & Branch */}
				{showCloneMode && hasToolType && (
					<div className="form-field">
						<label>Repository Access</label>
						<div className="radio-group">
							<label className="radio-label">
								<input
									type="radio"
									name="cloneMode"
									value="mount"
									checked={cloneMode === "mount"}
									onChange={(e) => {
										setCloneMode(e.target.value as "mount" | "clone");
										setIsCreatingNewBranch(false);
									}}
									disabled={isSubmitting}
								/>
								Mount (live sync)
							</label>
							<label className="radio-label">
								<input
									type="radio"
									name="cloneMode"
									value="clone"
									checked={cloneMode === "clone"}
									onChange={(e) => {
										setCloneMode(e.target.value as "mount" | "clone");
										setIsCreatingNewBranch(false);
									}}
									disabled={isSubmitting}
								/>
								Clone fresh copy
							</label>
						</div>

						{cloneMode === "clone" && (
							<>
								<label className="form-field">
									Branch
									{isLoadingBranches ? (
										<span className="muted">Loading branches...</span>
									) : (
										<select
											value={isCreatingNewBranch ? "__new__" : branch}
											onChange={(e) => {
												const value = e.target.value;
												if (value === "__new__") {
													setIsCreatingNewBranch(true);
													setNewBranchName("");
												} else {
													setIsCreatingNewBranch(false);
													setBranch(value);
													setBaseBranch(value);
												}
											}}
											disabled={isSubmitting}
										>
											{branches.map((b) => (
												<option key={b.name} value={b.name}>
													{b.name} {b.is_default ? "(default)" : ""}
												</option>
											))}
											<option value="__new__">Create new branch...</option>
										</select>
									)}
								</label>

								{isCreatingNewBranch && (
									<>
										<label className="form-field">
											New Branch Name
											<input
												type="text"
												value={newBranchName}
												onChange={(e) => setNewBranchName(e.target.value)}
												placeholder="feature/my-new-branch"
												required
												disabled={isSubmitting}
											/>
										</label>
										<label className="form-field">
											Base Branch
											<select
												value={baseBranch}
												onChange={(e) => setBaseBranch(e.target.value)}
												disabled={isSubmitting}
											>
												{branches.map((b) => (
													<option key={b.name} value={b.name}>
														{b.name} {b.is_default ? "(default)" : ""}
													</option>
												))}
											</select>
										</label>
									</>
								)}

								{selectedRepo && (
									<div className="form-field ssh-key-info">
										{(() => {
											const repo = repositories.find(
												(r) => r.id === selectedRepo,
											);
											if (!repo) return null;
											if (repo.ssh_key_id) {
												const key = sshKeys.find(
													(k) => k.id === repo.ssh_key_id,
												);
												return (
													<span className="success-text">
														SSH key: {key?.name || "Assigned"}
													</span>
												);
											}
											return (
												<span className="warning-text">
													No SSH key assigned to this repository. Clone mode
													requires an SSH key.
												</span>
											);
										})()}
									</div>
								)}
							</>
						)}
					</div>
				)}

				{/* Display Name */}
				{hasToolType && (
					<div className="form-field">
						<label>Display Name (optional)</label>
						<input
							type="text"
							value={displayName}
							onChange={(e) => setDisplayName(e.target.value)}
							placeholder="My Development Environment"
							disabled={isSubmitting}
						/>
					</div>
				)}

				{/* Error & Submit */}
				{error && <p className="error-text">{error}</p>}

				{hasToolType && (
					<div className="form-actions">
						{onCancel && (
							<button
								className="secondary-button"
								type="button"
								onClick={onCancel}
								disabled={isSubmitting}
							>
								Cancel
							</button>
						)}
						<button
							className="primary-button"
							type="submit"
							disabled={isSubmitting}
						>
							{isSubmitting ? (
								<>
									<Icon name="loading" size="sm" />
									Creating...
								</>
							) : (
								<>
									<Icon name="add" size="sm" />
									{submitLabel}
								</>
							)}
						</button>
					</div>
				)}
			</form>
		</div>
	);
};
