import { useState } from "react";
import { useMutation, useQueryClient, useSuspenseQuery } from "@tanstack/react-query";
import * as stylex from "@stylexjs/stylex";
import {
	blocklistsQuery,
	groupCreateMutation,
	groupDeleteMutation,
	groupsQuery,
	groupUpdateMutation,
} from "@/lib/queries";
import type { Blocklist, Group } from "@/lib/types";
import GroupSourcesEditor from "./GroupSourcesEditor";
import InlineError from "@/lib/InlineError";
import { styles as shared } from "@/ui/styles";
import { colors } from "@/ui/tokens.stylex";
import { DEFAULT_GROUP_ID } from "@/lib/defaultGroup";
import { READ_ONLY_HINT, useReadOnlyConfig } from "@/features/settings/authority";

const DEFAULT_GROUP_NOTE = "The default group cannot be renamed or deleted.";

const styles = stylex.create({
	heading: {
		fontSize: "1.5rem",
		lineHeight: "2rem",
		fontWeight: 600,
	},
	createForm: {
		marginTop: "1rem",
		display: "flex",
		flexWrap: "wrap",
		alignItems: "center",
		gap: "0.5rem",
	},
	fieldLabel: {
		fontSize: "0.875rem",
		lineHeight: "1.25rem",
		fontWeight: 500,
	},
	list: {
		display: "flex",
		flexDirection: "column",
		gap: "1rem",
		marginTop: "1.5rem",
	},
	row: {
		borderRadius: "0.25rem",
		borderWidth: 1,
		borderStyle: "solid",
		borderColor: colors.border,
		padding: "1rem",
	},
	rowControls: {
		display: "flex",
		flexWrap: "wrap",
		alignItems: "center",
		gap: "0.75rem",
	},
	renameForm: {
		display: "flex",
		alignItems: "center",
		gap: "0.5rem",
	},
	name: {
		fontWeight: 500,
	},
	checkboxLabel: {
		display: "inline-flex",
		alignItems: "center",
		gap: "0.5rem",
		fontSize: "0.875rem",
		lineHeight: "1.25rem",
	},
	actions: {
		marginLeft: "auto",
		display: "inline-flex",
		flexWrap: "wrap",
		alignItems: "center",
		gap: "0.5rem",
	},
	groupButton: {
		opacity: { default: 1, ":disabled": 0.5 },
	},
	destructive: {
		color: colors.danger,
	},
	lockNote: {
		marginTop: "0.5rem",
		fontSize: "0.75rem",
		lineHeight: "1rem",
		color: colors.textMuted,
	},
});

export default function GroupsPage() {
	const { data: groups } = useSuspenseQuery(groupsQuery());
	const { data: blocklists } = useSuspenseQuery(blocklistsQuery());
	const queryClient = useQueryClient();
	const createMutation = useMutation(groupCreateMutation(queryClient));
	const [newName, setNewName] = useState("");
	const readOnly = useReadOnlyConfig();

	return (
		<section>
			<h1 {...stylex.props(styles.heading)}>Groups</h1>
			<form
				{...stylex.props(styles.createForm)}
				onSubmit={(event) => {
					event.preventDefault();
					const name = newName.trim();
					if (name === "") return;
					createMutation.mutate({ name }, { onSuccess: () => setNewName("") });
				}}
			>
				<label {...stylex.props(styles.fieldLabel)} htmlFor="new-group-name">
					New group
				</label>
				<input
					id="new-group-name"
					type="text"
					value={newName}
					onChange={(event) => setNewName(event.target.value)}
					disabled={readOnly}
					{...stylex.props(shared.smallInput, shared.focusRing)}
				/>
				<button
					type="submit"
					disabled={createMutation.isPending || readOnly}
					title={readOnly ? READ_ONLY_HINT : undefined}
					{...stylex.props(shared.primaryButton, shared.focusRing)}
				>
					Create
				</button>
			</form>
			<InlineError error={createMutation.error} />
			<ul {...stylex.props(styles.list)}>
				{groups.map((group) => (
					<GroupRow key={group.id} group={group} blocklists={blocklists} />
				))}
			</ul>
		</section>
	);
}

function GroupRow({ group, blocklists }: { group: Group; blocklists: Blocklist[] }) {
	const queryClient = useQueryClient();
	const updateMutation = useMutation(groupUpdateMutation(queryClient));
	const deleteMutation = useMutation(groupDeleteMutation(queryClient));
	const [renaming, setRenaming] = useState(false);
	const [name, setName] = useState(group.name);
	const [confirming, setConfirming] = useState(false);
	const [expanded, setExpanded] = useState(false);
	const isDefault = group.id === DEFAULT_GROUP_ID;
	const readOnly = useReadOnlyConfig();
	const lockNote = isDefault ? DEFAULT_GROUP_NOTE : readOnly ? READ_ONLY_HINT : undefined;

	return (
		<li {...stylex.props(styles.row)}>
			<div {...stylex.props(styles.rowControls)}>
				{renaming ? (
					<form
						{...stylex.props(styles.renameForm)}
						onSubmit={(event) => {
							event.preventDefault();
							const trimmed = name.trim();
							if (trimmed === "") return;
							updateMutation.mutate(
								{ id: group.id, input: { name: trimmed, safe_search: group.safe_search } },
								{ onSuccess: () => setRenaming(false) },
							);
						}}
					>
						<input
							type="text"
							aria-label={`New name for ${group.name}`}
							value={name}
							onChange={(event) => setName(event.target.value)}
							{...stylex.props(shared.smallInput, shared.focusRing)}
							autoFocus
						/>
						<button
							type="submit"
							disabled={updateMutation.isPending || readOnly}
							title={readOnly ? READ_ONLY_HINT : undefined}
							{...stylex.props(shared.smallButton, styles.groupButton, shared.focusRing)}
						>
							Save
						</button>
						<button
							type="button"
							onClick={() => {
								setName(group.name);
								setRenaming(false);
							}}
							{...stylex.props(shared.smallButton, styles.groupButton, shared.focusRing)}
						>
							Cancel
						</button>
					</form>
				) : (
					<span {...stylex.props(styles.name)}>{group.name}</span>
				)}
				<label {...stylex.props(styles.checkboxLabel)}>
					<input
						type="checkbox"
						checked={group.safe_search}
						disabled={updateMutation.isPending || readOnly}
						title={readOnly ? READ_ONLY_HINT : undefined}
						{...stylex.props(shared.focusRing)}
						onChange={(event) =>
							updateMutation.mutate({
								id: group.id,
								input: { name: group.name, safe_search: event.target.checked },
							})
						}
					/>
					Safe search
				</label>
				<span {...stylex.props(styles.actions)}>
					<button
						type="button"
						aria-expanded={expanded}
						onClick={() => setExpanded((open) => !open)}
						{...stylex.props(shared.smallButton, styles.groupButton, shared.focusRing)}
					>
						Sources
					</button>
					{!renaming && (
						<button
							type="button"
							disabled={isDefault || readOnly}
							title={lockNote}
							onClick={() => {
								setName(group.name);
								setRenaming(true);
							}}
							{...stylex.props(shared.smallButton, styles.groupButton, shared.focusRing)}
						>
							Rename
						</button>
					)}
					{confirming ? (
						<>
							<button
								type="button"
								onClick={() => {
									setConfirming(false);
									deleteMutation.mutate(group.id);
								}}
								{...stylex.props(
									shared.smallButton,
									styles.groupButton,
									styles.destructive,
									shared.focusRing,
								)}
							>
								Confirm delete
							</button>
							<button
								type="button"
								onClick={() => setConfirming(false)}
								{...stylex.props(shared.smallButton, styles.groupButton, shared.focusRing)}
							>
								Cancel
							</button>
						</>
					) : (
						<button
							type="button"
							disabled={isDefault || readOnly}
							title={lockNote}
							onClick={() => setConfirming(true)}
							{...stylex.props(
								shared.smallButton,
								styles.groupButton,
								styles.destructive,
								shared.focusRing,
							)}
						>
							Delete
						</button>
					)}
				</span>
			</div>
			{isDefault && <p {...stylex.props(styles.lockNote)}>{DEFAULT_GROUP_NOTE}</p>}
			<InlineError error={updateMutation.error ?? deleteMutation.error} />
			{expanded && <GroupSourcesEditor groupId={group.id} blocklists={blocklists} />}
		</li>
	);
}
