/**
 * <folk-campaign-manager> — Campaign viewer/editor with import modal and AI generator.
 *
 * Subscribes to Automerge doc for campaign data. Falls back to MYCOFI_CAMPAIGN
 * demo data when no campaigns exist or space=demo.
 */

import { socialsSchema, socialsDocId } from '../schemas';
import type { SocialsDoc, Campaign, CampaignPost } from '../schemas';
import type { DocumentId } from '../../../shared/local-first/document';
import { MYCOFI_CAMPAIGN, PLATFORM_ICONS, PLATFORM_COLORS } from '../campaign-data';
import { TourEngine } from '../../../shared/tour-engine';

export class FolkCampaignManager extends HTMLElement {
	private _space = 'demo';
	private _campaigns: Campaign[] = [];
	private _offlineUnsub: (() => void) | null = null;
	private _subscribedDocIds: string[] = [];

	// AI generation state
	private _generatedCampaign: Campaign | null = null;
	private _previewMode = false;
	private _generating = false;
	private _lastBrief = '';

	// Guided tour
	private _tour!: TourEngine;
	private static readonly TOUR_STEPS = [
		{ target: '.campaign-header', title: "Campaign Overview", message: "This is your campaign dashboard — see the title, description, platforms, and post count at a glance.", advanceOnClick: false },
		{ target: '.phase:first-of-type', title: "View Posts by Phase", message: "Posts are organised into phases. Each phase has a timeline and its own set of scheduled posts.", advanceOnClick: false },
		{ target: 'a[href*="thread-editor"]', title: "Open Thread Editor", message: "Jump to the thread editor to compose and preview tweet threads with live card preview.", advanceOnClick: true },
		{ target: '#generate-btn', title: "AI Campaign Generator", message: "Paste event details and let AI create a full campaign.", advanceOnClick: true },
		{ target: '#import-md-btn', title: "Import from Markdown", message: "Paste tweets separated by --- to bulk-import content into the campaign.", advanceOnClick: true },
	];

	static get observedAttributes() { return ['space']; }

	connectedCallback() {
		if (!this.shadowRoot) this.attachShadow({ mode: 'open' });
		this._tour = new TourEngine(
			this.shadowRoot!,
			FolkCampaignManager.TOUR_STEPS,
			"rsocials_tour_done",
			() => this.shadowRoot!.querySelector('.container') as HTMLElement,
		);
		this._space = this.getAttribute('space') || 'demo';
		// Start with demo campaign
		this._campaigns = [{ ...MYCOFI_CAMPAIGN, createdAt: Date.now(), updatedAt: Date.now() }];
		this.render();
		if (this._space !== 'demo') {
			this.subscribeOffline();
		}
		// Auto-start tour on first visit
		if (!localStorage.getItem("rsocials_tour_done")) {
			setTimeout(() => this._tour.start(), 1200);
		}
	}

	disconnectedCallback() {
		this._offlineUnsub?.();
		this._offlineUnsub = null;
		const runtime = (window as any).__rspaceOfflineRuntime;
		if (runtime) {
			for (const id of this._subscribedDocIds) runtime.unsubscribe(id);
		}
		this._subscribedDocIds = [];
	}

	attributeChangedCallback(name: string, _old: string, val: string) {
		if (name === 'space') this._space = val;
	}

	private async subscribeOffline() {
		const runtime = (window as any).__rspaceOfflineRuntime;
		if (!runtime?.isInitialized) return;

		try {
			const docId = socialsDocId(this._space) as DocumentId;
			const doc = await runtime.subscribe(docId, socialsSchema);
			this._subscribedDocIds.push(docId);
			this.renderFromDoc(doc);

			this._offlineUnsub = runtime.onChange(docId, (updated: any) => {
				this.renderFromDoc(updated);
			});
		} catch {
			// Runtime unavailable — use demo data
		}
	}

	private renderFromDoc(doc: SocialsDoc) {
		if (!doc?.campaigns || Object.keys(doc.campaigns).length === 0) return;
		this._campaigns = Object.values(doc.campaigns).sort((a, b) => b.updatedAt - a.updatedAt);
		this.render();
	}

	private saveCampaignToDoc(campaign: Campaign) {
		const runtime = (window as any).__rspaceOfflineRuntime;
		if (!runtime?.isInitialized) return;

		const docId = socialsDocId(this._space) as DocumentId;
		runtime.change(docId, `Save campaign ${campaign.title}`, (d: SocialsDoc) => {
			if (!d.campaigns) d.campaigns = {} as any;
			campaign.updatedAt = Date.now();
			d.campaigns[campaign.id] = campaign;
		});
	}

	private get basePath() {
		const host = window.location.hostname;
		if (host.endsWith('.rspace.online') || host.endsWith('.rsocials.online')) {
			return '/rsocials/';
		}
		return `/${this._space}/rsocials/`;
	}

	private esc(s: string): string {
		return s.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;');
	}

	private renderPostCard(post: CampaignPost): string {
		const icon = PLATFORM_ICONS[post.platform] || post.platform;
		const color = PLATFORM_COLORS[post.platform] || '#64748b';
		const statusClass = post.status === 'scheduled' ? 'status--scheduled' : 'status--draft';
		const date = new Date(post.scheduledAt);
		const dateStr = date.toLocaleDateString('en-US', { month: 'short', day: 'numeric', hour: 'numeric', minute: '2-digit' });
		const isLong = post.content.length > 180;
		const contentPreview = isLong ? this.esc(post.content.substring(0, 180)) + '...' : this.esc(post.content);
		const fullContent = this.esc(post.content);
		const tags = post.hashtags.map(h => `<span class="tag">#${this.esc(h)}</span>`).join(' ');

		// Thread badge — links to thread editor if threadId exists
		let threadBadge = '';
		if (post.threadPosts && post.threadPosts.length > 0) {
			if (post.threadId) {
				threadBadge = `<a href="${this.basePath}thread-editor/${this.esc(post.threadId)}/edit" class="thread-badge thread-badge--link" data-post-id="${this.esc(post.id)}">🧵 ${post.threadPosts.length}-post thread — Edit</a>`;
			} else {
				threadBadge = `<span class="thread-badge" data-post-id="${this.esc(post.id)}">🧵 ${post.threadPosts.length}-post thread</span>`;
			}
		}

		// Email subject for newsletter
		let emailLine = '';
		if (post.emailSubject) {
			emailLine = `<div class="post__email-subject">📧 ${this.esc(post.emailSubject)}</div>`;
		}

		// Thread expansion area
		let threadExpansion = '';
		if (post.threadPosts && post.threadPosts.length > 0) {
			const threadItems = post.threadPosts.map((t, i) =>
				`<div class="thread-post"><span class="thread-post__num">${i + 1}.</span> ${this.esc(t)}</div>`
			).join('');
			threadExpansion = `<div class="thread-expansion" id="thread-${this.esc(post.id)}" hidden>${threadItems}</div>`;
		}

		// "Open Thread" link for posts with created threads
		let threadLink = '';
		if (post.threadId && !(post.threadPosts && post.threadPosts.length > 0)) {
			threadLink = `<a href="${this.basePath}thread-editor/${this.esc(post.threadId)}/edit" class="post__thread-link">Open Thread</a>`;
		}

		return `
		<div class="post" data-platform="${this.esc(post.platform)}" data-post-id="${this.esc(post.id)}">
			<div class="post__header">
				<span class="post__platform" style="background:${color}">${icon}</span>
				<div class="post__meta">
					<strong>${this.esc(post.platform)} — ${this.esc(post.postType)}</strong>
					<span class="post__date">${dateStr}</span>
				</div>
				<span class="status ${statusClass}">${this.esc(post.status)}</span>
			</div>
			${emailLine}
			<div class="post__step">Step ${post.stepNumber}</div>
			<p class="post__content" data-preview="${contentPreview.replace(/"/g, '&quot;')}" data-full="${fullContent.replace(/"/g, '&quot;')}" data-collapsed="true">${contentPreview.replace(/\n/g, '<br>')}</p>
			${threadBadge}
			${threadExpansion}
			${threadLink}
			<div class="post__tags">${tags}</div>
		</div>`;
	}

	private renderCampaign(c: Campaign): string {
		// Dynamically derive phase numbers from campaign data
		const phaseNumbers = [...new Set(c.posts.map(p => p.phase))].sort((a, b) => a - b);
		// If no posts have phases, fall back to the phases array indices
		const phases = phaseNumbers.length > 0 ? phaseNumbers : c.phases.map((_, i) => i + 1);
		const phaseIcons = ['📣', '🚀', '📡', '🎯', '📈'];

		const phaseHTML = phases.map((phaseNum, i) => {
			const phasePosts = c.posts.filter(p => p.phase === phaseNum);
			const phaseInfo = c.phases[i] || { label: `Phase ${phaseNum}`, days: '' };
			if (!phasePosts.length) return '';

			const postsHTML = phasePosts.map(post => this.renderPostCard(post)).join('');

			return `
			<div class="phase">
				<h3 class="phase__title">${phaseIcons[i] || '📋'} Phase ${phaseNum}: ${this.esc(phaseInfo.label)} <span class="phase__days">${this.esc(phaseInfo.days)}</span></h3>
				<div class="phase__posts">${postsHTML}</div>
			</div>`;
		}).join('');

		return `
		<div class="campaign-header">
			<span class="campaign-icon">🍄</span>
			<div>
				<h1 class="campaign-title">${this.esc(c.title)}</h1>
				<p class="campaign-desc">${this.esc(c.description)}</p>
				<div class="campaign-stats">
					<span>📅 ${this.esc(c.duration)}</span>
					<span>📱 ${c.platforms.join(', ')}</span>
					<span>📝 ${c.posts.length} posts across ${c.phases.length} phases</span>
				</div>
			</div>
		</div>
		<div class="actions">
			<a href="${this.basePath}thread-editor" class="btn btn--outline">Open Thread Editor</a>
			<button class="btn btn--accent" id="generate-btn">Generate from Brief</button>
			<button class="btn btn--primary" id="import-md-btn">Import from Markdown</button>
			<button class="btn btn--outline" id="btn-tour" style="margin-left:auto">Tour</button>
		</div>
		${phaseHTML}
		<div id="imported-posts"></div>`;
	}

	private renderPreviewBanner(): string {
		return `
		<div class="preview-banner">
			<span class="preview-banner__label">AI-Generated Campaign Preview</span>
			<div class="preview-banner__actions">
				<button class="btn btn--primary btn--sm" id="preview-save">Save to Space</button>
				<button class="btn btn--accent btn--sm" id="preview-regenerate">Regenerate</button>
				<button class="btn btn--outline btn--sm" id="preview-discard">Discard</button>
			</div>
		</div>`;
	}

	private render() {
		if (!this.shadowRoot) return;

		let contentHTML: string;
		if (this._previewMode && this._generatedCampaign) {
			contentHTML = this.renderPreviewBanner() + this.renderCampaign(this._generatedCampaign);
		} else {
			const c = this._campaigns[0] || { ...MYCOFI_CAMPAIGN, createdAt: Date.now(), updatedAt: Date.now() };
			contentHTML = this.renderCampaign(c);
		}

		const allPlatforms = ['x', 'linkedin', 'instagram', 'youtube', 'threads', 'bluesky', 'newsletter'];

		this.shadowRoot.innerHTML = `
			<style>
				:host { display: block; }
				.container { max-width: 900px; margin: 0 auto; padding: 2rem 1rem; }
				.campaign-header { display: flex; align-items: flex-start; gap: 1rem; margin-bottom: 2rem; padding-bottom: 1.5rem; border-bottom: 1px solid var(--rs-input-border, #334155); }
				.campaign-icon { font-size: 3rem; }
				.campaign-title { margin: 0; font-size: 1.5rem; color: var(--rs-text-primary, #f1f5f9); }
				.campaign-desc { margin: 0.25rem 0 0.5rem; color: var(--rs-text-secondary, #94a3b8); font-size: 0.9rem; line-height: 1.5; }
				.campaign-stats { display: flex; flex-wrap: wrap; gap: 1rem; font-size: 0.8rem; color: var(--rs-text-muted, #64748b); }
				.phase { margin-bottom: 2rem; }
				.phase__title { font-size: 1.15rem; color: var(--rs-text-primary, #f1f5f9); margin: 0 0 1rem; display: flex; align-items: center; gap: 0.5rem; }
				.phase__days { font-size: 0.8rem; color: var(--rs-text-muted, #64748b); font-weight: 400; }
				.phase__posts { display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); gap: 0.75rem; }
				.post {
					background: var(--rs-bg-surface, #1e293b); border: 1px solid var(--rs-input-border, #334155); border-radius: 0.75rem; padding: 1rem;
					transition: border-color 0.15s;
				}
				.post:hover { border-color: var(--rs-primary); }
				.post__header { display: flex; align-items: center; gap: 0.5rem; margin-bottom: 0.5rem; }
				.post__platform {
					width: 28px; height: 28px; border-radius: 6px; display: flex; align-items: center; justify-content: center;
					color: white; font-size: 0.75rem; font-weight: 700; flex-shrink: 0;
				}
				.post__meta { flex: 1; min-width: 0; }
				.post__meta strong { display: block; font-size: 0.8rem; color: var(--rs-text-primary, #f1f5f9); text-transform: capitalize; }
				.post__date { font-size: 0.7rem; color: var(--rs-text-muted, #64748b); }
				.post__step { font-size: 0.65rem; color: var(--rs-primary); font-weight: 600; text-transform: uppercase; letter-spacing: 0.05em; margin-bottom: 0.5rem; }
				.status { font-size: 0.6rem; padding: 2px 6px; border-radius: 4px; text-transform: uppercase; font-weight: 600; letter-spacing: 0.05em; white-space: nowrap; }
				.status--scheduled { background: rgba(16,185,129,0.15); color: #34d399; }
				.status--draft { background: rgba(251,191,36,0.15); color: #fbbf24; }
				.post__content { font-size: 0.8rem; color: var(--rs-text-secondary, #94a3b8); line-height: 1.5; margin: 0 0 0.5rem; }
				.post__tags { display: flex; flex-wrap: wrap; gap: 0.25rem; }
				.tag { font-size: 0.65rem; color: var(--rs-primary); }
				.post__email-subject { font-size: 0.75rem; color: #a78bfa; font-weight: 600; margin-bottom: 0.4rem; padding: 0.25rem 0.5rem; background: rgba(167,139,250,0.1); border-radius: 4px; }
				.thread-badge {
					display: inline-block; font-size: 0.7rem; color: #60a5fa; background: rgba(96,165,250,0.12);
					padding: 2px 8px; border-radius: 4px; margin-bottom: 0.4rem; cursor: pointer;
					transition: background 0.15s;
				}
				.thread-badge:hover { background: rgba(96,165,250,0.25); }
				.thread-badge--link { border: 1px solid rgba(96,165,250,0.3); text-decoration: none; }
				.thread-badge--link:hover { border-color: #60a5fa; }
				.post { cursor: pointer; }
				.post__content[data-collapsed="false"] { display: block; -webkit-line-clamp: unset; overflow: visible; white-space: normal; }
				.post__thread-link {
					display: inline-block; font-size: 0.7rem; color: #14b8a6; text-decoration: none;
					padding: 2px 8px; border-radius: 4px; margin-bottom: 0.4rem;
					background: rgba(20,184,166,0.1); border: 1px solid rgba(20,184,166,0.2);
					transition: background 0.15s, border-color 0.15s;
				}
				.post__thread-link:hover { background: rgba(20,184,166,0.2); border-color: #14b8a6; }
				.thread-expansion { margin: 0.4rem 0; padding: 0.5rem; background: var(--rs-input-bg, #0f172a); border-radius: 6px; border: 1px solid var(--rs-input-border, #334155); }
				.thread-expansion[hidden] { display: none; }
				.thread-post { font-size: 0.75rem; color: var(--rs-text-secondary, #94a3b8); padding: 0.3rem 0; border-bottom: 1px solid rgba(51,65,85,0.5); line-height: 1.4; }
				.thread-post:last-child { border-bottom: none; }
				.thread-post__num { color: var(--rs-primary); font-weight: 600; margin-right: 0.3rem; }
				.actions { display: flex; flex-wrap: wrap; gap: 0.75rem; margin-bottom: 1.5rem; }
				.btn {
					padding: 0.5rem 1rem; border-radius: 8px; font-size: 0.85rem; font-weight: 600;
					cursor: pointer; transition: all 0.15s; text-decoration: none; display: inline-flex; align-items: center; gap: 0.4rem;
				}
				.btn--sm { padding: 0.35rem 0.75rem; font-size: 0.8rem; }
				.btn--primary { background: var(--rs-primary); color: white; border: none; }
				.btn--primary:hover { background: var(--rs-primary-hover); }
				.btn--accent { background: var(--rs-gradient-primary, linear-gradient(135deg, #6366f1, #8b5cf6)); color: white; border: none; }
				.btn--accent:hover { opacity: 0.9; }
				.btn--outline { background: transparent; color: var(--rs-text-secondary, #94a3b8); border: 1px solid var(--rs-input-border, #334155); }
				.btn--outline:hover { border-color: var(--rs-primary); color: var(--rs-primary-hover, #c4b5fd); }
				.btn:disabled { opacity: 0.5; cursor: not-allowed; }

				/* Preview banner */
				.preview-banner {
					display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: 0.75rem;
					padding: 0.75rem 1rem; margin-bottom: 1.5rem; border-radius: 8px;
					background: linear-gradient(135deg, rgba(99,102,241,0.15), rgba(139,92,246,0.15));
					border: 1px solid rgba(99,102,241,0.3);
				}
				.preview-banner__label { font-size: 0.85rem; font-weight: 600; color: #a78bfa; }
				.preview-banner__actions { display: flex; gap: 0.5rem; }

				/* Modals */
				.modal-overlay {
					position: fixed; inset: 0; background: rgba(0,0,0,0.6); display: flex;
					align-items: center; justify-content: center; z-index: 1000;
				}
				.modal-overlay[hidden] { display: none; }
				.modal {
					background: var(--rs-bg-surface, #1e293b); border: 1px solid var(--rs-input-border, #334155); border-radius: 0.75rem;
					padding: 1.5rem; width: 90%; max-width: 580px; display: flex; flex-direction: column; gap: 1rem;
					max-height: 90vh; overflow-y: auto;
				}
				.modal__header { display: flex; align-items: center; justify-content: space-between; }
				.modal__header h3 { margin: 0; font-size: 1.1rem; color: var(--rs-text-primary, #f1f5f9); }
				.modal__close {
					background: none; border: none; color: var(--rs-text-muted, #64748b); font-size: 1.5rem; cursor: pointer;
					line-height: 1; padding: 0;
				}
				.modal__close:hover { color: var(--rs-text-primary, #f1f5f9); }
				.modal__textarea {
					width: 100%; min-height: 160px; background: var(--rs-input-bg, #0f172a); color: var(--rs-input-text, #f1f5f9); border: 1px solid var(--rs-input-border, #334155);
					border-radius: 8px; padding: 0.75rem; font-family: inherit; font-size: 0.85rem; resize: vertical;
					line-height: 1.5; box-sizing: border-box;
				}
				.modal__textarea:focus { outline: none; border-color: var(--rs-primary); }
				.modal__textarea::placeholder { color: var(--rs-text-muted, #64748b); }
				.modal__row { display: flex; gap: 0.75rem; align-items: center; flex-wrap: wrap; }
				.modal__select {
					flex: 1; background: var(--rs-input-bg, #0f172a); color: var(--rs-input-text, #f1f5f9); border: 1px solid var(--rs-input-border, #334155);
					border-radius: 8px; padding: 0.5rem 0.75rem; font-size: 0.85rem; min-width: 120px;
				}
				.modal__select:focus { outline: none; border-color: var(--rs-primary); }
				.modal__label { font-size: 0.8rem; color: var(--rs-text-secondary, #94a3b8); font-weight: 600; margin-bottom: 0.25rem; }
				.modal__section { display: flex; flex-direction: column; gap: 0.25rem; }

				/* Platform checkboxes */
				.platform-checks { display: flex; flex-wrap: wrap; gap: 0.5rem; }
				.platform-check { display: flex; align-items: center; gap: 0.3rem; }
				.platform-check input[type="checkbox"] { accent-color: var(--rs-primary, #6366f1); }
				.platform-check label { font-size: 0.8rem; color: var(--rs-text-secondary, #94a3b8); cursor: pointer; text-transform: capitalize; }

				/* Loading spinner */
				.spinner { display: inline-block; width: 14px; height: 14px; border: 2px solid rgba(255,255,255,0.3); border-top-color: white; border-radius: 50%; animation: spin 0.6s linear infinite; }
				@keyframes spin { to { transform: rotate(360deg); } }
				.gen-error { color: #f87171; font-size: 0.8rem; margin-top: 0.25rem; }
			</style>
			<div class="container">
				${contentHTML}
			</div>
			<div class="modal-overlay" id="import-modal" hidden>
				<div class="modal">
					<div class="modal__header">
						<h3>Import from Markdown</h3>
						<button class="modal__close" id="import-modal-close">&times;</button>
					</div>
					<textarea class="modal__textarea" id="import-md-textarea" placeholder="Paste tweets separated by ---\n\nFirst tweet\n---\nSecond tweet\n---\nThird tweet"></textarea>
					<div class="modal__row">
						<select class="modal__select" id="import-platform">
							<option value="twitter">Twitter / X</option>
							<option value="bluesky">Bluesky</option>
							<option value="mastodon">Mastodon</option>
							<option value="linkedin">LinkedIn</option>
						</select>
						<button class="btn btn--primary" id="import-parse-btn">Parse &amp; Add</button>
					</div>
				</div>
			</div>
			<div class="modal-overlay" id="generate-modal" hidden>
				<div class="modal">
					<div class="modal__header">
						<h3>Generate Campaign from Brief</h3>
						<button class="modal__close" id="generate-modal-close">&times;</button>
					</div>
					<div class="modal__section">
						<span class="modal__label">Event Brief</span>
						<textarea class="modal__textarea" id="gen-brief" placeholder="Paste your event details here, e.g.:\n\nWe're hosting a Regenerative Finance Summit on April 15, 2026 at the Vancouver Convention Centre. Featured speakers include Vitalik Buterin and Kevin Owocki. Topics: quadratic funding, impact certificates, token engineering. Registration opens March 20. Early bird tickets $99."></textarea>
					</div>
					<div class="modal__section">
						<span class="modal__label">Platforms</span>
						<div class="platform-checks" id="gen-platforms">
							${allPlatforms.map(p => `
								<label class="platform-check">
									<input type="checkbox" value="${p}" checked>
									<span>${PLATFORM_ICONS[p] || ''} ${p}</span>
								</label>
							`).join('')}
						</div>
					</div>
					<div class="modal__row">
						<div class="modal__section" style="flex:1">
							<span class="modal__label">Tone</span>
							<select class="modal__select" id="gen-tone">
								<option value="professional">Professional</option>
								<option value="casual">Casual</option>
								<option value="hype">Hype</option>
								<option value="educational">Educational</option>
								<option value="rebellious">Rebellious</option>
							</select>
						</div>
						<div class="modal__section" style="flex:1">
							<span class="modal__label">Style</span>
							<select class="modal__select" id="gen-style">
								<option value="event-promo">Event Promo</option>
								<option value="product-launch">Product Launch</option>
								<option value="awareness">Awareness</option>
								<option value="community">Community</option>
							</select>
						</div>
					</div>
					<div id="gen-error"></div>
					<button class="btn btn--accent" id="gen-submit" style="align-self:stretch;justify-content:center">
						Generate Campaign
					</button>
				</div>
			</div>
		`;

		this.bindEvents();
		this._tour.renderOverlay();
	}

	startTour() { this._tour.start(); }

	private bindEvents() {
		if (!this.shadowRoot) return;

		// Tour button
		this.shadowRoot.getElementById('btn-tour')?.addEventListener('click', () => this.startTour());

		// ── Import modal ──
		const importModal = this.shadowRoot.getElementById('import-modal') as HTMLElement;
		const importOpenBtn = this.shadowRoot.getElementById('import-md-btn');
		const importCloseBtn = this.shadowRoot.getElementById('import-modal-close');
		const parseBtn = this.shadowRoot.getElementById('import-parse-btn');
		const mdInput = this.shadowRoot.getElementById('import-md-textarea') as HTMLTextAreaElement;
		const platformSel = this.shadowRoot.getElementById('import-platform') as HTMLSelectElement;
		const importedEl = this.shadowRoot.getElementById('imported-posts');

		importOpenBtn?.addEventListener('click', () => { importModal.hidden = false; });
		importCloseBtn?.addEventListener('click', () => { importModal.hidden = true; });
		importModal?.addEventListener('click', (e) => { if (e.target === importModal) importModal.hidden = true; });

		parseBtn?.addEventListener('click', () => {
			const raw = mdInput.value;
			const tweets = raw.split(/\n---\n/).map(t => t.trim()).filter(Boolean);
			if (!tweets.length || !importedEl) return;
			const platform = platformSel.value;
			const total = tweets.length;

			const posts: CampaignPost[] = tweets.map((text, i) => ({
				id: `imported-${Date.now()}-${i}`,
				platform,
				postType: 'text',
				stepNumber: i + 1,
				content: text,
				scheduledAt: new Date().toISOString(),
				status: 'imported',
				hashtags: [],
				phase: 1,
				phaseLabel: 'Imported',
			}));

			let html = `<div class="phase"><h3 class="phase__title">📥 Imported Posts (${total})</h3>`;
			html += '<div class="phase__posts">';
			tweets.forEach((text, i) => {
				const preview = text.length > 180 ? this.esc(text.substring(0, 180)) + '...' : this.esc(text);
				html += `<div class="post">
					<div class="post__header">
						<span class="post__platform" style="background:var(--rs-primary)">${this.esc(platform.charAt(0).toUpperCase())}</span>
						<div class="post__meta"><strong>${this.esc(platform)}</strong></div>
						<span class="status status--draft">imported</span>
					</div>
					<div class="post__step">Tweet ${i + 1}/${total}</div>
					<p class="post__content">${preview.replace(/\n/g, '<br>')}</p>
				</div>`;
			});
			html += '</div></div>';
			importedEl.innerHTML = html;
			importModal.hidden = true;

			if (this._space !== 'demo') {
				const c = this._campaigns[0];
				if (c) {
					c.posts = [...c.posts, ...posts];
					this.saveCampaignToDoc(c);
				}
			}
		});

		// ── Generate modal ──
		const genModal = this.shadowRoot.getElementById('generate-modal') as HTMLElement;
		const genOpenBtn = this.shadowRoot.getElementById('generate-btn');
		const genCloseBtn = this.shadowRoot.getElementById('generate-modal-close');
		const genSubmit = this.shadowRoot.getElementById('gen-submit') as HTMLButtonElement;
		const genBrief = this.shadowRoot.getElementById('gen-brief') as HTMLTextAreaElement;
		const genError = this.shadowRoot.getElementById('gen-error') as HTMLElement;

		genOpenBtn?.addEventListener('click', () => {
			genModal.hidden = false;
			// Restore last brief if regenerating
			if (this._lastBrief && genBrief) genBrief.value = this._lastBrief;
		});
		genCloseBtn?.addEventListener('click', () => { genModal.hidden = true; });
		genModal?.addEventListener('click', (e) => { if (e.target === genModal) genModal.hidden = true; });

		genSubmit?.addEventListener('click', () => this.handleGenerate());

		// ── Preview mode buttons ──
		this.shadowRoot.getElementById('preview-save')?.addEventListener('click', () => {
			if (!this._generatedCampaign) return;
			this.saveCampaignToDoc(this._generatedCampaign);
			this._campaigns.unshift(this._generatedCampaign);
			this._generatedCampaign = null;
			this._previewMode = false;
			this.render();
		});

		this.shadowRoot.getElementById('preview-discard')?.addEventListener('click', () => {
			this._generatedCampaign = null;
			this._previewMode = false;
			this.render();
		});

		this.shadowRoot.getElementById('preview-regenerate')?.addEventListener('click', () => {
			this._previewMode = false;
			this._generatedCampaign = null;
			this.render();
			// Re-open generate modal after render
			requestAnimationFrame(() => {
				const modal = this.shadowRoot?.getElementById('generate-modal') as HTMLElement;
				if (modal) modal.hidden = false;
			});
		});

		// ── Thread badge toggles (skip linked badges — they navigate) ──
		this.shadowRoot.querySelectorAll('.thread-badge:not(.thread-badge--link)').forEach(badge => {
			badge.addEventListener('click', (e) => {
				e.stopPropagation();
				const postId = (badge as HTMLElement).dataset.postId;
				if (!postId) return;
				const expansion = this.shadowRoot!.getElementById(`thread-${postId}`);
				if (expansion) expansion.hidden = !expansion.hidden;
			});
		});

		// ── Linked thread badges (stop post card click from firing) ──
		this.shadowRoot.querySelectorAll('.thread-badge--link').forEach(badge => {
			badge.addEventListener('click', (e) => e.stopPropagation());
		});

		// ── Thread link buttons (stop post card click) ──
		this.shadowRoot.querySelectorAll('.post__thread-link').forEach(link => {
			link.addEventListener('click', (e) => e.stopPropagation());
		});

		// ── Post card click → toggle content expand ──
		this.shadowRoot.querySelectorAll('.post').forEach(post => {
			post.addEventListener('click', () => {
				const content = post.querySelector('.post__content') as HTMLElement;
				if (!content) return;
				const collapsed = content.dataset.collapsed === 'true';
				if (collapsed) {
					content.innerHTML = (content.dataset.full || '').replace(/\n/g, '<br>');
					content.dataset.collapsed = 'false';
				} else {
					content.innerHTML = (content.dataset.preview || '').replace(/\n/g, '<br>');
					content.dataset.collapsed = 'true';
				}
			});
		});
	}

	private async handleGenerate() {
		if (!this.shadowRoot || this._generating) return;

		const briefEl = this.shadowRoot.getElementById('gen-brief') as HTMLTextAreaElement;
		const errorEl = this.shadowRoot.getElementById('gen-error') as HTMLElement;
		const submitBtn = this.shadowRoot.getElementById('gen-submit') as HTMLButtonElement;

		const brief = briefEl?.value?.trim();
		if (!brief || brief.length < 10) {
			if (errorEl) errorEl.innerHTML = '<span class="gen-error">Please enter at least 10 characters describing your event.</span>';
			return;
		}

		// Gather selected platforms
		const platformChecks = this.shadowRoot.querySelectorAll('#gen-platforms input[type="checkbox"]');
		const platforms: string[] = [];
		platformChecks.forEach((cb: Element) => {
			if ((cb as HTMLInputElement).checked) platforms.push((cb as HTMLInputElement).value);
		});
		if (platforms.length === 0) {
			if (errorEl) errorEl.innerHTML = '<span class="gen-error">Select at least one platform.</span>';
			return;
		}

		const tone = (this.shadowRoot.getElementById('gen-tone') as HTMLSelectElement)?.value || 'professional';
		const style = (this.shadowRoot.getElementById('gen-style') as HTMLSelectElement)?.value || 'event-promo';

		this._generating = true;
		this._lastBrief = brief;
		if (errorEl) errorEl.innerHTML = '';
		if (submitBtn) {
			submitBtn.disabled = true;
			submitBtn.innerHTML = '<span class="spinner"></span> Generating...';
		}

		try {
			const res = await fetch(`${this.basePath}api/campaign/generate`, {
				method: 'POST',
				headers: { 'Content-Type': 'application/json' },
				body: JSON.stringify({ brief, platforms, tone, style }),
			});

			if (!res.ok) {
				const err = await res.json().catch(() => ({ error: 'Unknown error' }));
				throw new Error(err.error || `HTTP ${res.status}`);
			}

			const campaign: Campaign = await res.json();
			this._generatedCampaign = campaign;
			this._previewMode = true;

			// Close modal and render preview
			const genModal = this.shadowRoot.getElementById('generate-modal') as HTMLElement;
			if (genModal) genModal.hidden = true;

			this.render();
		} catch (e: any) {
			if (errorEl) errorEl.innerHTML = `<span class="gen-error">${this.esc(e.message || 'Generation failed')}</span>`;
		} finally {
			this._generating = false;
			if (submitBtn) {
				submitBtn.disabled = false;
				submitBtn.innerHTML = 'Generate Campaign';
			}
		}
	}
}

customElements.define('folk-campaign-manager', FolkCampaignManager);
