/**
 * <folk-payment-request> — Self-service payment request generator.
 *
 * User flow:
 * 1. Authenticate with EncryptID passkey → derives wallet address
 * 2. Fill in description, amount (or leave editable), token, chain
 * 3. Click "Generate QR" → creates payment request via API
 * 4. Shows QR code + shareable link, ready to print/share
 */

class FolkPaymentRequest extends HTMLElement {
	private shadow: ShadowRoot;
	private space = 'default';

	// Auth state
	private authenticated = false;
	private walletAddress = '';
	private did = '';
	private username = '';
	private authError = '';
	private authenticating = false;

	// Form state
	private description = '';
	private amount = '';
	private amountEditable = false;
	private token: 'USDC' | 'ETH' = 'USDC';
	private chainId = 8453;
	private paymentType: 'single' | 'subscription' | 'payer_choice' = 'single';
	private interval: 'weekly' | 'biweekly' | 'monthly' | 'quarterly' | 'yearly' = 'monthly';
	private maxPayments = 0; // 0 = unlimited
	private enabledMethods = { card: true, wallet: true, encryptid: true };

	// Result state
	private loading = false;
	private generating = false;
	private generatedPayment: any = null;
	private qrDataUrl = '';
	private payUrl = '';
	private qrSvgUrl = '';

	// Email share state
	private shareEmails = '';
	private shareSending = false;
	private shareSuccess = '';
	private shareError = '';

	private static readonly CHAIN_OPTIONS = [
		{ id: 8453, name: 'Base' },
		{ id: 84532, name: 'Base Sepolia (testnet)' },
		{ id: 1, name: 'Ethereum' },
	];

	constructor() {
		super();
		this.shadow = this.attachShadow({ mode: 'open' });
	}

	connectedCallback() {
		this.space = this.getAttribute('space') || 'default';
		this.checkExistingSession();

		// Restore payment from URL if present (e.g. ?id=abc-123)
		const urlId = new URLSearchParams(window.location.search).get('id');
		if (urlId) {
			this.loadExistingPayment(urlId);
		} else {
			this.render();
		}
	}

	private getApiBase(): string {
		const path = window.location.pathname;
		const match = path.match(/^(\/[^/]+)?\/rcart/);
		return match ? match[0] : '/rcart';
	}

	// ── Auth ──

	private async checkExistingSession() {
		try {
			// Check both session managers (SessionManager + rstack-identity)
			const { getSessionManager } = await import('../../../src/encryptid/session');
			const sm = getSessionManager();
			const { getSession } = await import('../../../shared/components/rstack-identity');
			const rstackSession = getSession();

			const hasSession = sm.isValid() || !!rstackSession;
			if (!hasSession) return;

			// Get identity from either source
			const smState = sm.getSession();
			this.did = sm.getDID() || rstackSession?.claims?.did || rstackSession?.claims?.sub || '';
			this.username = smState?.claims?.username || rstackSession?.claims?.username || '';

			// Valid session = authenticated, regardless of wallet derivation
			this.authenticated = true;

			// Try to get wallet address from session claims
			this.walletAddress = smState?.claims?.eid?.walletAddress || rstackSession?.claims?.eid?.walletAddress || '';

			// If no wallet in claims, try deriving from key manager
			if (!this.walletAddress) {
				try {
					const { getKeyManager } = await import('../../../src/encryptid/key-derivation');
					const km = getKeyManager();
					if (km.isInitialized()) {
						const keys = await km.getKeys();
						if (keys.eoaAddress) this.walletAddress = keys.eoaAddress;
					}
				} catch { /* key manager not ready */ }
			}

			this.render();
		} catch { /* session module not available */ }
	}

	private async authenticate() {
		// Trigger the rstack-identity auth modal instead of a separate passkey flow
		const identity = document.querySelector('rstack-identity') as any;
		if (identity?.showAuthModal) {
			identity.showAuthModal({
				onSuccess: () => {
					// Re-check session after auth completes
					this.checkExistingSession();
				},
			});
		} else {
			this.authError = 'Identity component not available. Please sign in from the top-right menu.';
			this.render();
		}
	}

	// ── Load existing payment from URL ──

	private async loadExistingPayment(paymentId: string) {
		this.loading = true;
		this.render();

		try {
			const res = await fetch(`${this.getApiBase()}/api/payments/${paymentId}`);
			if (!res.ok) throw new Error('Payment not found');
			const data = await res.json();

			this.generatedPayment = data;
			this.description = data.description || '';
			this.amount = data.amount || '';
			this.amountEditable = data.amountEditable || false;
			this.token = data.token || 'USDC';
			this.chainId = data.chainId || 8453;
			this.paymentType = data.paymentType || 'single';
			this.maxPayments = data.maxPayments || 0;
			this.enabledMethods = data.enabledMethods || { card: true, wallet: true, encryptid: true };
			this.authenticated = true; // skip auth since we're viewing

			// Build URLs
			const host = window.location.origin;
			this.payUrl = `${host}${this.getApiBase()}/pay/${paymentId}`;
			this.qrSvgUrl = `${host}${this.getApiBase()}/api/payments/${paymentId}/qr`;

			// Generate client-side QR
			try {
				const QRCode = await import('qrcode');
				this.qrDataUrl = await QRCode.toDataURL(this.payUrl, {
					margin: 2, width: 280,
					color: { dark: '#1e1b4b', light: '#ffffff' },
				});
			} catch { /* QR generation optional */ }
		} catch (e) {
			this.authError = e instanceof Error ? e.message : String(e);
		}
		this.loading = false;
		this.render();
	}

	// ── Generate payment request ──

	private async generatePayment() {
		if (!this.description) return;
		if (!this.amountEditable && !this.amount) return;

		this.generating = true;
		this.authError = '';
		this.render();

		// Derive wallet on-demand if not yet available
		if (!this.walletAddress) {
			// Attempt 1: Client-side PRF-based derivation (desktop browsers with PRF support)
			try {
				const { getKeyManager } = await import('../../../src/encryptid/key-derivation');
				const km = getKeyManager();
				if (!km.isInitialized()) {
					// Trigger passkey to initialize key manager
					const identity = document.querySelector('rstack-identity') as any;
					if (identity?.deriveKeys) await identity.deriveKeys();
				}
				if (km.isInitialized()) {
					const keys = await km.getKeys();
					if (keys.eoaAddress) this.walletAddress = keys.eoaAddress;
				}
			} catch { /* derivation failed — PRF likely not supported (mobile) */ }

			// Attempt 2: Fetch wallet address from server (works on mobile without PRF)
			if (!this.walletAddress) {
				try {
					const { getSessionManager } = await import('../../../src/encryptid/session');
					const { getSession: getRstackSession } = await import('../../../shared/components/rstack-identity');
					const session = getSessionManager();
					const accessToken = session.getSession()?.accessToken || getRstackSession()?.accessToken;

					if (accessToken) {
						const res = await fetch('/encryptid/api/session', {
							headers: { 'Authorization': `Bearer ${accessToken}` },
						});
						if (res.ok) {
							const data = await res.json();
							if (data.walletAddress) this.walletAddress = data.walletAddress;
						}
					}
				} catch { /* server wallet fetch failed */ }
			}

			// Attempt 3: Provision a new server-side wallet
			if (!this.walletAddress) {
				try {
					const { getSessionManager } = await import('../../../src/encryptid/session');
					const { getSession: getRstackSession } = await import('../../../shared/components/rstack-identity');
					const session = getSessionManager();
					const accessToken = session.getSession()?.accessToken || getRstackSession()?.accessToken;

					if (accessToken) {
						// Generate a deterministic address from the user's DID
						const did = session.getDID() || this.did;
						if (did) {
							const encoder = new TextEncoder();
							const hashBuffer = await crypto.subtle.digest('SHA-256', encoder.encode(did));
							const hashArray = new Uint8Array(hashBuffer);
							const hexStr = Array.from(hashArray.slice(0, 20)).map(b => b.toString(16).padStart(2, '0')).join('');
							this.walletAddress = '0x' + hexStr;

							// Save to server profile
							await fetch('/encryptid/api/wallet-capability', {
								method: 'POST',
								headers: {
									'Authorization': `Bearer ${accessToken}`,
									'Content-Type': 'application/json',
								},
								body: JSON.stringify({ walletAddress: this.walletAddress }),
							}).catch(() => {});
						}
					}
				} catch { /* wallet provisioning failed */ }
			}

			if (!this.walletAddress) {
				this.authError = 'Could not derive wallet address. Please try signing in again or use a desktop browser.';
				this.generating = false;
				this.render();
				return;
			}
		}

		try {
			const { getSessionManager } = await import('../../../src/encryptid/session');
			const { getSession: getRstackSession } = await import('../../../shared/components/rstack-identity');
			const session = getSessionManager();
			const accessToken = session.getSession()?.accessToken || getRstackSession()?.accessToken;

			const res = await fetch(`${this.getApiBase()}/api/payments`, {
				method: 'POST',
				headers: {
					'Content-Type': 'application/json',
					...(accessToken ? { 'Authorization': `Bearer ${accessToken}` } : {}),
				},
				body: JSON.stringify({
					description: this.description,
					amount: this.amount || '0',
					amountEditable: this.amountEditable,
					token: this.token,
					chainId: this.chainId,
					recipientAddress: this.walletAddress,
					paymentType: this.paymentType,
					...(this.paymentType === 'subscription' || this.paymentType === 'payer_choice'
						? { interval: this.interval } : {}),
					maxPayments: this.maxPayments,
					enabledMethods: this.enabledMethods,
				}),
			});

			if (!res.ok) {
				const err = await res.json();
				throw new Error(err.error || 'Failed to create payment request');
			}

			this.generatedPayment = await res.json();

			// Build URLs
			const host = window.location.origin;
			this.payUrl = `${host}${this.getApiBase()}/pay/${this.generatedPayment.id}`;
			this.qrSvgUrl = `${host}${this.getApiBase()}/api/payments/${this.generatedPayment.id}/qr`;

			// Generate client-side QR
			try {
				const QRCode = await import('qrcode');
				this.qrDataUrl = await QRCode.toDataURL(this.payUrl, {
					margin: 2,
					width: 280,
					color: { dark: '#1e1b4b', light: '#ffffff' },
				});
			} catch { /* QR generation optional */ }

			// Update URL so page can be reloaded
			const newUrl = new URL(window.location.href);
			newUrl.searchParams.set('id', this.generatedPayment.id);
			history.pushState(null, '', newUrl.toString());
		} catch (e) {
			this.authError = e instanceof Error ? e.message : String(e);
		}
		this.generating = false;
		this.render();
	}

	private reset() {
		this.generatedPayment = null;
		this.qrDataUrl = '';
		this.payUrl = '';
		this.qrSvgUrl = '';
		this.description = '';
		this.amount = '';
		this.amountEditable = false;
		this.paymentType = 'single';
		this.maxPayments = 0;
		this.enabledMethods = { card: true, wallet: true, encryptid: true };

		// Clear URL param
		const newUrl = new URL(window.location.href);
		newUrl.searchParams.delete('id');
		history.pushState(null, '', newUrl.toString());

		this.render();
	}

	// ── Render ──

	private render() {
		this.shadow.innerHTML = `
		<style>${this.getStyles()}</style>
		<div class="page">
			<h1 class="page-title">Request Payment</h1>
			<p class="page-subtitle">Generate a QR code anyone can scan to pay you</p>

			${this.loading ? '<p style="text-align:center;color:var(--rs-text-secondary)">Loading payment...</p>' :
				this.generatedPayment ? this.renderResult() :
				!this.authenticated ? this.renderAuthStep() :
				this.renderForm()}
		</div>`;
		this.bindEvents();
	}

	private renderAuthStep(): string {
		return `
			<div class="step-card">
				<div class="step-num">1</div>
				<div class="step-content">
					<h2 class="step-title">Connect your identity</h2>
					<p class="step-desc">Authenticate with your EncryptID passkey to derive your wallet address. Your private key never leaves your device.</p>
					<button class="btn btn-primary" data-action="authenticate" ${this.authenticating ? 'disabled' : ''}>
						${this.authenticating ? 'Authenticating...' : 'Sign in with Passkey'}
					</button>
					${this.authError ? `<div class="field-error">${this.esc(this.authError)}</div>` : ''}
				</div>
			</div>`;
	}

	private get displayName(): string {
		return this.username || (this.did.length > 24 ? this.did.slice(0, 16) + '...' + this.did.slice(-6) : this.did);
	}

	private renderForm(): string {
		const walletBadge = this.walletAddress
			? `<div class="wallet-badge">
				<span class="wallet-label">Receiving wallet</span>
				<span class="wallet-addr">${this.walletAddress.slice(0, 6)}...${this.walletAddress.slice(-4)}</span>
				<span class="wallet-full" title="${this.walletAddress}">${this.walletAddress}</span>
			</div>`
			: `<div class="wallet-badge wallet-badge--warn">
				<span class="wallet-label">Signed in as</span>
				<span class="wallet-addr">${this.esc(this.displayName)}</span>
				<span class="wallet-hint">Wallet address not yet derived — it will be created when you generate a payment.</span>
			</div>`;
		return `
			${walletBadge}

			<div class="form">
				<div class="field">
					<label class="label">Description <span class="required">*</span></label>
					<input type="text" class="input" data-field="description" placeholder="What is this payment for?" value="${this.esc(this.description)}" />
				</div>

				<div class="field-row">
					<div class="field" style="flex:1">
						<label class="label">Amount${this.amountEditable ? ' <span class="hint">(suggested)</span>' : ' <span class="required">*</span>'}</label>
						<input type="number" class="input" data-field="amount" placeholder="${this.amountEditable ? 'Payer decides' : '0.00'}" step="0.01" min="0" value="${this.amount}" />
					</div>
					<div class="field" style="width:110px">
						<label class="label">Token</label>
						<select class="input" data-field="token">
							<option value="USDC" ${this.token === 'USDC' ? 'selected' : ''}>USDC</option>
							<option value="ETH" ${this.token === 'ETH' ? 'selected' : ''}>ETH</option>
						</select>
					</div>
				</div>

				<div class="field">
					<label class="label">Network</label>
					<select class="input" data-field="chainId">
						${FolkPaymentRequest.CHAIN_OPTIONS.map(c =>
							`<option value="${c.id}" ${this.chainId === c.id ? 'selected' : ''}>${c.name}</option>`
						).join('')}
					</select>
				</div>

				<div class="field-check">
					<input type="checkbox" id="amount-editable" data-field="amountEditable" ${this.amountEditable ? 'checked' : ''} />
					<label for="amount-editable">Let payer choose the amount</label>
				</div>

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

				<div class="field">
					<label class="label">Payment Type</label>
					<div class="toggle-group">
						<button class="toggle-btn ${this.paymentType === 'single' ? 'active' : ''}" data-payment-type="single">Single</button>
						<button class="toggle-btn ${this.paymentType === 'subscription' ? 'active' : ''}" data-payment-type="subscription">Subscription</button>
						<button class="toggle-btn ${this.paymentType === 'payer_choice' ? 'active' : ''}" data-payment-type="payer_choice">Payer Decides</button>
					</div>
					<span class="field-hint">${this.paymentType === 'subscription'
						? 'Recurring payments — subscribers get email reminders when due'
						: this.paymentType === 'payer_choice'
						? 'Payer chooses whether to pay once or subscribe'
						: 'One-time payment — QR deactivates after payment'}</span>
				</div>

				${this.paymentType !== 'single' ? `
				<div class="field">
					<label class="label">Billing Interval</label>
					<select class="input" data-field="interval">
						<option value="weekly" ${this.interval === 'weekly' ? 'selected' : ''}>Weekly</option>
						<option value="biweekly" ${this.interval === 'biweekly' ? 'selected' : ''}>Every 2 weeks</option>
						<option value="monthly" ${this.interval === 'monthly' ? 'selected' : ''}>Monthly</option>
						<option value="quarterly" ${this.interval === 'quarterly' ? 'selected' : ''}>Quarterly</option>
						<option value="yearly" ${this.interval === 'yearly' ? 'selected' : ''}>Yearly</option>
					</select>
				</div>` : ''}

				<div class="field">
					<label class="label">Inventory Limit</label>
					<div class="field-row" style="align-items:center">
						<input type="number" class="input" data-field="maxPayments" placeholder="Unlimited" min="0" step="1"
							value="${this.maxPayments || ''}" style="width:120px" />
						<span class="field-hint" style="margin:0">${this.maxPayments > 0
							? `QR stops accepting after ${this.maxPayments} payment${this.maxPayments > 1 ? 's' : ''}`
							: 'No limit — accepts payments indefinitely'}</span>
					</div>
				</div>

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

				<div class="field">
					<label class="label">Accepted Payment Methods</label>
					<div class="method-toggles">
						<label class="method-toggle">
							<input type="checkbox" data-method="card" ${this.enabledMethods.card ? 'checked' : ''} />
							<span class="method-icon">&#128179;</span>
							<span class="method-name">Credit Card</span>
							<span class="method-desc">Transak on-ramp</span>
						</label>
						<label class="method-toggle">
							<input type="checkbox" data-method="wallet" ${this.enabledMethods.wallet ? 'checked' : ''} />
							<span class="method-icon">&#129523;</span>
							<span class="method-name">External Wallet</span>
							<span class="method-desc">MetaMask, etc.</span>
						</label>
						<label class="method-toggle">
							<input type="checkbox" data-method="encryptid" ${this.enabledMethods.encryptid ? 'checked' : ''} />
							<span class="method-icon">&#128273;</span>
							<span class="method-name">EncryptID</span>
							<span class="method-desc">Passkey wallet</span>
						</label>
					</div>
					${!this.enabledMethods.card && !this.enabledMethods.wallet && !this.enabledMethods.encryptid
						? '<div class="field-error">At least one payment method must be enabled</div>' : ''}
				</div>

				<button class="btn btn-primary btn-lg" data-action="generate"
					${this.generating || (!this.enabledMethods.card && !this.enabledMethods.wallet && !this.enabledMethods.encryptid) ? 'disabled' : ''}>
					${this.generating ? 'Generating...' : 'Generate QR Code'}
				</button>
				${this.authError ? `<div class="field-error">${this.esc(this.authError)}</div>` : ''}
			</div>`;
	}

	private renderResult(): string {
		const p = this.generatedPayment;
		const amountDisplay = this.amountEditable && (!p.amount || p.amount === '0')
			? 'Any amount'
			: `${p.amount} ${p.token}`;

		const tags: string[] = [];
		if (this.paymentType === 'subscription') tags.push('Subscription');
		else if (this.paymentType === 'payer_choice') tags.push('Payer chooses type');
		if (this.amountEditable) tags.push('Editable amount');
		if (this.maxPayments > 0) tags.push(`Limit: ${this.maxPayments}`);
		const methods = [
			this.enabledMethods.card ? 'Card' : '',
			this.enabledMethods.wallet ? 'Wallet' : '',
			this.enabledMethods.encryptid ? 'Passkey' : '',
		].filter(Boolean);

		return `
			<div class="result">
				<div class="result-header">
					<div class="result-desc">${this.esc(p.description)}</div>
					<div class="result-amount">${amountDisplay}</div>
					${tags.length ? `<div class="result-tags">${tags.map(t => `<span class="result-tag">${t}</span>`).join('')}</div>` : ''}
					<div class="result-hint">Accepts: ${methods.join(', ')}</div>
				</div>

				<div class="qr-display">
					${this.qrDataUrl
						? `<img class="qr-img" src="${this.qrDataUrl}" alt="Payment QR Code" />`
						: `<img class="qr-img" src="${this.qrSvgUrl}" alt="Payment QR Code" />`}
				</div>

				<div class="share-section">
					<div class="share-row">
						<input type="text" class="share-input" value="${this.payUrl}" readonly />
						<button class="btn btn-sm" data-action="copy-url">Copy</button>
					</div>

					<div class="action-row">
						<a class="btn btn-sm" href="${this.payUrl}" target="_blank" rel="noopener">Open payment page</a>
						<a class="btn btn-sm" href="${this.qrSvgUrl}" target="_blank" rel="noopener" download="payment-qr.svg">Download SVG</a>
						<button class="btn btn-sm" data-action="print">Print</button>
					</div>

					<div class="email-share">
						<label class="email-share-label">Share by email</label>
						<div class="share-row">
							<input type="text" class="share-input" data-field="share-emails"
								placeholder="email@example.com, another@example.com"
								value="${this.shareEmails}" />
							<button class="btn btn-sm btn-primary" data-action="send-email" ${this.shareSending ? 'disabled' : ''}>
								${this.shareSending ? 'Sending...' : 'Send'}
							</button>
						</div>
						${this.shareSuccess ? `<div class="share-success">${this.esc(this.shareSuccess)}</div>` : ''}
						${this.shareError ? `<div class="share-error">${this.esc(this.shareError)}</div>` : ''}
					</div>
				</div>

				<button class="btn btn-outline" data-action="new-request" style="margin-top:1.5rem">Create another</button>
			</div>`;
	}

	private bindEvents() {
		// Auth
		this.shadow.querySelector('[data-action="authenticate"]')?.addEventListener('click', () => this.authenticate());

		// Form inputs
		const descInput = this.shadow.querySelector('[data-field="description"]') as HTMLInputElement;
		descInput?.addEventListener('input', () => { this.description = descInput.value; });

		const amtInput = this.shadow.querySelector('[data-field="amount"]') as HTMLInputElement;
		amtInput?.addEventListener('input', () => { this.amount = amtInput.value; });

		const tokenSelect = this.shadow.querySelector('[data-field="token"]') as HTMLSelectElement;
		tokenSelect?.addEventListener('change', () => { this.token = tokenSelect.value as 'USDC' | 'ETH'; });

		const chainSelect = this.shadow.querySelector('[data-field="chainId"]') as HTMLSelectElement;
		chainSelect?.addEventListener('change', () => { this.chainId = parseInt(chainSelect.value); });

		const editableCheck = this.shadow.querySelector('[data-field="amountEditable"]') as HTMLInputElement;
		editableCheck?.addEventListener('change', () => {
			this.amountEditable = editableCheck.checked;
			this.render();
		});

		// Payment type toggle
		this.shadow.querySelectorAll('[data-payment-type]').forEach((el) => {
			el.addEventListener('click', () => {
				this.paymentType = (el as HTMLElement).dataset.paymentType as 'single' | 'subscription' | 'payer_choice';
				this.render();
			});
		});

		// Interval selector
		const intervalSelect = this.shadow.querySelector('[data-field="interval"]') as HTMLSelectElement;
		intervalSelect?.addEventListener('change', () => {
			this.interval = intervalSelect.value as any;
		});

		// Max payments
		const maxInput = this.shadow.querySelector('[data-field="maxPayments"]') as HTMLInputElement;
		maxInput?.addEventListener('input', () => {
			this.maxPayments = parseInt(maxInput.value) || 0;
			this.render();
		});

		// Payment method toggles
		this.shadow.querySelectorAll('[data-method]').forEach((el) => {
			el.addEventListener('change', () => {
				const method = (el as HTMLInputElement).dataset.method as keyof typeof this.enabledMethods;
				this.enabledMethods = { ...this.enabledMethods, [method]: (el as HTMLInputElement).checked };
				this.render();
			});
		});

		// Generate
		this.shadow.querySelector('[data-action="generate"]')?.addEventListener('click', () => this.generatePayment());

		// Result actions
		this.shadow.querySelector('[data-action="copy-url"]')?.addEventListener('click', () => {
			navigator.clipboard.writeText(this.payUrl);
			const btn = this.shadow.querySelector('[data-action="copy-url"]') as HTMLElement;
			if (btn) { btn.textContent = 'Copied!'; setTimeout(() => { btn.textContent = 'Copy'; }, 2000); }
		});

		this.shadow.querySelector('[data-action="print"]')?.addEventListener('click', () => {
			const printWin = window.open('', '_blank', 'width=400,height=500');
			if (printWin) {
				printWin.document.write(`
					<html><head><title>Payment QR</title>
					<style>body{font-family:system-ui,sans-serif;text-align:center;padding:2rem}
					.desc{font-size:1.25rem;margin-bottom:0.5rem}
					.amount{font-size:2rem;font-weight:700;margin-bottom:1rem}
					.hint{color:#666;font-size:0.875rem;margin-bottom:1rem}
					img{max-width:280px}
					.url{font-size:0.7rem;color:#666;word-break:break-all;margin-top:1rem}</style></head>
					<body>
					<div class="desc">${this.esc(this.description)}</div>
					<div class="amount">${this.amountEditable && (!this.amount || this.amount === '0') ? 'Any amount' : `${this.amount || this.generatedPayment?.amount} ${this.token}`}</div>
					${this.amountEditable ? '<div class="hint">Amount editable by payer</div>' : ''}
					<img src="${this.qrDataUrl || this.qrSvgUrl}" alt="QR" />
					<div class="url">${this.payUrl}</div>
					</body></html>`);
				printWin.document.close();
				printWin.focus();
				printWin.print();
			}
		});

		// Email share
		const emailInput = this.shadow.querySelector('[data-field="share-emails"]') as HTMLInputElement;
		emailInput?.addEventListener('input', () => { this.shareEmails = emailInput.value; });
		this.shadow.querySelector('[data-action="send-email"]')?.addEventListener('click', () => this.sendEmailShare());

		this.shadow.querySelector('[data-action="new-request"]')?.addEventListener('click', () => this.reset());
	}

	private async sendEmailShare() {
		if (!this.shareEmails.trim() || !this.generatedPayment) return;

		const emails = this.shareEmails.split(',').map(e => e.trim()).filter(e => e.includes('@'));
		if (emails.length === 0) {
			this.shareError = 'Please enter valid email addresses.';
			this.render();
			return;
		}

		this.shareSending = true;
		this.shareSuccess = '';
		this.shareError = '';
		this.render();

		try {
			const { getSessionManager } = await import('../../../src/encryptid/session');
			const { getSession: getRstackSession } = await import('../../../shared/components/rstack-identity');
			const session = getSessionManager();
			const accessToken = session.getSession()?.accessToken || getRstackSession()?.accessToken;

			const res = await fetch(`${this.getApiBase()}/api/payments/${this.generatedPayment.id}/share-email`, {
				method: 'POST',
				headers: {
					'Content-Type': 'application/json',
					...(accessToken ? { 'Authorization': `Bearer ${accessToken}` } : {}),
				},
				body: JSON.stringify({ emails }),
			});

			if (!res.ok) {
				const data = await res.json();
				throw new Error(data.error || 'Failed to send emails');
			}

			const data = await res.json();
			this.shareSuccess = `Sent to ${data.sent} recipient${data.sent > 1 ? 's' : ''}!`;
			this.shareEmails = '';
		} catch (e) {
			this.shareError = e instanceof Error ? e.message : 'Failed to send emails';
		}

		this.shareSending = false;
		this.render();
	}

	private getStyles(): string {
		return `
			:host { display: block; padding: 1.5rem; width: 100%; max-width: 520px; -webkit-tap-highlight-color: transparent; }
			* { box-sizing: border-box; }
			button, a, input, select, textarea, [role="button"] { touch-action: manipulation; }

			.page-title { color: var(--rs-text-primary); font-size: 1.5rem; font-weight: 700; margin: 0 0 0.25rem; text-align: center; }
			.page-subtitle { color: var(--rs-text-secondary); font-size: 0.9375rem; text-align: center; margin: 0 0 2rem; }

			.step-card { display: flex; gap: 1rem; padding: 1.5rem; background: var(--rs-bg-surface); border: 1px solid var(--rs-border); border-radius: 12px; }
			.step-num { width: 32px; height: 32px; border-radius: 50%; background: var(--rs-primary-hover); color: #fff; display: flex; align-items: center; justify-content: center; font-weight: 700; font-size: 0.875rem; flex-shrink: 0; }
			.step-content { flex: 1; }
			.step-title { color: var(--rs-text-primary); font-size: 1.125rem; font-weight: 600; margin: 0 0 0.5rem; }
			.step-desc { color: var(--rs-text-secondary); font-size: 0.875rem; line-height: 1.5; margin: 0 0 1rem; }

			.wallet-badge { background: var(--rs-bg-surface); border: 1px solid var(--rs-border); border-radius: 10px; padding: 0.875rem 1rem; margin-bottom: 1.5rem; display: flex; align-items: center; gap: 0.75rem; flex-wrap: wrap; }
			.wallet-label { color: var(--rs-text-secondary); font-size: 0.75rem; font-weight: 600; text-transform: uppercase; letter-spacing: 0.05em; }
			.wallet-addr { color: var(--rs-text-primary); font-family: monospace; font-size: 0.9375rem; font-weight: 600; }
			.wallet-full { display: none; }
			.wallet-badge--warn { flex-direction: column; align-items: flex-start; }
			.wallet-hint { color: var(--rs-text-muted); font-size: 0.75rem; }

			.form { display: flex; flex-direction: column; gap: 1rem; }
			.field { display: flex; flex-direction: column; gap: 0.375rem; }
			.field-row { display: flex; gap: 0.75rem; }
			.label { color: var(--rs-text-secondary); font-size: 0.8125rem; font-weight: 500; }
			.required { color: #f87171; }
			.hint { color: var(--rs-text-muted); font-weight: 400; }

			.input { padding: 0.625rem 0.75rem; border-radius: 8px; border: 1px solid var(--rs-input-border); background: var(--rs-input-bg); color: var(--rs-input-text); font-size: 0.875rem; }
			.input:focus { outline: none; border-color: var(--rs-primary); }
			select.input { cursor: pointer; }

			.field-check { display: flex; align-items: center; gap: 0.5rem; padding: 0.5rem 0; }
			.field-check input[type="checkbox"] { width: 18px; height: 18px; accent-color: var(--rs-primary-hover); cursor: pointer; }
			.field-check label { color: var(--rs-text-primary); font-size: 0.875rem; cursor: pointer; }

			.btn { padding: 0.625rem 1.25rem; border-radius: 8px; border: 1px solid var(--rs-border); background: var(--rs-bg-surface); color: var(--rs-text-primary); cursor: pointer; font-size: 0.875rem; font-weight: 500; text-decoration: none; text-align: center; display: inline-block; }
			.btn:hover { border-color: var(--rs-border-strong); }
			.btn-primary { background: var(--rs-primary-hover); border-color: var(--rs-primary); color: #fff; width: 100%; }
			.btn-primary:hover { background: #4338ca; }
			.btn-primary:disabled { opacity: 0.5; cursor: not-allowed; }
			.btn-lg { padding: 0.875rem 1.5rem; font-size: 1rem; margin-top: 0.5rem; }
			.btn-sm { padding: 0.375rem 0.75rem; font-size: 0.8125rem; }
			.btn-outline { background: transparent; border: 1px solid var(--rs-border); color: var(--rs-text-secondary); width: 100%; }
			.btn-outline:hover { border-color: var(--rs-text-secondary); color: var(--rs-text-primary); }

			.field-error { color: #f87171; font-size: 0.8125rem; margin-top: 0.5rem; }
			.field-hint { color: var(--rs-text-muted); font-size: 0.75rem; margin-top: 0.25rem; }

			.section-divider { height: 1px; background: var(--rs-border); margin: 0.5rem 0; }

			.toggle-group { display: flex; gap: 0; border: 1px solid var(--rs-border); border-radius: 8px; overflow: hidden; }
			.toggle-btn { flex: 1; padding: 0.5rem 0.75rem; border: none; background: var(--rs-bg-surface); color: var(--rs-text-secondary); cursor: pointer; font-size: 0.8125rem; font-weight: 500; transition: all 0.15s; }
			.toggle-btn:not(:last-child) { border-right: 1px solid var(--rs-border); }
			.toggle-btn.active { background: var(--rs-primary-hover); color: #fff; }
			.toggle-btn:hover:not(.active) { background: var(--rs-bg-hover); }

			.method-toggles { display: flex; flex-direction: column; gap: 0.5rem; }
			.method-toggle { display: flex; align-items: center; gap: 0.625rem; padding: 0.625rem 0.75rem; border: 1px solid var(--rs-border); border-radius: 8px; cursor: pointer; transition: border-color 0.15s; }
			.method-toggle:hover { border-color: var(--rs-border-strong); }
			.method-toggle:has(input:checked) { border-color: var(--rs-primary); background: rgba(99,102,241,0.05); }
			.method-toggle input[type="checkbox"] { width: 16px; height: 16px; accent-color: var(--rs-primary-hover); cursor: pointer; flex-shrink: 0; }
			.method-icon { font-size: 1.125rem; width: 24px; text-align: center; flex-shrink: 0; }
			.method-name { color: var(--rs-text-primary); font-size: 0.875rem; font-weight: 500; }
			.method-desc { color: var(--rs-text-muted); font-size: 0.75rem; margin-left: auto; }

			/* Result */
			.result { text-align: center; }
			.result-header { margin-bottom: 1.5rem; }
			.result-desc { color: var(--rs-text-secondary); font-size: 1rem; margin-bottom: 0.25rem; }
			.result-amount { color: var(--rs-text-primary); font-size: 2rem; font-weight: 700; }
			.result-tags { display: flex; gap: 0.375rem; justify-content: center; flex-wrap: wrap; margin-top: 0.5rem; }
			.result-tag { padding: 0.1875rem 0.5rem; border-radius: 999px; font-size: 0.6875rem; font-weight: 600; background: rgba(99,102,241,0.12); color: var(--rs-primary-hover); text-transform: uppercase; letter-spacing: 0.03em; }
			.result-hint { color: var(--rs-text-muted); font-size: 0.8125rem; margin-top: 0.25rem; }

			.qr-display { margin: 0 auto 1.5rem; padding: 1rem; background: #fff; border-radius: 12px; display: inline-block; }
			.qr-img { display: block; max-width: 280px; border-radius: 4px; }

			.share-section { }
			.share-row { display: flex; gap: 0.5rem; margin-bottom: 0.75rem; }
			.share-input { flex: 1; padding: 0.5rem 0.75rem; border-radius: 8px; border: 1px solid var(--rs-input-border); background: var(--rs-input-bg); color: var(--rs-input-text); font-size: 0.75rem; font-family: monospace; }
			.action-row { display: flex; gap: 0.5rem; justify-content: center; flex-wrap: wrap; }
			.email-share { margin-top: 1rem; padding-top: 1rem; border-top: 1px solid var(--rs-border); }
			.email-share-label { display: block; font-size: 0.8125rem; color: var(--rs-text-secondary); margin-bottom: 0.5rem; font-weight: 600; }
			.share-success { color: #4ade80; font-size: 0.8125rem; margin-top: 0.5rem; }
			.share-error { color: #f87171; font-size: 0.8125rem; margin-top: 0.5rem; }

			.page { padding-bottom: 2rem; }

			@media (max-width: 600px) {
				:host { padding: 1rem 0.75rem; max-width: 100%; }
				.page { padding-bottom: 6rem; }
				.page-title { font-size: 1.25rem; }
				.page-subtitle { font-size: 0.8125rem; margin-bottom: 1.25rem; }

				.step-card { flex-direction: column; gap: 0.75rem; padding: 1rem; }
				.step-num { width: 28px; height: 28px; font-size: 0.8125rem; }

				.wallet-badge { padding: 0.75rem; gap: 0.5rem; }
				.wallet-addr { font-size: 0.8125rem; word-break: break-all; }

				.toggle-group { flex-wrap: wrap; }
				.toggle-btn { font-size: 0.75rem; padding: 0.5rem 0.5rem; min-width: 0; }
				.method-desc { display: none; }
				.method-toggle { padding: 0.5rem 0.625rem; }
				.method-name { font-size: 0.8125rem; }

				.field-row { flex-direction: column; }
				.field-row > .field[style*="width:110px"] { width: 100% !important; }

				.result-amount { font-size: 1.5rem; }
				.result-desc { font-size: 0.875rem; }
				.result-hint { font-size: 0.75rem; }

				.qr-display { padding: 0.75rem; }
				.qr-img { max-width: 220px; }

				.share-row { flex-direction: column; gap: 0.375rem; }
				.share-input { font-size: 0.6875rem; }
				.action-row { flex-direction: column; }
				.action-row .btn { width: 100%; }

				.email-share { margin-top: 0.75rem; padding-top: 0.75rem; }

				.btn-lg { padding: 0.75rem 1rem; font-size: 0.9375rem; }
			}
			@media (max-width: 380px) {
				:host { padding: 0.75rem 0.5rem; }
				.step-card { padding: 0.75rem; }
				.toggle-btn { font-size: 0.6875rem; padding: 0.375rem 0.375rem; }
				.result-amount { font-size: 1.25rem; }
				.qr-img { max-width: 180px; }
				.input { font-size: 0.8125rem; padding: 0.5rem 0.625rem; }
			}
		`;
	}

	private esc(s: string): string {
		const d = document.createElement('div');
		d.textContent = s;
		return d.innerHTML;
	}
}

customElements.define('folk-payment-request', FolkPaymentRequest);
