---
/**
 * Server-rendered comment list for a content item.
 *
 * Fetches approved comments directly from the repository (no API call).
 * Renders semantic HTML with CSS custom properties for styling.
 *
 * @example
 * ```astro
 * ---
 * import { Comments } from "emdash/ui";
 * ---
 * <Comments collection="posts" contentId={post.id} threaded />
 * ```
 */
import type { PublicComment } from "../database/repositories/comment.js";
import { getComments } from "../comments/query.js";
import { getCollectionInfo } from "../schema/query.js";

interface Props {
	collection: string;
	contentId: string;
	threaded?: boolean;
	class?: string;
}

const {
	collection,
	contentId,
	threaded = false,
	class: className,
} = Astro.props;

const collectionInfo = await getCollectionInfo(collection);
const enabled = collectionInfo?.commentsEnabled ?? false;
const { items, total } = enabled
	? await getComments({ collection, contentId, threaded })
	: { items: [], total: 0 };

const URL_RE = /https?:\/\/[^\s<>"')\]]+/g;
const AMP_RE = /&/g;
const LT_RE = /</g;
const GT_RE = />/g;
const QUOT_RE = /"/g;

function autoLinkUrls(text: string): string {
	return text.replace(
		URL_RE,
		(url) =>
			`<a href="${url}" rel="nofollow ugc noopener" target="_blank">${url}</a>`
	);
}

function escapeHtml(text: string): string {
	return text
		.replace(AMP_RE, "&amp;")
		.replace(LT_RE, "&lt;")
		.replace(GT_RE, "&gt;")
		.replace(QUOT_RE, "&quot;");
}

function formatBody(text: string): string {
	return autoLinkUrls(escapeHtml(text));
}
---

{
	enabled && (
		<section
			class:list={["ec-comments", className]}
			data-ec-comments
			data-collection={collection}
			data-content-id={contentId}
		>
			<h3 class="ec-comments-heading">
				{total === 0
					? "No comments yet"
					: total === 1
						? "1 Comment"
						: `${total} Comments`}
			</h3>

			{items.length > 0 && (
				<ol class="ec-comments-list">
					{items.map((comment: PublicComment) => (
						<li>
							<article
								class="ec-comment"
								id={`comment-${comment.id}`}
								data-comment-id={comment.id}
							>
								<header class="ec-comment-header">
									<span class="ec-comment-author">
										{comment.authorName}
										{comment.isRegisteredUser && (
											<span class="ec-comment-badge" aria-label="Site member">
												&#x2713;
											</span>
										)}
									</span>
									<time class="ec-comment-date" datetime={comment.createdAt}>
										{new Date(comment.createdAt).toLocaleDateString("en-US", {
											year: "numeric",
											month: "long",
											day: "numeric",
											hour: "numeric",
											minute: "2-digit",
										})}
									</time>
								</header>
								<div
									class="ec-comment-body"
									set:html={formatBody(comment.body)}
								/>
								{threaded && comment.replies && comment.replies.length > 0 && (
									<ol class="ec-comment-replies">
										{comment.replies.map((reply: PublicComment) => (
											<li>
												<article
													class="ec-comment ec-comment-reply"
													id={`comment-${reply.id}`}
													data-comment-id={reply.id}
												>
													<header class="ec-comment-header">
														<span class="ec-comment-author">
															{reply.authorName}
															{reply.isRegisteredUser && (
																<span
																	class="ec-comment-badge"
																	aria-label="Site member"
																>
																	&#x2713;
																</span>
															)}
														</span>
														<time
															class="ec-comment-date"
															datetime={reply.createdAt}
														>
															{new Date(reply.createdAt).toLocaleDateString(
																"en-US",
																{
																	year: "numeric",
																	month: "long",
																	day: "numeric",
																	hour: "numeric",
																	minute: "2-digit",
																}
															)}
														</time>
													</header>
													<div
														class="ec-comment-body"
														set:html={formatBody(reply.body)}
													/>
												</article>
											</li>
										))}
									</ol>
								)}
							</article>
						</li>
					))}
				</ol>
			)}
		</section>
	)
}

<style>
	.ec-comments {
		--ec-comment-gap: 1.5rem;
		--ec-comment-indent: 2rem;
		--ec-comment-border: 1px solid #e5e7eb;
	}

	.ec-comments-list,
	.ec-comment-replies {
		list-style: none;
		padding: 0;
		margin: 0;
	}

	.ec-comments-list > li + li {
		margin-top: var(--ec-comment-gap);
	}

	.ec-comment {
		padding-bottom: var(--ec-comment-gap);
		border-bottom: var(--ec-comment-border);
	}

	.ec-comment-replies {
		margin-top: var(--ec-comment-gap);
		padding-left: var(--ec-comment-indent);
	}

	.ec-comment-replies > li + li {
		margin-top: var(--ec-comment-gap);
	}

	.ec-comment-header {
		display: flex;
		align-items: baseline;
		gap: 0.5rem;
		flex-wrap: wrap;
	}

	.ec-comment-author {
		font-weight: 600;
	}

	.ec-comment-author a {
		color: inherit;
	}

	.ec-comment-badge {
		font-size: 0.75em;
		vertical-align: super;
	}

	.ec-comment-date {
		font-size: 0.875em;
		opacity: 0.6;
	}

	.ec-comment-body {
		margin-top: 0.5rem;
		white-space: pre-wrap;
		word-break: break-word;
	}
</style>
