import { useCallback, useEffect, useState } from "react";
import { Link, useParams, useSearchParams } from "react-router-dom";

import { apiClient } from "../api/client";
import type { GitRepository } from "../types/git-repository";
import type { ToolType } from "../types/tool-type";
import {
	getRepositoryStatus,
	listRepositories,
	type GitStatus,
} from "../api/git-repositories";
import { WorkspaceSidebar } from "../components/features/git";
import { FileEditor } from "../components/features/git/FileEditor";
import { WorkspaceHeader } from "../components/features/workspace/WorkspaceHeader";
import { GitToolbar } from "../components/features/git/GitToolbar";
import { LoadingState, ErrorState } from "../components/ui";
import { listToolTypes } from "../api/tool-types";

type WorkspaceStatus = "loading" | "ready" | "error" | "empty";

interface Project {
	id: string;
	name: string;
	description?: string | null;
}

export const RepoWorkspace = () => {
	const { projectId } = useParams<{ projectId: string }>();
	const [searchParams, setSearchParams] = useSearchParams();

	const [status, setStatus] = useState<WorkspaceStatus>("loading");
	const [project, setProject] = useState<Project | null>(null);
	const [repositories, setRepositories] = useState<GitRepository[]>([]);
	const [selectedRepoId, setSelectedRepoId] = useState<string | null>(
		searchParams.get("repo"),
	);
	const [branches, setBranches] = useState<string[]>([]);
	const [currentBranch, setCurrentBranch] = useState<string>("main");
	const [gitStatus, setGitStatus] = useState<GitStatus | null>(null);
	const [toolTypes, setToolTypes] = useState<ToolType[]>([]);

	const loadProject = useCallback(async () => {
		if (!projectId) return;
		try {
			const response = await apiClient.get(`/projects/${projectId}`);
			setProject(response.data);
		} catch {
			setProject(null);
		}
	}, [projectId]);

	const loadRepositories = useCallback(async () => {
		if (!projectId) return;
		setStatus("loading");
		try {
			const data = await listRepositories(projectId);
			setRepositories(data);
			if (data.length === 0) {
				setStatus("empty");
			} else {
				setStatus("ready");
				if (!selectedRepoId) {
					setSelectedRepoId(data[0].id);
					const newParams = new URLSearchParams(searchParams);
					newParams.set("repo", data[0].id);
					setSearchParams(newParams, { replace: true });
				}
			}
		} catch {
			setRepositories([]);
			setStatus("error");
		}
	}, [projectId, selectedRepoId, searchParams, setSearchParams]);

	const loadBranches = useCallback(async () => {
		if (!projectId || !selectedRepoId) return;
		try {
			const response = await apiClient.get(
				`/projects/${projectId}/repositories/${selectedRepoId}/branches`,
			);
			const branchList = response.data.branches.map(
				(b: { name: string }) => b.name,
			);
			setBranches(branchList);
			const defaultBranch = response.data.default_branch;
			if (defaultBranch) setCurrentBranch(defaultBranch);
		} catch {
			setBranches([]);
		}
	}, [projectId, selectedRepoId]);

	const loadGitStatus = useCallback(async () => {
		if (!projectId || !selectedRepoId) return;
		try {
			const data = await getRepositoryStatus(projectId, selectedRepoId);
			setGitStatus(data);
		} catch {
			setGitStatus(null);
		}
	}, [projectId, selectedRepoId]);

	const loadToolTypes = useCallback(async () => {
		try {
			const data = await listToolTypes();
			setToolTypes(data);
		} catch {
			setToolTypes([]);
		}
	}, []);

	useEffect(() => {
		void loadProject();
		void loadRepositories();
		void loadToolTypes();
	}, [loadProject, loadRepositories, loadToolTypes]);

	useEffect(() => {
		void loadBranches();
		void loadGitStatus();
	}, [loadBranches, loadGitStatus]);

	const handleRepoChange = (repoId: string) => {
		setSelectedRepoId(repoId);
		const newParams = new URLSearchParams(searchParams);
		newParams.set("repo", repoId);
		newParams.delete("branch");
		newParams.delete("path");
		setSearchParams(newParams);
	};

	const selectedRepo = repositories.find((r) => r.id === selectedRepoId);

	return (
		<section className="repo-workspace">
			{project && (
				<WorkspaceHeader project={project} currentRepo={selectedRepo || null} />
			)}

			{status === "loading" && (
				<LoadingState message="Loading repositories..." />
			)}

			{status === "error" && (
				<ErrorState
					message="Failed to load repositories"
					onRetry={() => void loadRepositories()}
				/>
			)}

			{status === "empty" && (
				<div className="card stack">
					<p>No repositories in this project yet.</p>
					<Link
						className="primary-button"
						to={`/projects/${projectId}/settings/repositories`}
					>
						Manage Repositories
					</Link>
				</div>
			)}

			{status === "ready" && repositories.length > 0 && (
				<>
					{selectedRepoId && (
						<GitToolbar
							projectId={projectId!}
							repoId={selectedRepoId}
							currentBranch={currentBranch}
							branches={branches}
							hasRemote={Boolean(selectedRepo?.remote_url)}
							onBranchChange={(branch) => {
								setCurrentBranch(branch);
								const newParams = new URLSearchParams(searchParams);
								newParams.set("branch", branch);
								setSearchParams(newParams);
							}}
							onRefresh={() => {
								void loadBranches();
								void loadGitStatus();
								window.dispatchEvent(new CustomEvent("refresh-file-tree"));
							}}
						/>
					)}
					<div className="workspace-layout">
						{selectedRepoId && (
							<WorkspaceSidebar
								projectId={projectId!}
								repoId={selectedRepoId}
								repositories={repositories}
								gitStatus={gitStatus}
								toolTypes={toolTypes}
								onRepoChange={handleRepoChange}
								onCommit={() => {
									void loadGitStatus();
									window.dispatchEvent(new CustomEvent("refresh-file-tree"));
								}}
							/>
						)}
						<main className="workspace-main">
							{selectedRepoId && (
								<FileEditor projectId={projectId!} repoId={selectedRepoId} gitStatus={gitStatus} />
							)}
						</main>
					</div>
				</>
			)}
		</section>
	);
};
