<script>
	import { createEventDispatcher } from 'svelte';
	import Icon from '$lib/Icon.svelte';
	import { RECOMMENDATION_PROFILES } from '$lib/collection-tools.js';

	export let users = [];
	export let selectedUserId = null;

	const dispatch = createEventDispatcher();

	let sourceUserId = null;
	let targetUserIds = [];
	let collectionName = '';
	let selectedSeeds = [];
	let recommendations = [];
	let includeSeeds = true;
	let recommendationLimit = 18;
	let recommendationProfile = 'balanced';
	let recentItems = [];
	let recentBusy = false;
	let recentError = '';
	let movieSearchTerm = '';
	let showSearchTerm = '';
	let movieResults = [];
	let showResults = [];
	let movieSearchBusy = false;
	let showSearchBusy = false;
	let movieSearchError = '';
	let showSearchError = '';
	let previewBusy = false;
	let createBusy = false;
	let actionError = '';
	let actionMessage = '';
	let existingCollection = null;

	$: sourceUsers = users.filter((user) => user.embyGuid);
	$: profileOptions = Object.values(RECOMMENDATION_PROFILES);
	$: selectedProfile = RECOMMENDATION_PROFILES[recommendationProfile] || RECOMMENDATION_PROFILES.balanced;
	$: if (!sourceUsers.some((user) => user.id === sourceUserId)) {
		sourceUserId = sourceUsers.some((user) => user.id === selectedUserId)
			? selectedUserId
			: (sourceUsers[0]?.id || null);
	}
	$: sourceUser = users.find((user) => user.id === sourceUserId);
	$: canPreview = !!sourceUser?.embyGuid && selectedSeeds.length > 0;
	$: canCreate = canPreview && !!collectionName.trim() && recommendations.length > 0 && !createBusy;

	$: if (sourceUser?.embyGuid) {
		loadRecentActivity(sourceUser.embyGuid);
	}

	let lastRecentUserId = '';

	async function loadRecentActivity(embyGuid) {
		if (!embyGuid || lastRecentUserId === embyGuid) return;
		lastRecentUserId = embyGuid;
		recentBusy = true;
		recentError = '';
		recentItems = [];

		try {
			const params = new URLSearchParams({ embyGuid });
			const response = await fetch(`/api/emby-user-context?${params.toString()}`);
			const body = await response.json().catch(() => ({}));
			if (!response.ok) throw new Error(body.message || body.error || response.statusText);
			const activity = Array.isArray(body.recentlyPlayed) ? body.recentlyPlayed : [];
			recentItems = activity.filter((item) => item.type === 'Movie' || item.type === 'Series');
		} catch (error) {
			recentError = error.message;
		} finally {
			recentBusy = false;
		}
	}

	function toggleTargetUser(userId) {
		if (targetUserIds.includes(userId)) {
			targetUserIds = targetUserIds.filter((id) => id !== userId);
		} else {
			targetUserIds = [...targetUserIds, userId];
		}
	}

	function addSeed(item) {
		if (!item?.id || selectedSeeds.some((seed) => seed.id === item.id)) return;
		selectedSeeds = [...selectedSeeds, item];
		recommendations = [];
		existingCollection = null;
		actionError = '';
		actionMessage = '';
	}

	function removeSeed(seedId) {
		selectedSeeds = selectedSeeds.filter((seed) => seed.id !== seedId);
		recommendations = [];
		existingCollection = null;
	}

	function handleProfileChange() {
		recommendations = [];
		existingCollection = null;
		actionError = '';
		actionMessage = '';
	}

	function logPreviewDiagnostics(requestPayload, responseBody) {
		if (typeof window === 'undefined') return;

		const diagnostics = responseBody?.diagnostics || {};
		const perSeed = Array.isArray(diagnostics.perSeed) ? diagnostics.perSeed : [];

		console.groupCollapsed('[Collections] Recommendation preview');
		console.info('Request', requestPayload);
		console.info('Response summary', {
			profile: responseBody?.profile,
			recommendationCount: (responseBody?.recommendations || []).length,
			libraryItemCount: diagnostics.libraryItemCount ?? 0,
			watchedItemCount: diagnostics.watchedItemCount ?? 0,
			seedCount: diagnostics.seedCount ?? 0,
			embyCandidates: diagnostics.embyCandidates ?? 0,
			tmdbEnabled: diagnostics.tmdbEnabled ?? false,
			tmdbCandidates: diagnostics.tmdbCandidates ?? 0,
			tmdbResolved: diagnostics.tmdbResolved ?? 0,
			uniqueCandidateCount: diagnostics.uniqueCandidateCount ?? 0,
			excludedSeedCandidateCount: diagnostics.excludedSeedCandidateCount ?? 0
		});
		console.info('Seeds returned by API', responseBody?.seeds || []);
		if ((diagnostics.sampleExcludedSeedCandidates || []).length) {
			console.warn('Candidates dropped because they resolved back onto the seed items', diagnostics.sampleExcludedSeedCandidates);
		}
		if (perSeed.length) {
			console.table(
				perSeed.map((seed) => ({
					seed: seed.seedName,
					type: seed.seedType,
					year: seed.seedYear,
					tmdbProviderId: seed.providerTmdbId || '',
					tmdbMatchId: seed.tmdbMatch?.tmdbId || '',
					tmdbMediaType: seed.tmdbMatch?.mediaType || '',
					similar: seed.similarCount ?? 0,
					recommendations: seed.recommendationCount ?? 0,
					localSimilar: seed.localSimilarCount ?? 0,
					localRecommendations: seed.localRecommendationCount ?? 0,
					error: seed.error || ''
				}))
			);
			console.info('Per-seed detail', perSeed);
		}
		if ((diagnostics.discoverQueries || []).length) {
			console.table(
				diagnostics.discoverQueries.map((query) => ({
					query: query.label,
					tmdbCount: query.tmdbCount,
					localCount: query.localCount,
					error: query.error || ''
				}))
			);
			console.info('Discover query detail', diagnostics.discoverQueries);
		}
		if ((responseBody?.recommendations || []).length) {
			console.info('Recommendations', responseBody.recommendations);
		}
		console.groupEnd();
	}

	async function searchItems(type) {
		const searchTerm = type === 'Movie' ? movieSearchTerm.trim() : showSearchTerm.trim();
		if (!sourceUser?.embyGuid) {
			if (type === 'Movie') movieSearchError = 'Select a source user first.';
			else showSearchError = 'Select a source user first.';
			return;
		}
		if (!searchTerm) {
			if (type === 'Movie') movieResults = [];
			else showResults = [];
			return;
		}

		if (type === 'Movie') {
			movieSearchBusy = true;
			movieSearchError = '';
		} else {
			showSearchBusy = true;
			showSearchError = '';
		}

		try {
			const params = new URLSearchParams({
				userId: sourceUser.embyGuid,
				term: searchTerm,
				types: type,
				limit: '10'
			});
			const response = await fetch(`/api/emby-item-search?${params.toString()}`);
			const body = await response.json().catch(() => ({ items: [] }));
			if (!response.ok) throw new Error(body.message || body.error || response.statusText);
			if (type === 'Movie') movieResults = body.items || [];
			else showResults = body.items || [];
		} catch (error) {
			if (type === 'Movie') {
				movieSearchError = error.message;
				movieResults = [];
			} else {
				showSearchError = error.message;
				showResults = [];
			}
		} finally {
			if (type === 'Movie') movieSearchBusy = false;
			else showSearchBusy = false;
		}
	}

	async function previewRecommendations() {
		if (!canPreview) return;
		previewBusy = true;
		actionError = '';
		actionMessage = '';
		const requestPayload = {
			mode: 'preview',
			userId: sourceUser.embyGuid,
			seedIds: selectedSeeds.map((seed) => seed.id),
			seeds: selectedSeeds.map((seed) => ({
				id: seed.id,
				name: seed.name,
				type: seed.type,
				year: seed.year
			})),
			name: collectionName.trim(),
			limit: recommendationLimit,
			profile: recommendationProfile
		};

		try {
			const response = await fetch('/api/emby-collections', {
				method: 'POST',
				headers: { 'Content-Type': 'application/json' },
				body: JSON.stringify(requestPayload)
			});
			const body = await response.json().catch(() => ({}));
			if (!response.ok) throw new Error(body.message || body.error || response.statusText);
			logPreviewDiagnostics(requestPayload, body);
			recommendations = body.recommendations || [];
			existingCollection = body.collection || null;
			if (recommendations.length) {
				actionMessage = existingCollection?.updated
					? `Generated ${recommendations.length} recommendations. Re-running create will update "${existingCollection.name}".`
					: `Generated ${recommendations.length} recommendations.`;
			} else if (body?.diagnostics?.tmdbEnabled && body?.diagnostics?.tmdbCandidates > 0 && body?.diagnostics?.tmdbResolved === 0) {
				actionMessage = 'TMDB found similar titles, but none of them matched items currently in your Emby library.';
			} else {
				actionMessage = 'No recommendations were returned for these seeds.';
			}
		} catch (error) {
			console.error('[Collections] Recommendation preview failed', {
				request: requestPayload,
				error
			});
			actionError = error.message;
			recommendations = [];
			existingCollection = null;
		} finally {
			previewBusy = false;
		}
	}

	async function createCollection() {
		if (!canCreate) return;
		createBusy = true;
		actionError = '';
		actionMessage = '';

		try {
			const response = await fetch('/api/emby-collections', {
				method: 'POST',
				headers: { 'Content-Type': 'application/json' },
				body: JSON.stringify({
					mode: 'create',
					userId: sourceUser.embyGuid,
					name: collectionName.trim(),
					seedIds: selectedSeeds.map((seed) => seed.id),
					limit: recommendationLimit,
					includeSeeds,
					profile: recommendationProfile
				})
			});
			const body = await response.json().catch(() => ({}));
			if (!response.ok) throw new Error(body.message || body.error || response.statusText);

			dispatch('created', {
				collection: body.collection,
				targetUserIds,
				seeds: selectedSeeds,
				recommendations: body.recommendations || []
			});
			existingCollection = body.collection || null;
			actionMessage = body.collection?.updated
				? `Updated collection "${body.collection.name}".`
				: `Created collection "${body.collection?.name || collectionName.trim()}".`;
		} catch (error) {
			actionError = error.message;
		} finally {
			createBusy = false;
		}
	}
</script>

<div class="collection-page">
	<div class="page-header">
		<div>
			<div class="page-title-row">
				<span class="page-icon"><Icon name="collections" size={18} /></span>
				<h2>Collections</h2>
			</div>
			<p class="page-copy">Build recommendation collections from recent activity, seed movies, and seed shows.</p>
		</div>
		<div class="page-actions">
			<label class="field-inline compact field-select">
				<span>Profile</span>
				<select bind:value={recommendationProfile} on:change={handleProfileChange}>
					{#each profileOptions as profile}
						<option value={profile.id}>{profile.label}</option>
					{/each}
				</select>
			</label>
			<label class="field-inline compact">
				<input type="checkbox" bind:checked={includeSeeds} />
				<span>Include seeds in collection</span>
			</label>
			<label class="field-inline compact">
				<span>Recommendation count</span>
				<select bind:value={recommendationLimit}>
					<option value={12}>12</option>
					<option value={18}>18</option>
					<option value={24}>24</option>
					<option value={30}>30</option>
				</select>
			</label>
		</div>
	</div>

	<div class="builder-grid">
			<div class="builder-main">
			<div class="builder-card hero-card">
				<div class="field-grid">
					<label class="field">
						<span class="field-label">Source user</span>
						<select bind:value={sourceUserId}>
							{#each sourceUsers as user}
								<option value={user.id}>{user.name}</option>
							{/each}
						</select>
					</label>
					<label class="field">
						<span class="field-label">Collection name</span>
						<input type="text" bind:value={collectionName} placeholder="Recommended for Family Night" />
					</label>
				</div>
				<p class="profile-note">{selectedProfile.description}</p>
			</div>

			<div class="seed-grid">
				<section class="builder-card">
					<div class="card-header">
						<div class="card-title-row">
							<Icon name="activity" size={16} />
							<h3>Watched Activity</h3>
						</div>
						<span class="card-copy">Quick-add from recent movies and shows.</span>
					</div>
					{#if recentError}
						<div class="status error">{recentError}</div>
					{:else if recentBusy}
						<div class="status">Loading recent activity…</div>
					{:else if recentItems.length}
						<div class="result-list">
							{#each recentItems as item}
								<button class="result-card" on:click={() => addSeed(item)}>
									<div class="result-name">{item.name}</div>
									<div class="result-meta">{item.type}{item.datePlayed ? ` · ${new Date(item.datePlayed).toLocaleDateString()}` : ''}</div>
								</button>
							{/each}
						</div>
					{:else}
						<div class="empty-note">No recent movie or show activity was available for this user.</div>
					{/if}
				</section>

				<section class="builder-card">
					<div class="card-header">
						<div class="card-title-row">
							<Icon name="search" size={16} />
							<h3>Seed Movies</h3>
						</div>
						<span class="card-copy">Search Emby and add movie seeds.</span>
					</div>
					<div class="lookup-row">
						<input
							type="text"
							bind:value={movieSearchTerm}
							on:keydown={(event) => event.key === 'Enter' && searchItems('Movie')}
							placeholder="Search movies..."
						/>
						<button class="btn ghost" on:click={() => searchItems('Movie')} disabled={movieSearchBusy}>
							{movieSearchBusy ? 'Searching…' : 'Search'}
						</button>
					</div>
					{#if movieSearchError}
						<div class="status error">{movieSearchError}</div>
					{/if}
					{#if movieResults.length}
						<div class="result-list">
							{#each movieResults as item}
								<button class="result-card" on:click={() => addSeed(item)}>
									<div class="result-name">{item.name}</div>
									<div class="result-meta">{item.year ? `${item.year} · ` : ''}{item.type}</div>
								</button>
							{/each}
						</div>
					{/if}
				</section>

				<section class="builder-card">
					<div class="card-header">
						<div class="card-title-row">
							<Icon name="search" size={16} />
							<h3>Seed Shows</h3>
						</div>
						<span class="card-copy">Search Emby and add TV seeds.</span>
					</div>
					<div class="lookup-row">
						<input
							type="text"
							bind:value={showSearchTerm}
							on:keydown={(event) => event.key === 'Enter' && searchItems('Series')}
							placeholder="Search shows..."
						/>
						<button class="btn ghost" on:click={() => searchItems('Series')} disabled={showSearchBusy}>
							{showSearchBusy ? 'Searching…' : 'Search'}
						</button>
					</div>
					{#if showSearchError}
						<div class="status error">{showSearchError}</div>
					{/if}
					{#if showResults.length}
						<div class="result-list">
							{#each showResults as item}
								<button class="result-card" on:click={() => addSeed(item)}>
									<div class="result-name">{item.name}</div>
									<div class="result-meta">{item.year ? `${item.year} · ` : ''}{item.type}</div>
								</button>
							{/each}
						</div>
					{/if}
				</section>
			</div>
		</div>

		<div class="builder-side">
			<section class="builder-card sticky-card">
				<div class="card-header">
					<div class="card-title-row">
						<Icon name="spark" size={16} />
						<h3>Selected Seeds</h3>
					</div>
					<span class="card-copy">Mix watched activity with manual seeds.</span>
				</div>
				{#if selectedSeeds.length}
					<div class="seed-list">
						{#each selectedSeeds as item}
							<div class="seed-chip">
								<div>
									<div class="result-name">{item.name}</div>
									<div class="result-meta">{item.type}{item.year ? ` · ${item.year}` : ''}</div>
								</div>
								<button class="remove-btn" on:click={() => removeSeed(item.id)}>×</button>
							</div>
						{/each}
					</div>
				{:else}
					<div class="empty-note">Add at least one seed to generate recommendations.</div>
				{/if}

				<div class="divider"></div>

				<div class="card-header compact">
					<div class="card-title-row">
						<Icon name="boxset" size={16} />
						<h3>Apply Section To</h3>
					</div>
				</div>
				<div class="target-list">
					{#each users.filter((user) => user.embyGuid) as user}
						<label class="target-option" class:selected={targetUserIds.includes(user.id)}>
							<input
								type="checkbox"
								checked={targetUserIds.includes(user.id)}
								on:change={() => toggleTargetUser(user.id)}
							/>
							<span>{user.name}</span>
							<span class="target-count">{user.sections?.length || 0} sections</span>
						</label>
					{/each}
				</div>

				{#if recommendations.length}
					<div class="divider"></div>
					<div class="card-header compact">
						<div class="card-title-row">
							<Icon name="collections" size={16} />
							<h3>Recommendation Preview</h3>
						</div>
					</div>
					<div class="preview-list">
						{#each recommendations as item}
							<div class="preview-item">
								<div class="result-name">{item.name}</div>
								<div class="result-meta">
									{item.type}{item.year ? ` · ${item.year}` : ''} · matched {item.matchCount}
									{#if item.styleScore !== null && item.styleScore !== undefined}
										· style {item.styleScore}
									{/if}
									{#if item.qualityScore !== null && item.qualityScore !== undefined}
										· quality {item.qualityScore}
									{/if}
								</div>
							</div>
						{/each}
					</div>
				{/if}

				{#if existingCollection?.id}
					<div class="divider"></div>
					<div class="status">
						Collection target: {existingCollection.name} · existing box set will be updated
					</div>
				{/if}

				{#if actionError}
					<div class="status error">{actionError}</div>
				{:else if actionMessage}
					<div class="status ok">{actionMessage}</div>
				{/if}

				<div class="action-row">
					<button class="btn ghost" on:click={previewRecommendations} disabled={!canPreview || previewBusy || createBusy}>
						{previewBusy ? 'Generating…' : 'Preview Recommendations'}
					</button>
					<button class="btn accent" on:click={createCollection} disabled={!canCreate || previewBusy || createBusy}>
						{createBusy ? (existingCollection?.updated ? 'Updating…' : 'Creating…') : (existingCollection?.updated ? 'Update Collection' : 'Create Collection')}
					</button>
				</div>
			</section>
		</div>
	</div>
</div>

<style>
	.collection-page {
		display: flex;
		flex-direction: column;
		gap: 18px;
	}
	.page-header {
		display: flex;
		justify-content: space-between;
		gap: 16px;
		align-items: flex-start;
	}
	.page-title-row,
	.card-title-row {
		display: flex;
		align-items: center;
		gap: 10px;
	}
	h2,
	h3 {
		margin: 0;
		color: var(--text);
	}
	h2 {
		font-size: 24px;
		font-weight: 800;
	}
	h3 {
		font-size: 15px;
		font-weight: 800;
	}
	.page-copy,
	.card-copy {
		margin: 6px 0 0;
		font-size: 13px;
		line-height: 1.5;
		color: var(--text-muted);
	}
	.page-actions {
		display: flex;
		gap: 12px;
		flex-wrap: wrap;
	}
	.field-select {
		min-width: 220px;
	}
	.builder-grid {
		display: grid;
		grid-template-columns: minmax(0, 1.7fr) minmax(320px, 0.9fr);
		gap: 18px;
		align-items: start;
	}
	.builder-main,
	.builder-side,
	.seed-grid {
		display: flex;
		flex-direction: column;
		gap: 18px;
	}
	.seed-grid {
		display: grid;
		grid-template-columns: repeat(3, minmax(0, 1fr));
	}
	.builder-card {
		background: #0f1116;
		border: 1px solid var(--border);
		border-radius: 12px;
		padding: 18px;
	}
	.hero-card {
		padding-bottom: 14px;
	}
	.profile-note {
		margin: 12px 0 0;
		font-size: 12px;
		line-height: 1.5;
		color: var(--text-muted);
	}
	.sticky-card {
		position: sticky;
		top: 24px;
	}
	.card-header.compact {
		margin-bottom: 8px;
	}
	.field-grid {
		display: grid;
		grid-template-columns: 1fr 1fr;
		gap: 12px;
	}
	.field {
		display: flex;
		flex-direction: column;
		gap: 6px;
	}
	.field-label {
		font-size: 11px;
		font-weight: 700;
		text-transform: uppercase;
		letter-spacing: 0.08em;
		color: var(--text-muted);
	}
	.field-inline {
		display: flex;
		align-items: center;
		gap: 8px;
		color: var(--text);
		font-size: 13px;
	}
	.field-inline.compact {
		font-size: 12px;
	}
	input,
	select {
		width: 100%;
		box-sizing: border-box;
		padding: 10px 12px;
		border-radius: 10px;
		border: 1px solid var(--border);
		background: #12151b;
		color: var(--text);
		font-size: 13px;
		font-family: inherit;
	}
	input:focus,
	select:focus {
		outline: none;
		border-color: var(--border-strong);
	}
	.lookup-row {
		display: grid;
		grid-template-columns: minmax(0, 1fr) auto;
		gap: 10px;
		margin-top: 12px;
	}
	.result-list,
	.seed-list,
	.target-list,
	.preview-list {
		display: flex;
		flex-direction: column;
		gap: 8px;
		margin-top: 12px;
	}
	.result-card,
	.seed-chip,
	.target-option,
	.preview-item {
		border: 1px solid var(--border);
		border-radius: 10px;
		background: #111419;
		padding: 12px 14px;
	}
	.result-card {
		all: unset;
		cursor: pointer;
		border: 1px solid var(--border);
		border-radius: 10px;
		background: #111419;
		padding: 12px 14px;
		transition: background 0.12s ease, border-color 0.12s ease;
	}
	.result-card:hover,
	.target-option:hover {
		background: var(--surface-hover);
		border-color: var(--border-strong);
	}
	.result-name {
		font-size: 14px;
		font-weight: 600;
		color: var(--text);
	}
	.result-meta,
	.target-count {
		font-size: 12px;
		color: var(--text-muted);
	}
	.seed-chip,
	.target-option {
		display: flex;
		align-items: center;
		justify-content: space-between;
		gap: 12px;
	}
	.target-option {
		cursor: pointer;
	}
	.target-option.selected {
		background: var(--surface-active);
		border-color: var(--border-strong);
	}
	.preview-item {
		display: flex;
		flex-direction: column;
		gap: 4px;
	}
	.remove-btn {
		all: unset;
		cursor: pointer;
		color: var(--text-muted);
		font-size: 20px;
		line-height: 1;
	}
	.remove-btn:hover {
		color: var(--danger);
	}
	.empty-note {
		padding: 14px;
		border-radius: 10px;
		background: #111419;
		border: 1px dashed var(--border);
		color: var(--text-muted);
		font-size: 13px;
		margin-top: 12px;
	}
	.divider {
		height: 1px;
		background: rgba(148, 163, 184, 0.1);
		margin: 16px 0;
	}
	.action-row {
		display: flex;
		flex-direction: column;
		gap: 10px;
		margin-top: 16px;
	}
	.status {
		padding: 10px 12px;
		border-radius: 10px;
		font-size: 12px;
		background: #111419;
		border: 1px solid var(--border);
		color: var(--text-muted);
		margin-top: 12px;
	}
	.status.ok {
		border-color: rgba(34, 197, 94, 0.3);
		color: #86efac;
	}
	.status.error {
		border-color: rgba(239, 68, 68, 0.3);
		color: #fca5a5;
	}
	.btn {
		all: unset;
		cursor: pointer;
		padding: 9px 16px;
		border-radius: 10px;
		font-size: 13px;
		font-weight: 600;
		font-family: inherit;
		border: 1px solid transparent;
		text-align: center;
	}
	.btn.ghost {
		color: var(--text);
		border-color: var(--border);
		background: #15181e;
	}
	.btn.accent {
		background: var(--accent);
		border-color: rgba(42, 215, 239, 0.35);
		color: #031014;
	}
	.btn:disabled {
		opacity: 0.45;
		cursor: default;
	}
	.page-icon {
		display: inline-flex;
		align-items: center;
		justify-content: center;
		width: 34px;
		height: 34px;
		border-radius: 8px;
		background: rgba(40, 193, 220, 0.1);
		color: var(--accent);
	}

	@media (max-width: 1100px) {
		.builder-grid {
			grid-template-columns: 1fr;
		}
		.sticky-card {
			position: static;
		}
	}

	@media (max-width: 860px) {
		.seed-grid,
		.field-grid,
		.lookup-row {
			grid-template-columns: 1fr;
		}
		.page-header {
			flex-direction: column;
		}
		.page-actions {
			width: 100%;
		}
	}
</style>
