import * as React from "react";
import type { ProjectSettings } from "../api/settings";
import { settingsApi } from "../api/settings";

const { useState, useEffect } = React;

interface SettingsPageProps {
	onBack: () => void;
}

const fieldStyle: React.CSSProperties = {
	display: "flex",
	flexDirection: "column",
	gap: "4px",
};

const labelStyle: React.CSSProperties = {
	fontSize: "0.8em",
	color: "#aaa",
	fontWeight: 500,
};

const descStyle: React.CSSProperties = {
	fontSize: "0.75em",
	color: "#666",
	marginTop: "2px",
};

const inputStyle: React.CSSProperties = {
	padding: "8px 10px",
	borderRadius: "6px",
	border: "1px solid #333",
	background: "#1e1e1e",
	color: "#ececec",
	fontSize: "0.9em",
	fontFamily: "monospace",
	outline: "none",
};

const sectionStyle: React.CSSProperties = {
	background: "#1e1e1e",
	border: "1px solid #333",
	borderRadius: "8px",
	padding: "20px",
	display: "flex",
	flexDirection: "column",
	gap: "16px",
};

const sectionTitleStyle: React.CSSProperties = {
	fontSize: "0.85em",
	fontWeight: 600,
	color: "#aaa",
	textTransform: "uppercase",
	letterSpacing: "0.06em",
	marginBottom: "2px",
};

interface TextFieldProps {
	label: string;
	description?: string;
	value: string;
	onChange: (v: string) => void;
	placeholder?: string;
}

function TextField({
	label,
	description,
	value,
	onChange,
	placeholder,
}: TextFieldProps) {
	return (
		<div style={fieldStyle}>
			<label style={labelStyle}>{label}</label>
			{description && <span style={descStyle}>{description}</span>}
			<input
				type="text"
				value={value}
				onChange={(e) => onChange(e.target.value)}
				placeholder={placeholder ?? ""}
				style={inputStyle}
				autoComplete="off"
			/>
		</div>
	);
}

interface NumberFieldProps {
	label: string;
	description?: string;
	value: number | null;
	onChange: (v: number | null) => void;
	min?: number;
	placeholder?: string;
}

function NumberField({
	label,
	description,
	value,
	onChange,
	min,
	placeholder,
}: NumberFieldProps) {
	return (
		<div style={fieldStyle}>
			<label style={labelStyle}>{label}</label>
			{description && <span style={descStyle}>{description}</span>}
			<input
				type="number"
				value={value === null ? "" : value}
				min={min}
				onChange={(e) => {
					const raw = e.target.value.trim();
					if (raw === "") {
						onChange(null);
					} else {
						const n = Number(raw);
						if (!Number.isNaN(n)) onChange(n);
					}
				}}
				placeholder={placeholder ?? ""}
				style={inputStyle}
			/>
		</div>
	);
}

interface CheckboxFieldProps {
	label: string;
	description?: string;
	checked: boolean;
	onChange: (v: boolean) => void;
}

function CheckboxField({
	label,
	description,
	checked,
	onChange,
}: CheckboxFieldProps) {
	return (
		<div style={fieldStyle}>
			{description && <span style={descStyle}>{description}</span>}
			<label
				style={{
					display: "flex",
					alignItems: "center",
					gap: "8px",
					cursor: "pointer",
					fontSize: "0.9em",
					color: "#ccc",
				}}
			>
				<input
					type="checkbox"
					checked={checked}
					onChange={(e) => onChange(e.target.checked)}
				/>
				{label}
			</label>
		</div>
	);
}

const QA_MODES = ["server", "agent", "human"] as const;

/** Settings page — form-based editor for project.toml scalar settings. */
export function SettingsPage({ onBack }: SettingsPageProps) {
	const [settings, setSettings] = useState<ProjectSettings | null>(null);
	const [status, setStatus] = useState<
		"idle" | "loading" | "saving" | "saved" | "error"
	>("loading");
	const [errorMsg, setErrorMsg] = useState<string | null>(null);
	const [validationErrors, setValidationErrors] = useState<
		Record<string, string>
	>({});

	useEffect(() => {
		settingsApi
			.getProjectSettings()
			.then((s) => {
				setSettings(s);
				setStatus("idle");
			})
			.catch((e: unknown) => {
				setStatus("error");
				setErrorMsg(e instanceof Error ? e.message : "Failed to load settings");
			});
	}, []);

	function patch(partial: Partial<ProjectSettings>) {
		setSettings((prev) => (prev ? { ...prev, ...partial } : prev));
		setValidationErrors({});
	}

	function validate(s: ProjectSettings): Record<string, string> {
		const errors: Record<string, string> = {};
		if (!QA_MODES.includes(s.default_qa as (typeof QA_MODES)[number])) {
			errors.default_qa = `Must be one of: ${QA_MODES.join(", ")}`;
		}
		if (s.max_retries < 0) {
			errors.max_retries = "Must be 0 or greater";
		}
		if (s.watcher_sweep_interval_secs < 1) {
			errors.watcher_sweep_interval_secs = "Must be at least 1 second";
		}
		if (s.watcher_done_retention_secs < 1) {
			errors.watcher_done_retention_secs = "Must be at least 1 second";
		}
		return errors;
	}

	async function handleSave() {
		if (!settings) return;
		const errors = validate(settings);
		if (Object.keys(errors).length > 0) {
			setValidationErrors(errors);
			return;
		}
		setStatus("saving");
		setErrorMsg(null);
		try {
			const saved = await settingsApi.putProjectSettings(settings);
			setSettings(saved);
			setStatus("saved");
			setTimeout(() => setStatus("idle"), 2000);
		} catch (e) {
			setStatus("error");
			setErrorMsg(e instanceof Error ? e.message : "Save failed");
		}
	}

	const s = settings;

	return (
		<div
			style={{
				display: "flex",
				flexDirection: "column",
				height: "100%",
				backgroundColor: "#171717",
				color: "#ececec",
				overflow: "auto",
			}}
		>
			{/* Header */}
			<div
				style={{
					padding: "12px 24px",
					borderBottom: "1px solid #333",
					display: "flex",
					alignItems: "center",
					gap: "16px",
					background: "#171717",
					flexShrink: 0,
				}}
			>
				<button
					type="button"
					onClick={onBack}
					style={{
						background: "transparent",
						border: "none",
						cursor: "pointer",
						color: "#888",
						fontSize: "0.9em",
						padding: "4px 8px",
						borderRadius: "4px",
					}}
				>
					← Back
				</button>
				<span style={{ fontWeight: 700, fontSize: "1em" }}>
					Project Settings
				</span>
			</div>

			{/* Body */}
			<div
				style={{
					flex: 1,
					padding: "24px",
					display: "flex",
					flexDirection: "column",
					gap: "20px",
					maxWidth: "640px",
				}}
			>
				{status === "loading" && (
					<p style={{ color: "#888", fontSize: "0.9em" }}>Loading settings…</p>
				)}

				{status === "error" && !s && (
					<p style={{ color: "#f08080", fontSize: "0.9em" }}>
						Error: {errorMsg}
					</p>
				)}

				{s && (
					<>
						{/* Pipeline */}
						<div style={sectionStyle}>
							<div style={sectionTitleStyle}>Pipeline</div>

							<div style={fieldStyle}>
								<label style={labelStyle}>Default QA Mode</label>
								<span style={descStyle}>
									How stories are QA-reviewed after the coder stage. Default:
									server.
								</span>
								<select
									value={s.default_qa}
									onChange={(e) => patch({ default_qa: e.target.value })}
									style={{ ...inputStyle, cursor: "pointer" }}
								>
									{QA_MODES.map((m) => (
										<option key={m} value={m}>
											{m}
										</option>
									))}
								</select>
								{validationErrors.default_qa && (
									<span style={{ color: "#f08080", fontSize: "0.8em" }}>
										{validationErrors.default_qa}
									</span>
								)}
							</div>

							<NumberField
								label="Max Retries"
								description="Maximum retries per story per pipeline stage before blocking. Default: 2. Set 0 to disable."
								value={s.max_retries}
								min={0}
								onChange={(v) => patch({ max_retries: v ?? 0 })}
							/>
							{validationErrors.max_retries && (
								<span style={{ color: "#f08080", fontSize: "0.8em" }}>
									{validationErrors.max_retries}
								</span>
							)}

							<NumberField
								label="Max Concurrent Coders"
								description="Maximum number of coder-stage agents running at once. Leave blank for unlimited."
								value={s.max_coders}
								min={1}
								placeholder="unlimited"
								onChange={(v) => patch({ max_coders: v })}
							/>

							<TextField
								label="Default Coder Model"
								description="When set, only coder agents matching this model are auto-assigned (e.g. sonnet, opus)."
								value={s.default_coder_model ?? ""}
								onChange={(v) =>
									patch({ default_coder_model: v.trim() || null })
								}
								placeholder="e.g. sonnet"
							/>
						</div>

						{/* Git */}
						<div style={sectionStyle}>
							<div style={sectionTitleStyle}>Git</div>

							<TextField
								label="Base Branch"
								description="Overrides auto-detection of the merge target branch (e.g. main, master, develop)."
								value={s.base_branch ?? ""}
								onChange={(v) => patch({ base_branch: v.trim() || null })}
								placeholder="e.g. master"
							/>
						</div>

						{/* Notifications */}
						<div style={sectionStyle}>
							<div style={sectionTitleStyle}>Notifications</div>

							<CheckboxField
								label="Rate Limit Notifications"
								description="Send chat notifications on soft API rate-limit warnings. Disable to reduce noise."
								checked={s.rate_limit_notifications}
								onChange={(v) => patch({ rate_limit_notifications: v })}
							/>
						</div>

						{/* Advanced */}
						<div style={sectionStyle}>
							<div style={sectionTitleStyle}>Advanced</div>

							<TextField
								label="Timezone"
								description="IANA timezone for timer inputs (e.g. Europe/London, America/New_York). Leave blank for system default."
								value={s.timezone ?? ""}
								onChange={(v) => patch({ timezone: v.trim() || null })}
								placeholder="e.g. Europe/London"
							/>

							<TextField
								label="Rendezvous URL"
								description="WebSocket URL of a remote huskies node for CRDT state sync (e.g. ws://host:3001/crdt-sync)."
								value={s.rendezvous ?? ""}
								onChange={(v) => patch({ rendezvous: v.trim() || null })}
								placeholder="e.g. ws://host:3001/crdt-sync"
							/>
						</div>

						{/* Watcher */}
						<div style={sectionStyle}>
							<div style={sectionTitleStyle}>Archiver</div>

							<NumberField
								label="Sweep Interval (seconds)"
								description="How often to check the done stage for items ready to archive. Default: 60."
								value={s.watcher_sweep_interval_secs}
								min={1}
								onChange={(v) =>
									patch({ watcher_sweep_interval_secs: v ?? 60 })
								}
							/>
							{validationErrors.watcher_sweep_interval_secs && (
								<span style={{ color: "#f08080", fontSize: "0.8em" }}>
									{validationErrors.watcher_sweep_interval_secs}
								</span>
							)}

							<NumberField
								label="Done Retention (seconds)"
								description="How long an item must stay in the done stage before archiving. Default: 14400 (4 hours)."
								value={s.watcher_done_retention_secs}
								min={1}
								onChange={(v) =>
									patch({ watcher_done_retention_secs: v ?? 14400 })
								}
							/>
							{validationErrors.watcher_done_retention_secs && (
								<span style={{ color: "#f08080", fontSize: "0.8em" }}>
									{validationErrors.watcher_done_retention_secs}
								</span>
							)}
						</div>

						{/* Save */}
						<div style={{ display: "flex", alignItems: "center", gap: "12px" }}>
							<button
								type="button"
								onClick={handleSave}
								disabled={status === "saving"}
								style={{
									padding: "8px 24px",
									borderRadius: "6px",
									border: "none",
									background: status === "saved" ? "#1a5c2a" : "#2563eb",
									color: "#fff",
									cursor: status === "saving" ? "not-allowed" : "pointer",
									fontSize: "0.9em",
									fontWeight: 600,
									opacity: status === "saving" ? 0.7 : 1,
								}}
							>
								{status === "saving"
									? "Saving…"
									: status === "saved"
										? "Saved!"
										: "Save"}
							</button>
							{status === "error" && errorMsg && (
								<span style={{ color: "#f08080", fontSize: "0.85em" }}>
									{errorMsg}
								</span>
							)}
						</div>
					</>
				)}
			</div>
		</div>
	);
}
