<script lang="ts">
	import RecipientChip from '../../components/RecipientChip.svelte';
	import { onMount } from 'svelte';
	import { ndk, pageIcon, pageTitle } from '$lib/stores.svelte';
	import Notification from '../../components/Notification.svelte';
	import { createCarbonCopyLetter, createSealedLetter } from '$lib/utils.svelte';
	import type { NDKUser } from '@nostr-dev-kit/ndk';
	import { TokenInfoWithMailSubscriptionDuration } from '@arx/utils';
	import Icon from '@iconify/svelte';

	let isSending = $state(false);
	let letterSent = $state(0);
	let recipients = $state([]);
	let replyTo = $state('');
	let toField = $state('');
	let subject = $state('');
	let content = $state('');
	let stamp = $state('');
	let tokenInfo = $state<TokenInfoWithMailSubscriptionDuration>();
	let tokenInfoError = $state('');

	$effect(() => {
		if (isSending) $pageTitle = 'Sending...';
		else $pageTitle = 'New Letter';
	});

	$effect(() => {
		try {
			tokenInfo = new TokenInfoWithMailSubscriptionDuration(stamp);
			tokenInfoError = '';
		} catch (e) {
			tokenInfoError = (e as Error).message;
		}
	});

	function isValidNpub(npub: string): boolean {
		return npub.startsWith('npub');
	}

	function isPossibleNip05(nip05: string): boolean {
		let parts = nip05.split('@');
		if (parts.length !== 2) return false;
		let domain = parts[1];
		return domain.includes('.');
	}

	function recepientInput(e: KeyboardEvent) {
		if (e.key !== 'Enter') return;
		return addRecipient();
	}

	async function addRecipient() {
		if (!isValidNpub(toField) && !isPossibleNip05(toField)) return alert('Invalid recipient');
		if (isPossibleNip05(toField)) {
			const user = await $ndk.getUserFromNip05(toField);
			if (!user)
				return alert('Invalid recipient (nip05 does not match any npub)');
		}
		if (recipients.includes(toField)) toField = '';
		recipients = [...recipients, toField];
		toField = '';
		return true;
	}

	async function send() {
		if (!confirm('Are you sure you want to send this message?')) return;
		if (toField.length != 0 && !await addRecipient())
			return;
		if (recipients.length === 0) return alert('Please add at least one recipient');
		if (subject.length === 0) return alert('Please add a subject');
		if (content.length === 0) return alert('Please add a message');
		let newStamp;
		if (stamp) {
			if (tokenInfoError) return alert(tokenInfoError);
			if (!tokenInfo) return alert('Please add a valid stamp');
			newStamp = await tokenInfo.receive();
			stamp = '';
		}
		isSending = true;
		try {
			const notesToSend = [];
			const alreadyCheckedPublicKeys: string[] = [];
			const realRecipients: NDKUser[] = [];
			for (let r of recipients) {
				let recipient;
				if (isPossibleNip05(r))
					recipient = await $ndk.getUserFromNip05(r);
				else
					recipient = $ndk.getUser({
						npub: r
					});
				if (!recipient) return alert(`Invalid recipient: ${r}`);
				if (alreadyCheckedPublicKeys.includes(recipient.pubkey)) continue;
				alreadyCheckedPublicKeys.push(recipient.pubkey);
				notesToSend.push(await createSealedLetter(
					$ndk.activeUser!,
					recipient,
					subject,
					content,
					replyTo,
					newStamp
				));
				realRecipients.push(recipient);
			}
			notesToSend.push(await createCarbonCopyLetter(
				$ndk.activeUser!,
				realRecipients,
				subject,
				content
			));
			await Promise.all(notesToSend.map(n => n.publish()));
			letterSent = Date.now();
		} finally {
			isSending = false;
		}
	}

	onMount(() => {
		$pageTitle = 'New Letter';
		$pageIcon = 'proicons:compose';
		const urlParams = new URLSearchParams(window.location.search);
		if (urlParams.has('replyTo'))
			replyTo = urlParams.get('replyTo');
		if (urlParams.has('to'))
			recipients.push(urlParams.get('to'));
		if (urlParams.has('subject'))
			subject = urlParams.get('subject');
		if (urlParams.has('content'))
			content = urlParams.get('content');
	});
</script>

{#if letterSent}
	<Notification title="Letter Sent" duration={5000}>
		Letter sent to {recipients.join(', ')}.
	</Notification>
{/if}

{#if !isSending}
	<div class="compose-container">
		<div class="compose-fields">
			<div class="field">
				<label>To:</label>
				<div class="to">
					{#each recipients as r}
						<RecipientChip recipient={r}
													 onRemove={() => recipients = recipients.filter((recipient) => recipient !== r)} />
					{/each}
					<input
						bind:value={toField}
						onkeyup={recepientInput}
						placeholder="Enter npub or nip05..."
						type="text"
					/>
				</div>
			</div>

			<div class="field">
				<label>Subject:</label>
				<input bind:value={subject} class="input" placeholder="Enter subject..." type="text">
			</div>

			{#if recipients.length < 2}
				<div class="field">
					<label>Stamp:</label>
					<input bind:value={stamp} class="input" placeholder="Enter stamp..." type="text" />
				</div>

				{#if tokenInfoError && stamp.length > 0}
					<p class="error">
						{tokenInfoError}
					</p>
				{:else if tokenInfo && stamp.length > 0}
					<p class="stamp-count">
						<Icon icon="fxemoji:stampedenvelope" /> {tokenInfo.amount} sats
					</p>
				{/if}
			{/if}
		</div>

		<div class="compose-editor">
			<textarea bind:value={content} class="editor-content"></textarea>
		</div>

		<div class="compose-actions">
			<button class="send-button" onclick={send}>Send</button>
		</div>
	</div>
{/if}

<style>
  .compose-container {
    display: grid;
    grid-template-rows: auto auto 1fr auto;
    gap: var(--spacing-md);
  }

  .compose-fields {
    display: grid;
    gap: var(--spacing-sm);

    & .field {
      position: relative;
      display: grid;
      grid-template-columns: 80px 1fr;
      place-items: end;
      align-items: center;
      gap: var(--spacing-sm);
      background: var(--glass-bg);
      border: 1px solid var(--glass-border);
      padding: var(--spacing-md);

      & .to {
        display: flex;
        flex-wrap: wrap;
        gap: var(--spacing-sm);
        align-items: center;
        width: 100%;
      }

      & label {
        font-weight: bolder;
        color: var(--text-secondary);
      }

      & input {
        width: 100%;
        flex-basis: 100%;
      }
    }
  }

  .compose-editor {
    position: relative;
    background: var(--editor-bg);
    border-radius: 12px;
    border: 1px solid var(--input-border);
    overflow: hidden;
    transition: all 0.3s ease;

    &:focus-within {
      border-color: var(--accent);
      box-shadow: 0 0 0 3px var(--input-focus);
    }

    & .editor-content {
      background: transparent;
      resize: none;
      border: 0;
      width: 100%;
      padding: var(--spacing-md);
      min-height: 300px;
    }
  }

  .compose-actions {
    display: flex;
    justify-content: flex-end;
    gap: var(--spacing-sm);
  }

  @layer components {
    input {
      flex-grow: 1;
    }

    .send-button {
      background: var(--accent);
      color: white;
      padding: 0.75rem 2rem;
      border-radius: 8px;
      font-weight: 600;
      transition: all 0.3s ease;

      &:hover {
        background: var(--accent-light);
        transform: translateY(-2px);
        box-shadow: 0 4px 12px rgba(99, 102, 241, 0.3);
      }
    }
  }
</style>