<!--
Phase 28 — compose dialog for diplomatic mail. The recipient picker
reads `gameState.report.races[]` (Phase 22); the kind toggle exposes
personal / broadcast. The admin compose path lives in the
server-side admin tooling, not in the in-game UI, so it is not
surfaced here. Broadcast sends are gated server-side; the UI
surfaces the resulting 403 inline.
-->
<script lang="ts">
	import { getContext } from "svelte";

	import { i18n } from "$lib/i18n/index.svelte";
	import { mailStore } from "$lib/mail-store.svelte";
	import {
		RENDERED_REPORT_CONTEXT_KEY,
		type RenderedReportSource,
	} from "$lib/rendered-report.svelte";

	type ComposeKind = "personal" | "broadcast";

	let {
		onClose,
		onSent,
	}: {
		onClose: () => void;
		onSent: (raceName: string | null) => void;
	} = $props();

	const rendered = getContext<RenderedReportSource | undefined>(
		RENDERED_REPORT_CONTEXT_KEY,
	);

	const races = $derived.by<string[]>(() => {
		const r = rendered?.report;
		if (!r) {
			return [];
		}
		return r.races.map((race) => race.name);
	});

	let kind = $state<ComposeKind>("personal");
	let raceName = $state("");
	let subject = $state("");
	let body = $state("");
	let error = $state<string | null>(null);
	let sending = $state(false);

	$effect(() => {
		if (raceName === "" && races.length > 0) {
			raceName = races[0];
		}
	});

	async function submit(event: SubmitEvent): Promise<void> {
		event.preventDefault();
		error = null;
		const bodyText = body.trim();
		if (bodyText === "") {
			error = i18n.t("game.mail.body_required");
			return;
		}
		if (kind === "personal" && raceName === "") {
			error = i18n.t("game.mail.recipient_required");
			return;
		}
		sending = true;
		try {
			if (kind === "personal") {
				await mailStore.composePersonal({
					raceName,
					subject,
					body: bodyText,
				});
				onSent(raceName);
				return;
			}
			await mailStore.composeBroadcast({ subject, body: bodyText });
			onSent(null);
		} catch (err) {
			error = err instanceof Error ? err.message : String(err);
		} finally {
			sending = false;
		}
	}
</script>

<div class="overlay" data-testid="mail-compose">
	<form class="dialog" onsubmit={submit}>
		<header>
			<h3>{i18n.t("game.mail.compose_action")}</h3>
			<button type="button" class="close" onclick={onClose}>×</button>
		</header>

		<label>
			{i18n.t("game.mail.compose.target_label")}
			<select bind:value={kind} data-testid="mail-compose-kind">
				<option value="personal">{i18n.t("game.mail.compose.target_personal")}</option>
				<option value="broadcast">{i18n.t("game.mail.compose.target_broadcast")}</option>
			</select>
		</label>

		{#if kind === "personal"}
			<label>
				{i18n.t("game.mail.recipient_label")}
				<select bind:value={raceName} data-testid="mail-compose-recipient">
					{#each races as race (race)}
						<option value={race}>{race}</option>
					{/each}
				</select>
			</label>
		{/if}

		<label>
			<span class="visually-hidden">{i18n.t("game.mail.subject_placeholder")}</span>
			<input
				type="text"
				bind:value={subject}
				placeholder={i18n.t("game.mail.subject_placeholder")}
				data-testid="mail-compose-subject"
			/>
		</label>

		<label>
			<span class="visually-hidden">{i18n.t("game.mail.body_placeholder")}</span>
			<textarea
				bind:value={body}
				placeholder={i18n.t("game.mail.body_placeholder")}
				rows="6"
				data-testid="mail-compose-body"
			></textarea>
		</label>

		{#if error}
			<p class="error" data-testid="mail-compose-error">{error}</p>
		{/if}

		<footer>
			<button type="button" onclick={onClose}>
				{i18n.t("game.mail.compose.cancel")}
			</button>
			<button type="submit" disabled={sending} data-testid="mail-compose-send">
				{i18n.t("game.mail.compose.send")}
			</button>
		</footer>
	</form>
</div>

<style>
	.overlay {
		position: fixed;
		inset: 0;
		background: rgba(0, 0, 0, 0.5);
		display: flex;
		align-items: center;
		justify-content: center;
		z-index: 50;
	}
	.dialog {
		display: flex;
		flex-direction: column;
		gap: 0.5rem;
		padding: 1rem 1.25rem;
		background: #161616;
		border: 1px solid #2a2a2a;
		border-radius: 8px;
		min-width: min(420px, 90vw);
		max-width: min(560px, 95vw);
	}
	header {
		display: flex;
		align-items: center;
		justify-content: space-between;
	}
	header h3 {
		margin: 0;
		font-size: 1rem;
	}
	.close {
		font: inherit;
		background: transparent;
		border: none;
		color: inherit;
		font-size: 1.25rem;
		cursor: pointer;
	}
	label {
		display: flex;
		flex-direction: column;
		gap: 0.2rem;
		font-size: 0.85rem;
		color: #ccc;
	}
	input,
	textarea,
	select {
		font: inherit;
		padding: 0.4rem 0.5rem;
		border: 1px solid #444;
		background: #111;
		color: inherit;
		border-radius: 4px;
	}
	footer {
		display: flex;
		justify-content: flex-end;
		gap: 0.5rem;
		margin-top: 0.5rem;
	}
	footer button {
		font: inherit;
		padding: 0.35rem 0.75rem;
		border: 1px solid #444;
		background: #1a1a1a;
		color: #fff;
		border-radius: 4px;
		cursor: pointer;
	}
	footer button[type="submit"] {
		background: #2a4d7d;
		border-color: #2a4d7d;
	}
	footer button:disabled {
		opacity: 0.5;
		cursor: not-allowed;
	}
	.error {
		color: #c62828;
		font-size: 0.85rem;
		margin: 0;
	}
	.visually-hidden {
		position: absolute;
		clip: rect(0 0 0 0);
		clip-path: inset(50%);
		height: 1px;
		width: 1px;
		overflow: hidden;
	}
</style>
