<script lang="ts">
	import { activeUser, ndk } from '$lib/stores.svelte';
	import { onMount } from 'svelte';
	import { browser } from '$app/environment';
	import { NDKNip07Signer, NDKPrivateKeySigner } from '@nostr-dev-kit/ndk';
	import { decode as decodeKey } from 'nostr-tools/nip19';
	import { decrypt as decryptNsec, encrypt as encryptNsec } from 'nostr-tools/nip49';
	import { goto } from '$app/navigation';

	let ncryptsec = $state(browser ? localStorage.getItem('ncryptsec') || '' : '');
	let nsec = $state('');
	let nsecField = $state('');
	let password = $state('');
	let isLoggingIn = $state(false);

	async function login() {
		localStorage.setItem('useNip07', 'true');
		$ndk.signer = new NDKNip07Signer();
		await $ndk.connect(6000);
		await $ndk.signer!.user();
		activeUser.set($ndk.activeUser);
	}

	async function loginWithExistingNcryptSec() {
		let decrypted;
		try {
			decrypted = decryptNsec(ncryptsec, password);
			if (!decrypted) return alert('Invalid password');
		} catch (e) {
			return alert('Invalid password');
		}
		$ndk.signer = new NDKPrivateKeySigner(decrypted);
		await $ndk.connect(6000);

		activeUser.set(await $ndk.signer!.user());
		activeUser.set($ndk.activeUser);
		goto('/');
	}

	function loginWithNsec() {
		if (password.length < 32) return alert('Password must be at least 32 characters long');
		let nsecBytes = decodeKey(nsec);
		if (nsecBytes.type !== 'nsec') return alert('Invalid nsec');
		let encrypted = encryptNsec(nsecBytes.data, password);
		localStorage.setItem('ncryptsec', encrypted);
		$ndk.signer = new NDKPrivateKeySigner(nsec);
		$ndk.connect(6000);
		$ndk.signer!.user();
		activeUser.set($ndk.activeUser);
		goto('/');
	}

	function cancelLoginWithNsec() {
		if (!ncryptsec)
			nsec = '';
		nsecField = '';
		isLoggingIn = false;
	}

	function nsecOk() {
		try {
			let decoded = decodeKey(nsecField);
			if (decoded.type !== 'nsec')
				return alert('Invalid nsec');
			nsec = nsecField;
		} catch (e) {
			return alert('Invalid nsec');
		}
	}

	onMount(() => {
		if ($ndk.activeUser)
			activeUser.set($ndk.activeUser);
	});
</script>

{#if isLoggingIn}
	<div class="login-warning">
		<h3>🚨 Critical Security Warning 🚨</h3>
		<p>Your nsec is the master key to your ENTIRE Nostr identity. If someone gets it:</p>

		<ul class="warning-list">
			<li>They can read ALL your letters - past and future</li>
			<li>They can post ANYTHING pretending to be you</li>
			<li>They can take over your account PERMANENTLY</li>
			<li>There is NO WAY to undo this - not even we can help you</li>
			<li>Your account would be LOST FOREVER</li>
		</ul>

		<p class="warning-action">Only enter your nsec on devices you completely trust!</p>
		<p class="warning-final">If you're not 100% sure about this, STOP and use a signing extension instead (or use
			bunkers, coming soon).</p>
	</div>

	{#if ncryptsec || nsec}
		<h3>Password Required</h3>
		<p>
			First time here? Create a strong password that is AT LEAST 32 characters long.<br>
			A good approach is to use 4-5 random words with numbers and symbols between them.<br>
			Example: correct-horse9battery!staple$running<br /><br />
			<a
				href="https://xkcd.com/936/"
				target="_blank"
				rel="noopener"
				class="button"
			>
				(See this XKCD comic for why this works)
			</a>
		</p>
		<p class="warning-action">
			Your password is used to encrypt your nsec. Write it down somewhere safe, it cannot be recovered.
		</p>
		<input
			bind:value={password}
			type="password"
			placeholder="Minimum 32 characters"
			class="password-input"
		/>
		<div class="password-strength">
			Length: {password?.length || 0}/32 characters
		</div>
		<div class="button-group">
			<button onclick={cancelLoginWithNsec}>Go Back</button>
			<button
				onclick={ncryptsec ? loginWithExistingNcryptSec : loginWithNsec}
				disabled={password?.length < 32}
			>
				Sign In
			</button>
		</div>
	{:else}
		<p>
			Already have a Nostr account? Enter your nsec below.<br>
			Need an account? Create one using any of these popular clients:
		</p>
		<ul class="client-list">
			<li>
				<a href="https://nosta.me" target="_blank" rel="noopener">
					Nosta
					<span class="client-desc">Simple nostr client focused on profile creation and viewing</span>
				</a>
			</li>
			<li>
				<a href="https://primal.net" target="_blank" rel="noopener">
					Primal
					<span class="client-desc">Feature-rich web and mobile nostr client with great UI</span>
				</a>
			</li>
			<li>
				<a href="https://damus.io" target="_blank" rel="noopener">
					Damus
					<span class="client-desc">Popular iOS nostr client</span>
				</a>
			</li>
			<li>
				<a href="https://amethyst.social" target="_blank" rel="noopener">
					Amethyst
					<span class="client-desc">Feature-packed Android nostr client</span>
				</a>
			</li>
			<li>
				<a href="https://iris.to" target="_blank" rel="noopener">
					Iris
					<span class="client-desc">Minimalist web nostr client</span>
				</a>
			</li>
		</ul>
		<input
			bind:value={nsecField}
			type="password"
			placeholder="nsec1..."
			class="nsec-input"
		/>
		<button onclick={nsecOk}>Continue</button>
	{/if}
{:else}
	<button onclick={login}>Login with Nostr Extension</button>
	<button onclick={() => isLoggingIn = true}>Login with Nsec</button>
{/if}

<style>
  button {
    display: block;
    align-self: center;
  }

  .login-warning {
    display: flex;
    flex-direction: column;
    gap: var(--spacing-sm);
    margin-block: var(--spacing-md);
    background: var(--glass-bg);
    padding: var(--spacing-md);
  }

  .client-list {
    list-style: none;
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
    gap: var(--spacing-sm);
    margin: var(--spacing-md) 0;

    li {
      background: var(--glass-bg);
      border: 1px solid var(--glass-border);
      border-radius: 8px;
      padding: var(--spacing-sm);
      transition: all 0.3s ease;
      position: relative;
      isolation: isolate;

      &::before {
        content: '';
        position: absolute;
        inset: -2px;
        background: linear-gradient(45deg, var(--accent), transparent);
        border-radius: 10px;
        z-index: -1;
        opacity: 0;
        transition: opacity 0.3s ease;
      }

      &:hover {
        transform: translateY(-2px);
        box-shadow: 0 0 15px var(--glass-glow);

        &::before {
          opacity: 1;
        }
      }

      a {
        color: var(--text-primary);
        text-decoration: none;
        display: block;
        font-weight: 500;

        .client-desc {
          display: block;
          color: var(--text-secondary);
          font-size: 0.8em;
          margin-top: var(--spacing-xs);
          opacity: 0.7;
        }

        &:hover {
          text-decoration: underline;
        }
      }
    }
  }

  .warning-list {
    display: flex;
    flex-direction: column;
    gap: var(--spacing-sm);
    margin: var(--spacing-md) 0;

    li {
      backdrop-filter: blur(var(--blur-strength));
      background: var(--glass-bg-dark);
      border: 1px solid var(--glass-border);
      border-radius: 8px;
      padding: var(--spacing-sm);
      color: var(--text-primary);
      display: flex;
      align-items: center;
      gap: var(--spacing-sm);
      box-shadow: var(--depth-shadow);
      transition: transform 0.3s ease;

      &::before {
        content: "⚠️";
        font-size: 1.2em;
      }

      &:hover {
        transform: translateX(var(--spacing-xs));
        background: var(--glass-bg-darker);
      }
    }
  }

  .warning-action {
    backdrop-filter: blur(var(--blur-strength));
    background: var(--chip-error);
    border: 1px solid var(--glass-border);
    border-radius: 8px;
    padding: var(--spacing-md);
    margin: var(--spacing-md) 0;
    text-align: center;
    font-weight: 600;
    color: var(--text-primary);
    box-shadow: var(--depth-shadow),
    0 0 15px var(--glass-glow);

    &:hover {
      background: color-mix(in srgb, var(--chip-error) 80%, black);
    }
  }

  .warning-final {
    position: relative;
    text-align: center;
    padding: var(--spacing-md) 0;
    margin-top: var(--spacing-md);
    font-weight: 600;
    color: var(--text-primary);

    &::before {
      content: '';
      position: absolute;
      top: 0;
      left: 50%;
      transform: translateX(-50%);
      width: 80%;
      height: 2px;
      background: linear-gradient(
          90deg,
          transparent,
          var(--chip-error),
          transparent
      );
    }
  }
</style>