/** Projects page with inline repositories and workspaces. */

import { useState } from "react";

import {
	createProject,
	deleteProject,
	listProjects,
	updateProject,
	type ProjectCreateInput,
	type ProjectUpdateInput,
} from "../api/projects";
import { deleteWorkspace, syncWorkspace } from "../api/workspaces";
import {
	EmptyState,
	ErrorState,
	LoadingState,
} from "../components/data-states";
import { Icon } from "../components/icon";
import { WorkspaceCreateForm } from "../components/workspace-create-form";
import { useAsyncData } from "../hooks/use-async-data";
import type { ProjectWithRepos, WorkspaceSummary } from "../types";

type DialogMode = "none" | "create" | "edit";

export const ProjectsPage = () => {
	const {
		data: projects,
		status,
		reload,
	} = useAsyncData<ProjectWithRepos[]>(listProjects, []);
	const [dialogMode, setDialogMode] = useState<DialogMode>("none");
	const [editingProject, setEditingProject] = useState<ProjectWithRepos | null>(
		null,
	);
	const [formName, setFormName] = useState("");
	const [formDescription, setFormDescription] = useState("");
	const [formError, setFormError] = useState<string | null>(null);
	const [deleteConfirmId, setDeleteConfirmId] = useState<string | null>(null);
	const [expandedProject, setExpandedProject] = useState<string | null>(null);
	const [creatingWorkspace, setCreatingWorkspace] = useState<{
		projectId: string;
		repoId: string;
	} | null>(null);
	const [workspaceLoading, setWorkspaceLoading] = useState<string | null>(null);

	const safeProjects = projects ?? [];

	const openCreate = () => {
		setFormName("");
		setFormDescription("");
		setFormError(null);
		setEditingProject(null);
		setDialogMode("create");
	};

	const openEdit = (project: ProjectWithRepos) => {
		setFormName(project.name);
		setFormDescription(project.description ?? "");
		setFormError(null);
		setEditingProject(project);
		setDialogMode("edit");
	};

	const closeDialog = () => {
		setDialogMode("none");
		setEditingProject(null);
		setFormError(null);
	};

	const handleSubmit = async (e: React.FormEvent) => {
		e.preventDefault();
		setFormError(null);

		if (!formName.trim()) {
			setFormError("Project name is required");
			return;
		}

		try {
			if (dialogMode === "create") {
				const input: ProjectCreateInput = {
					name: formName.trim(),
					description: formDescription.trim() || null,
				};
				await createProject(input);
			} else if (dialogMode === "edit" && editingProject) {
				const input: ProjectUpdateInput = {
					name: formName.trim(),
					description: formDescription.trim() || null,
				};
				await updateProject(editingProject.id, input);
			}
			closeDialog();
			reload();
		} catch {
			setFormError("Failed to save project");
		}
	};

	const handleDelete = async (projectId: string) => {
		try {
			await deleteProject(projectId);
			setDeleteConfirmId(null);
			reload();
		} catch {
			setDeleteConfirmId(null);
		}
	};

	const handleSyncWorkspace = async (
		projectId: string,
		repoId: string,
		workspace: WorkspaceSummary,
	) => {
		setWorkspaceLoading(workspace.id);
		try {
			await syncWorkspace(projectId, repoId, workspace.id);
			reload();
		} catch (err) {
			alert(err instanceof Error ? err.message : "Failed to sync workspace");
		} finally {
			setWorkspaceLoading(null);
		}
	};

	const handleDeleteWorkspace = async (workspace: WorkspaceSummary) => {
		if (!confirm(`Delete workspace "${workspace.name}"?`)) return;
		setWorkspaceLoading(workspace.id);
		try {
			await deleteWorkspace(workspace.id);
			reload();
		} catch (err) {
			alert(err instanceof Error ? err.message : "Failed to delete workspace");
		} finally {
			setWorkspaceLoading(null);
		}
	};

	const isEmpty = status === "ready" && safeProjects.length === 0;

	return (
		<section className="stack">
			<div className="page-header">
				<h1>Projects</h1>
				<button className="primary-button" onClick={openCreate} type="button">
					<Icon name="add" size="sm" />
					New Project
				</button>
			</div>

			{status === "loading" && <LoadingState message="Loading projects..." />}

			{status === "error" && (
				<ErrorState message="Failed to load projects" onRetry={reload} />
			)}

			{isEmpty && (
				<EmptyState message="No projects yet. Create your first project above." />
			)}

			{status === "ready" && safeProjects.length > 0 && (
				<div className="project-list">
					{safeProjects.map((project) => (
						<ProjectCard
							key={project.id}
							project={project}
							expanded={expandedProject === project.id}
							onToggle={() =>
								setExpandedProject(
									expandedProject === project.id ? null : project.id,
								)
							}
							onEdit={() => openEdit(project)}
							onDelete={() => setDeleteConfirmId(project.id)}
							deleteConfirm={deleteConfirmId === project.id}
							onConfirmDelete={() => void handleDelete(project.id)}
							onCancelDelete={() => setDeleteConfirmId(null)}
							onCreateWorkspace={(repoId) =>
								setCreatingWorkspace({ projectId: project.id, repoId })
							}
							onWorkspaceAction={(repoId, workspace, action) => {
								if (action === "sync") {
									void handleSyncWorkspace(project.id, repoId, workspace);
								} else if (action === "delete") {
									void handleDeleteWorkspace(workspace);
								}
							}}
							workspaceLoading={workspaceLoading}
							showCreateForm={
								creatingWorkspace?.projectId === project.id
									? creatingWorkspace.repoId
									: null
							}
							onCancelCreate={() => setCreatingWorkspace(null)}
							onCreated={() => {
								setCreatingWorkspace(null);
								reload();
							}}
						/>
					))}
				</div>
			)}

			{dialogMode !== "none" && (
				<div className="dialog-overlay" role="dialog" aria-modal="true">
					<div className="dialog">
						<h2>
							{dialogMode === "create" ? "Create Project" : "Edit Project"}
						</h2>
						<form onSubmit={handleSubmit} className="stack">
							<label className="form-field">
								Name
								<input
									type="text"
									value={formName}
									onChange={(e) => setFormName(e.target.value)}
									placeholder="Project name"
								/>
							</label>
							<label className="form-field">
								Description
								<textarea
									value={formDescription}
									onChange={(e) => setFormDescription(e.target.value)}
									placeholder="Optional description"
									rows={3}
								/>
							</label>
							{formError && <p className="error-text">{formError}</p>}
							<div className="dialog-actions">
								<button
									className="secondary-button"
									onClick={closeDialog}
									type="button"
								>
									<Icon name="cancel" size="sm" />
									Cancel
								</button>
								<button className="primary-button" type="submit">
									{dialogMode === "create" ? (
										<>
											<Icon name="add" size="sm" />
											Create
										</>
									) : (
										<>
											<Icon name="save" size="sm" />
											Save
										</>
									)}
								</button>
							</div>
						</form>
					</div>
				</div>
			)}
		</section>
	);
};

/* ─── Project Card ─── */

function ProjectCard({
	project,
	expanded,
	onToggle,
	onEdit,
	onDelete,
	deleteConfirm,
	onConfirmDelete,
	onCancelDelete,
	onCreateWorkspace,
	onWorkspaceAction,
	workspaceLoading,
	showCreateForm,
	onCancelCreate,
	onCreated,
}: {
	project: ProjectWithRepos;
	expanded: boolean;
	onToggle: () => void;
	onEdit: () => void;
	onDelete: () => void;
	deleteConfirm: boolean;
	onConfirmDelete: () => void;
	onCancelDelete: () => void;
	onCreateWorkspace: (repoId: string) => void;
	onWorkspaceAction: (
		repoId: string,
		workspace: WorkspaceSummary,
		action: "sync" | "delete",
	) => void;
	workspaceLoading: string | null;
	onCancelCreate: () => void;
	showCreateForm: string | null;
	onCreated: () => void;
}) {
	return (
		<article className="card project-card">
			<div className="project-info-row">
				<button
					className="project-toggle"
					onClick={onToggle}
					type="button"
					aria-expanded={expanded}
				>
					<Icon name={expanded ? "chevron-down" : "chevron-right"} size="sm" />
					<h3>{project.name}</h3>
					{project.repositories.length > 0 && (
						<span className="repo-count">
							{project.repositories.length} repo
							{project.repositories.length > 1 ? "s" : ""}
						</span>
					)}
				</button>
				<div className="project-actions">
					<button className="ghost-button" onClick={onEdit} type="button">
						<Icon name="edit" size="sm" />
						Edit
					</button>
					{deleteConfirm ? (
						<div className="delete-confirm">
							<span>Are you sure?</span>
							<button
								className="danger-button"
								onClick={onConfirmDelete}
								type="button"
							>
								<Icon name="delete" size="sm" />
								Delete
							</button>
							<button
								className="ghost-button"
								onClick={onCancelDelete}
								type="button"
							>
								<Icon name="cancel" size="sm" />
								Cancel
							</button>
						</div>
					) : (
						<button
							className="ghost-button danger-text"
							onClick={onDelete}
							type="button"
						>
							<Icon name="delete" size="sm" />
							Delete
						</button>
					)}
				</div>
			</div>

			{expanded && (
				<div className="project-detail">
					{project.repositories.length === 0 ? (
						<p className="muted">No repositories yet.</p>
					) : (
						<div className="repo-list">
							{project.repositories.map((repo) => (
								<div key={repo.id} className="repo-block">
									<div className="repo-header">
										<h4>{repo.name}</h4>
										<button
											className="btn btn-sm btn-primary"
											onClick={() => onCreateWorkspace(repo.id)}
											type="button"
										>
											<Icon name="add" size="sm" /> New Workspace
										</button>
									</div>
									{showCreateForm === repo.id && (
										<WorkspaceCreateForm
											defaultProjectId={project.id}
											defaultRepoId={repo.id}
											onSubmit={onCreated}
											onCancel={onCancelCreate}
										/>
									)}
									{repo.workspaces.length === 0 ? (
										<p className="muted">No workspaces.</p>
									) : (
										<div className="workspace-grid">
											{repo.workspaces.map((ws) => (
												<div
													key={ws.id}
													className={`workspace-chip ${ws.status}`}
												>
													<a href={`/workspaces/${ws.id}`}>{ws.name}</a>
													<span className="ws-branch">
														<Icon name="branch" size="sm" /> {ws.branch}
													</span>
													{ws.instance_count > 0 && (
														<span className="ws-instances">
															{ws.instance_count} tool
															{ws.instance_count > 1 ? "s" : ""}
														</span>
													)}
													<div className="ws-actions">
														<button
															type="button"
															disabled={workspaceLoading === ws.id}
															onClick={() =>
																onWorkspaceAction(repo.id, ws, "sync")
															}
														>
															<Icon name="refresh" size="sm" />
														</button>
														<button
															type="button"
															className="danger-text"
															disabled={workspaceLoading === ws.id}
															onClick={() =>
																onWorkspaceAction(repo.id, ws, "delete")
															}
														>
															<Icon name="delete" size="sm" />
														</button>
													</div>
												</div>
											))}
										</div>
									)}
								</div>
							))}
						</div>
					)}
				</div>
			)}
		</article>
	);
}
