import clsx from 'clsx';
import { Ban, CirclePlus, LoaderCircle, MessageSquarePlus, Pencil, RefreshCcwDot, Reply, Search, Smile, X } from 'lucide-solid';
import { A, useNavigate, useParams, useSearchParams, useLocation } from '@solidjs/router';
import { createQuery, useQueryClient } from '@tanstack/solid-query';
import type { ResourceUri } from '@atcute/lexicons/syntax';
import { For, Match, Show, Switch, createEffect, createMemo, createSignal, type Component } from 'solid-js';
import { createIssue, createIssueComment, getIssue, listIssuesPage, setIssueState, type IssueComment } from '../../lib/api/issues';
import { resolveActor } from '../../lib/api/identity';
import { parseAtUri } from '../../lib/api/records';
import type { RepoContext } from '../../lib/api/repos';
import { useAuth } from '../../lib/auth';
import { useIssuePreloader } from '../../lib/preloading';
import { Avatar, ErrorState, PaginationControls, StateBadge, ToggleButton, buttonStyles, cardStyles, inputStyles, textareaStyles } from '../../components/common';
import { AtUriPanel, MarkdownBlock, RepoFormSkeleton, RepoListPageSkeleton, RepoListSkeleton, RepoThreadSkeleton, IssueOrPullRow, ThreadCommentView } from '../../components/repo';
import { RepoFrame, issueQueryKey, issuesQueryKey, useRepoQuery } from './shared';
import { REPO_LIST_PAGE_LIMIT, formatRelativeTime, getErrorMessage, issueHref, parseIntegerSearchParam, uniqueCommenters, saveRecentIssueOrPull } from '../../lib/repo-utils';
import { buildIssueCommentThreads, buildIssueFilterQuery, parseIssueFilter } from './issues-helpers';

export const IssuesPage: Component = () => {
	const auth = useAuth();
	const repoQuery = useRepoQuery();
	const issuePreloader = useIssuePreloader();
	const [searchParams, setSearchParams] = useSearchParams();
	const filter = createMemo(() => parseIssueFilter(searchParams.q));
	const stateFilter = createMemo(() => filter().state);
	const authorFilter = createMemo(() => filter().author);
	const textFilter = createMemo(() => filter().query);
	const filterQuery = createMemo(() => buildIssueFilterQuery(filter()));
	const [filterDraft, setFilterDraft] = createSignal(filterQuery());
	const pageOffset = createMemo(() => parseIntegerSearchParam(searchParams.offset, 0, 0));
	const pageLimit = createMemo(() => parseIntegerSearchParam(searchParams.limit, REPO_LIST_PAGE_LIMIT, 1));
	const basePath = createMemo(() => {
		const repo = repoQuery.data;
		return repo ? `/${repo.owner.handle}/${repo.slug}/issues` : '/';
	});
	createEffect(() => {
		setFilterDraft(filterQuery());
	});
	const setStateFilter = (state: 'open' | 'closed') => {
		setSearchParams({
			q: buildIssueFilterQuery({ ...filter(), state }),
			offset: '0',
			limit: String(pageLimit()),
		});
	};
	const applyFilter = (event: SubmitEvent) => {
		event.preventDefault();
		setSearchParams({
			q: buildIssueFilterQuery(parseIssueFilter(filterDraft())),
			offset: '0',
			limit: String(pageLimit()),
		});
	};
	const resetFilter = () => {
		setSearchParams({
			q: 'state:open',
			offset: '0',
			limit: String(pageLimit()),
		});
	};

	const issuesQuery = createQuery(() => {
		const repo = repoQuery.data;
		return {
			queryKey: [...issuesQueryKey(repo?.repoDid ?? ''), stateFilter(), authorFilter(), textFilter(), pageOffset(), pageLimit()],
			enabled: Boolean(repo),
			queryFn: async () => {
				const author = authorFilter() ? (await resolveActor(authorFilter()!)).did : undefined;
				return listIssuesPage(repo!, {
					state: stateFilter(),
					author,
					query: textFilter(),
					offset: pageOffset(),
					limit: pageLimit(),
				});
			},
		};
	});

	const activeCount = createMemo(() => {
		const data = issuesQuery.data;
		if (!data) return undefined;
		return data.totalCount === undefined ? `${pageOffset() + data.items.length}+` : String(data.totalCount);
	});
	const paginated = createMemo(() => issuesQuery.data?.items ?? []);

	return (
		<RepoFrame active="issues" loadingFallback={<RepoListPageSkeleton kind="issues" showCreate={Boolean(auth.agent())} />}>
			<div class="rounded bg-white p-4 dark:bg-gray-800">
				<div class="untangled-filter-grid">
					<div class="untangled-toggle-group">
						<ToggleButton
							active={stateFilter() === 'open'}
							onClick={() => setStateFilter('open')}
							label="open"
							meta={stateFilter() === 'open' ? activeCount() : undefined}
						/>
						<ToggleButton
							active={stateFilter() === 'closed'}
							onClick={() => setStateFilter('closed')}
							label="closed"
							meta={stateFilter() === 'closed' ? activeCount() : undefined}
						/>
					</div>

					<form onSubmit={applyFilter} class="untangled-repo-filter-search">
						<input
							value={filterDraft()}
							onInput={(event) => setFilterDraft(event.currentTarget.value)}
							placeholder="search issues..."
							class="untangled-repo-filter-input"
						/>
						<button type="button" class="untangled-repo-filter-reset" aria-label="reset filters" onClick={resetFilter}>
							<X class="size-4" />
						</button>
						<button type="submit" class="untangled-repo-filter-submit" aria-label="apply filters">
							<Search class="size-4" />
						</button>
					</form>

					<Show when={auth.agent() && repoQuery.data}>
						<A
							href={`/${repoQuery.data!.owner.handle}/${repoQuery.data!.slug}/issues/new`}
							class={clsx(buttonStyles('primary'), 'col-start-3 justify-center no-underline hover:no-underline')}
						>
							<CirclePlus class="size-4" />
							new issue
						</A>
					</Show>
				</div>
			</div>

			<div class="mt-2">
				<Show
						when={!issuesQuery.isLoading}
						fallback={
							<RepoListSkeleton kind="issues" />
						}
					>
					<Show
						when={!issuesQuery.error}
						fallback={
							<div class={cardStyles('p-6')}>
								<ErrorState message={getErrorMessage(issuesQuery.error)} />
							</div>
						}
					>
						<Show
							when={paginated().length > 0}
							fallback={
								<div class={cardStyles('px-6 py-4 text-sm text-gray-500 dark:text-gray-400')}>
									{stateFilter() === 'open' ? 'No open issues' : 'No closed issues'}
									<Show when={authorFilter()}>
										{' '}by {authorFilter()}
									</Show>
									.
								</div>
							}
						>
								<div class="flex flex-col gap-2">
									<div class="contents">
										<For each={paginated()}>
											{(issue) => (
												<IssueOrPullRow
													title={issue.value.title}
													number={issue.number || issue.rkey}
													state={issue.state}
													kind="issue"
													author={{ did: issue.author.did, handle: issue.author.handle }}
													createdAt={issue.value.createdAt}
													href={issueHref(repoQuery.data!, issue.number || issue.rkey)}
													{...issuePreloader(
														`${repoQuery.data!.owner.handle}/${repoQuery.data!.slug}`,
														'issue',
														issue.uri,
														issue.number || issue.rkey,
														repoQuery.data!,
													)}
												/>
											)}
										</For>
								</div>
							</div>
							<Show when={repoQuery.data}>
								<PaginationControls
									basePath={basePath()}
									offset={pageOffset()}
									limit={pageLimit()}
									totalCount={issuesQuery.data?.totalCount}
									hasNext={issuesQuery.data?.hasNext}
									query={{ q: filterQuery() }}
								/>
							</Show>
						</Show>
					</Show>
				</Show>
			</div>
		</RepoFrame>
	);
};

export const NewIssuePage: Component = () => {
	const auth = useAuth();
	const repoQuery = useRepoQuery();
	const navigate = useNavigate();
	const [title, setTitle] = createSignal('');
	const [body, setBody] = createSignal('');
	const [error, setError] = createSignal<string | null>(null);
	const [submitting, setSubmitting] = createSignal(false);
	const client = useQueryClient();

	const submit = async (event: SubmitEvent) => {
		event.preventDefault();
		const agent = auth.agent();
		const repo = repoQuery.data;

		if (!agent || !repo) {
			setError('Sign in first.');
			return;
		}

		if (!title().trim()) {
			setError('Title required.');
			return;
		}

		setSubmitting(true);
		setError(null);

		try {
			const created = await createIssue(agent, repo, { title: title(), body: body() });
			await client.invalidateQueries({ queryKey: issuesQueryKey(repo.repoDid) });
			navigate(issueHref(repo, created.rkey));
		} catch (cause) {
			setError(getErrorMessage(cause));
		} finally {
			setSubmitting(false);
		}
	};

	return (
		<RepoFrame active="issues" loadingFallback={<RepoFormSkeleton titleWidth="w-36" />}>
			<div class={cardStyles('p-6')}>
				<form onSubmit={submit} class="flex flex-col gap-4">
					<h1 class="text-2xl font-bold m-0">new issue</h1>
					<input value={title()} onInput={(event) => setTitle(event.currentTarget.value)} placeholder="title" class={inputStyles()} />
					<textarea value={body()} onInput={(event) => setBody(event.currentTarget.value)} placeholder="body" class={textareaStyles()} rows="14" />
					<Show when={error()}>
						<p class="text-sm text-red-500">{error()}</p>
					</Show>
					<div class="flex justify-end">
						<button type="submit" class={clsx(buttonStyles('primary'), 'justify-center min-w-32')} disabled={submitting()}>
							<Show when={submitting()} fallback="create issue">
								<span class="inline-flex items-center gap-2">
									<LoaderCircle class="size-4 animate-spin" />
									creating
								</span>
							</Show>
						</button>
					</div>
				</form>
			</div>
		</RepoFrame>
	);
};

const updateIssueStateData = (
	data: unknown,
	issueUri: ResourceUri,
	state: 'open' | 'closed',
): unknown => {
	if (!data || typeof data !== 'object') return data;

	if ('issue' in data) {
		const detail = data as { issue?: { uri?: string; state?: string } };
		if (detail.issue?.uri === issueUri) {
			return {
				...detail,
				issue: {
					...detail.issue,
					state,
				},
			};
		}
	}

	if ('items' in data) {
		const page = data as { items?: Array<{ uri?: string; state?: string }> };
		if (Array.isArray(page.items)) {
			return {
				...page,
				items: page.items.map((issue) => (issue.uri === issueUri ? { ...issue, state } : issue)),
			};
		}
	}

	return data;
};

export const IssuePage: Component = () => {
	const auth = useAuth();
	const repoQuery = useRepoQuery();
	const params = useParams();
	const client = useQueryClient();
	const location = useLocation();
	const issueRef = createMemo(() => params.issueRef ?? '');
	const [comment, setComment] = createSignal('');
	const [replyingTo, setReplyingTo] = createSignal<IssueComment | null>(null);
	const [replyBody, setReplyBody] = createSignal('');
	const [workingAction, setWorkingAction] = createSignal<'comment' | 'reply' | 'state' | null>(null);
	const working = createMemo(() => workingAction() !== null);
	const [error, setError] = createSignal<string | null>(null);

	const issueQuery = createQuery(() => {
		const repo = repoQuery.data;
		return {
			queryKey: issueQueryKey(repo?.repoDid ?? '', issueRef()),
			enabled: Boolean(repo && issueRef()),
			queryFn: async () => getIssue(repo!, issueRef()),
		};
	});

	createEffect(() => {
		const repo = repoQuery.data;
		const detail = issueQuery.data;
		if (repo && detail) {
			saveRecentIssueOrPull(repo.owner.handle, repo.slug, {
				uri: detail.issue.uri,
				kind: 'issue',
				title: detail.issue.value.title,
				number: detail.issue.number,
				state: detail.issue.state,
				author: detail.issue.author.handle,
			});
		}
	});

	createEffect(() => {
		const hash = location.hash;
		const cleanHash = hash.startsWith('#') ? hash.slice(1) : hash;
		if (cleanHash && cleanHash.startsWith('comment-') && issueQuery.data?.comments) {
			setTimeout(() => {
				const element = document.getElementById(cleanHash);
				if (element) {
					// Remove highlight from any other elements first
					document.querySelectorAll('.untangled-comment-highlight').forEach((el) => {
						el.classList.remove('untangled-comment-highlight');
					});
					element.scrollIntoView({ behavior: 'smooth', block: 'center' });
					element.classList.add('untangled-comment-highlight');
				}
			}, 150);
		}
	});

	const withIssueInvalidation = async (repo: RepoContext, issueRef: string, issueUri: string) => {
		await client.invalidateQueries({ queryKey: issuesQueryKey(repo.repoDid) });
		await client.invalidateQueries({ queryKey: issueQueryKey(repo.repoDid, issueRef) });
		await client.invalidateQueries({ queryKey: issueQueryKey(repo.repoDid, parseAtUri(issueUri).rkey) });
	};

	const updateIssueStateCaches = (
		repo: RepoContext,
		currentIssueRef: string,
		issueUri: ResourceUri,
		state: 'open' | 'closed',
	) => {
		client.setQueryData(issueQueryKey(repo.repoDid, currentIssueRef), (data: unknown) =>
			updateIssueStateData(data, issueUri, state),
		);
		client.setQueryData(issueQueryKey(repo.repoDid, parseAtUri(issueUri).rkey), (data: unknown) =>
			updateIssueStateData(data, issueUri, state),
		);
		client.setQueriesData<unknown>({ queryKey: issuesQueryKey(repo.repoDid) }, (data: unknown) =>
			updateIssueStateData(data, issueUri, state),
		);
	};

	const toggleState = async () => {
		const agent = auth.agent();
		const repo = repoQuery.data;
		const detail = issueQuery.data;
		if (!agent || !repo || !detail) {
			return;
		}

		const nextState = detail.issue.state === 'open' ? 'closed' : 'open';
		const commentBody = nextState === 'closed' ? comment().trim() : '';

		setWorkingAction('state');
		setError(null);
		try {
			if (commentBody) {
				await createIssueComment(agent, detail.issue.uri, detail.issue.cid ?? '', commentBody);
				setComment('');
			}
			await setIssueState(agent, detail.issue.uri, nextState);
			if (commentBody) {
				await client.invalidateQueries({ queryKey: issueQueryKey(repo.repoDid, issueRef()) });
				await client.invalidateQueries({ queryKey: issueQueryKey(repo.repoDid, parseAtUri(detail.issue.uri).rkey) });
			}
			updateIssueStateCaches(repo, issueRef(), detail.issue.uri, nextState);
			await client.invalidateQueries({ queryKey: issuesQueryKey(repo.repoDid), refetchType: 'none' });
			await client.invalidateQueries({ queryKey: issueQueryKey(repo.repoDid, issueRef()), refetchType: 'none' });
			await client.invalidateQueries({ queryKey: issueQueryKey(repo.repoDid, parseAtUri(detail.issue.uri).rkey), refetchType: 'none' });
		} catch (cause) {
			setError(getErrorMessage(cause));
		} finally {
			setWorkingAction(null);
		}
	};

	const addComment = async (event: SubmitEvent) => {
		event.preventDefault();
		const agent = auth.agent();
		const repo = repoQuery.data;
		const detail = issueQuery.data;
		if (!agent || !repo || !detail || !comment().trim()) {
			return;
		}

		setWorkingAction('comment');
		setError(null);
		try {
			await createIssueComment(agent, detail.issue.uri, detail.issue.cid ?? '', comment());
			setComment('');
			await withIssueInvalidation(repo, issueRef(), detail.issue.uri);
		} catch (cause) {
			setError(getErrorMessage(cause));
		} finally {
			setWorkingAction(null);
		}
	};

	const submitReply = async (event: SubmitEvent, replyToComment: IssueComment) => {
		event.preventDefault();
		const agent = auth.agent();
		const repo = repoQuery.data;
		const detail = issueQuery.data;
		if (!agent || !repo || !detail || !replyBody().trim()) {
			return;
		}

		setWorkingAction('reply');
		setError(null);
		try {
			await createIssueComment(
				agent,
				detail.issue.uri,
				detail.issue.cid ?? '',
				replyBody(),
				{ uri: replyToComment.uri, cid: replyToComment.cid ?? '' }
			);
			setReplyBody('');
			setReplyingTo(null);
			await withIssueInvalidation(repo, issueRef(), detail.issue.uri);
		} catch (cause) {
			setError(getErrorMessage(cause));
		} finally {
			setWorkingAction(null);
		}
	};

	return (
		<RepoFrame active="issues" loadingFallback={<RepoThreadSkeleton kind="issue" />}>
			<Switch>
				<Match when={issueQuery.isLoading}>
					<RepoThreadSkeleton kind="issue" />
				</Match>
				<Match when={issueQuery.error}>
					<div class={cardStyles('p-6')}>
						<ErrorState message={getErrorMessage(issueQuery.error)} />
					</div>
				</Match>
				<Match when={issueQuery.data}>
					{(detail) => {
						const participants = createMemo(() => {
							const seen = new Set<string>();
							const people = [
								{ did: detail().issue.author.did, handle: detail().issue.author.handle },
								...uniqueCommenters(detail().comments),
							];
							return people.filter((person) => {
								if (seen.has(person.did)) return false;
								seen.add(person.did);
								return true;
							});
						});
							const currentDid = createMemo(() => auth.currentDid());
							const currentHandleQuery = createQuery(() => {
								const did = currentDid();
								return {
									queryKey: ['actor-handle', did ?? ''],
									enabled: Boolean(did),
									queryFn: async () => (await resolveActor(did!)).handle,
								};
							});
							const currentHandle = createMemo(() => currentHandleQuery.data ?? currentDid());
							const commentThreads = createMemo(() => buildIssueCommentThreads(detail().comments));
				return (
						<div class="grid grid-cols-1 gap-4 w-full md:grid-cols-10">
							<div class="col-span-1 min-w-0 md:col-span-8">
								<section class="bg-white dark:bg-gray-800 p-6 rounded relative w-full mx-auto dark:text-white">
									<header class="pb-2">
										<h1 class="m-0 text-2xl">
											{detail().issue.value.title}{' '}
											<span class="text-gray-500 dark:text-gray-400">#{detail().issue.number || detail().issue.rkey}</span>
										</h1>
									</header>

									<div class="mt-3 flex flex-wrap items-center gap-2 text-sm text-gray-500 dark:text-gray-400">
										<StateBadge state={detail().issue.state} kind="issue" />
										<span>opened by</span>
										<Avatar did={detail().issue.author.did} size="size-6" />
										<a href={`/${detail().issue.author.did}`} class="text-gray-700 dark:text-gray-200">{detail().issue.author.handle}</a>
										<span class="select-none">·</span>
										<span>{formatRelativeTime(detail().issue.value.createdAt)}</span>
									</div>

									<Show when={detail().issue.value.body}>
										<div class="pt-5 min-w-0">
											<MarkdownBlock markdown={detail().issue.value.body!} />
										</div>
									</Show>

									<div class="pt-5">
										<button type="button" class="inline-flex size-8 items-center justify-center rounded border border-gray-300 text-gray-500 dark:border-gray-600 dark:text-gray-400">
											<Smile class="size-4" />
										</button>
									</div>
								</section>

								<div class="flex min-w-0 flex-col gap-4">									<div class="mt-4 flex flex-col gap-4">
										<For each={commentThreads()}>
											{(thread) => (
												<div class="untangled-thread-group">
													<ThreadCommentView
														id={`comment-${thread.item.rkey}`}
														author={{ did: thread.item.author.did, handle: thread.item.author.handle }}
														createdAt={thread.item.value.createdAt}
														markdown={thread.item.value.body}
														isAuthor={thread.item.author.did === detail().issue.author.did}
														class="untangled-thread-comment"
													/>

													<Show when={thread.replies.length > 0}>
														<div class="untangled-thread-replies-list">
															<For each={thread.replies}>
																{(reply) => (
																	<ThreadCommentView
																		id={`comment-${reply.rkey}`}
																		author={{ did: reply.author.did, handle: reply.author.handle }}
																		createdAt={reply.value.createdAt}
																		markdown={reply.value.body}
																		isAuthor={reply.author.did === detail().issue.author.did}
																		class="untangled-thread-reply"
																	/>
																)}
															</For>
														</div>
													</Show>

													<Show when={auth.agent()}>
														<Show
															when={replyingTo()?.uri === thread.item.uri}
															fallback={
																<button
																	type="button"
																	class="untangled-thread-reply-trigger"
																	onClick={() => {
																		setReplyingTo(thread.item);
																		setReplyBody('');
																	}}
																>
																	<Show when={currentDid()}>
																		{(did) => <Avatar did={did()} size="size-8 mr-1" />}
																	</Show>
																	<span class="w-full p-0">Leave a reply...</span>
																</button>
															}
														>
														<form
															onSubmit={(event) => void submitReply(event, thread.item)}
															class="untangled-thread-reply-form"
														>
															<Show when={currentDid()}>
																{(did) => (
																	<div class="flex items-center gap-2 text-sm text-gray-500 dark:text-gray-400">
																		<Avatar did={did()} size="size-6" />
																		<span>{currentHandle()}</span>
																	</div>
																)}
															</Show>
															<textarea
																value={replyBody()}
																onInput={(event) => setReplyBody(event.currentTarget.value)}
																class={textareaStyles()}
																rows="3"
																placeholder="Leave a reply..."
															/>
															<div class="flex flex-wrap items-stretch justify-end gap-2 text-sm text-gray-500 dark:text-gray-400">
																<button type="button" class={clsx(buttonStyles(), 'text-red-500 dark:text-red-400')} onClick={() => setReplyingTo(null)}>
																	<X class="size-4" />
																	cancel
																</button>
																<button type="submit" class={buttonStyles('primary')} disabled={working() || !replyBody().trim()}>
																	<Show when={workingAction() === 'reply'} fallback={<Reply class="size-4" />}>
																		<LoaderCircle class="size-4 animate-spin" />
																	</Show>
																	reply
																</button>
															</div>
														</form>
														</Show>
													</Show>
												</div>
											)}
										</For>

										<Show when={auth.agent()}>
											<form onSubmit={addComment} class="flex min-w-0 flex-col gap-2">
												<div class="untangled-comment-composer">
													<Show when={currentDid()}>
														{(did) => (
															<div class="flex items-center gap-2 text-sm text-gray-700 dark:text-gray-200">
																<Avatar did={did()} size="size-6" />
																<span>{currentHandle()}</span>
															</div>
														)}
													</Show>
													<textarea
														value={comment()}
														onInput={(event) => setComment(event.currentTarget.value)}
														class={textareaStyles()}
														rows="5"
														placeholder="Add to the discussion. Markdown is supported."
													/>
													<Show when={error()}>
														<p class="text-sm text-red-500">{error()}</p>
													</Show>
												</div>
												<div class="flex flex-wrap items-center gap-2">
													<button type="submit" class={clsx(buttonStyles('primary'), 'justify-center')} disabled={working() || !comment().trim()}>
														<Show when={workingAction() === 'comment'} fallback={<MessageSquarePlus class="size-4" />}>
															<LoaderCircle class="size-4 animate-spin" />
														</Show>
														comment
													</button>
													<button type="button" class={buttonStyles()} disabled={working()} onClick={() => void toggleState()}>
														<Show
															when={workingAction() === 'state'}
															fallback={
																<Show when={detail().issue.state === 'open'} fallback={<RefreshCcwDot class="size-4" />}>
																	<Ban class="size-4" />
																</Show>
															}
														>
															<LoaderCircle class="size-4 animate-spin" />
														</Show>
														{detail().issue.state === 'open' ? (comment().trim() ? 'close with comment' : 'close') : 'reopen'}
													</button>
												</div>
											</form>
										</Show>
									</div>
								</div>
							</div>

							<div class="untangled-thread-meta col-span-1 flex min-w-0 flex-col gap-6 text-sm md:col-span-2">
								<section>
									<div class="flex items-center justify-between gap-2 font-semibold uppercase text-gray-500 dark:text-gray-400">
										<span>Labels</span>
										<Pencil class="size-3.5" />
									</div>
									<div class="mt-1 text-gray-500 dark:text-gray-400">None yet.</div>
								</section>
								<section>
									<div class="flex items-center justify-between gap-2 font-semibold uppercase text-gray-500 dark:text-gray-400">
										<span>Assignee</span>
										<Pencil class="size-3.5" />
									</div>
									<div class="mt-1 text-gray-500 dark:text-gray-400">None yet.</div>
								</section>
								<section>
									<div class="font-semibold text-gray-500 dark:text-gray-400">
										Participants <span class="rounded bg-gray-700 px-1 text-gray-200">{participants().length}</span>
									</div>
									<div class="untangled-overlap-avatars mt-2 flex">
										<For each={participants()}>
											{(participant) => <Avatar did={participant.did} size="size-8" />}
										</For>
									</div>
								</section>
								<AtUriPanel uri={detail().issue.uri} />
							</div>
						</div>
						);
					}}
				</Match>
			</Switch>
		</RepoFrame>
	);
};
