<script lang="ts">
	import { onMount, tick } from 'svelte';
	import { isSignInRedirect, getProviderFromUrl } from '@lit-protocol/lit-auth-client';
	import type { IRelayPKP } from '@lit-protocol/types';
	import { ProviderType } from '@lit-protocol/constants';
	import { createMessage } from '$lib/services/messages';
	import { createLitSession } from '$lib/services/createLitSession/createLitSession';

	const redirectUri = 'http://localhost:5173/';

	export let setupLitProvider;

	let view = 'sign_in';
	let sessionSigs;
	let error;
	let isLoading = false;
	let currentPKP;
	let pkps: IRelayPKP[] = [];
	let authMethod;
	let provider;

	function logMessage(text, type = 'SYSTEM') {
		console.log(text);
		createMessage({
			text,
			sender: '$lib/components/GoogleAuth.svelte',
			type
		});
	}

	onMount(async () => {
		try {
			provider = await setupLitProvider.setupLitProvider();
			setupLitProvider.alertMe();

			logMessage('Component mounted.');

			if (!authMethod && isSignInRedirect(redirectUri)) {
				logMessage('Redirect detected, handling...');
				const providerName = getProviderFromUrl();
				if (providerName) {
					await handleRedirect(providerName);
				} else {
					logMessage('No provider detected in the URL.', 'ERROR');
				}
			} else {
				logMessage('No redirect detected.');
			}
		} catch (err) {
			setError(err);
		}
	});

	async function authWithGoogle() {
		try {
			await provider.signIn();
			await handleRedirect(ProviderType.Google);
		} catch (err) {
			setError(err);
		}
	}

	async function handleRedirect(providerName: string) {
		logMessage(`Handling redirect for ${providerName}`);

		if (!provider) throw new Error('Invalid provider.');
		authMethod = await provider.authenticate();
		await tick();

		view = 'fetching';
		pkps = await provider.fetchPKPsThroughRelayer(authMethod);
		view = pkps.length > 0 ? 'fetched' : 'NO_PKPS';

		logMessage(`Fetched PKPs: ${pkps.length}`);
	}

	async function mint() {
		try {
			view = 'MINTING';
			const newPKP: IRelayPKP = await mintPkp(provider, authMethod);
			pkps = [...pkps, newPKP];
			await createSession(newPKP);
			view = 'MINTED';
		} catch (err) {
			setError(err);
		}
	}

	async function createSession(pkp: IRelayPKP) {
		logMessage('Creating session...');
		view = 'CREATING_SESSION';

		sessionSigs = await createLitSession(provider, pkp.publicKey, authMethod);
		currentPKP = pkp;

		logMessage('Session created.');
		view = 'SESSION_CREATED';
	}

	function setError(err) {
		console.error(err);
		error = err;
		view = 'ERROR';
	}

	function resetView() {
		view = authMethod ? 'fetched' : 'sign_in';
		error = null;
	}
</script>

<main>
	{#if error}
		<h1>Error</h1>
		<p>{error.message}</p>
		<button on:click={resetView}>Got it</button>
	{:else if isLoading}
		<h1>Loading...</h1>
	{:else if view === 'sign_in'}
		<h1>Sign in with Lit</h1>
		<button on:click={authWithGoogle}>Google</button>
	{:else if view === 'fetching'}
		<h1>Fetching your PKPs...</h1>
	{:else if view === 'NO_PKPS'}
		<h1>No PKPs found.</h1>
		<button on:click={mint}>Mint a PKP</button>
	{:else if view === 'fetched'}
		<h1>Select a PKP to continue</h1>
		{#each pkps as pkp}
			<button on:click={async () => await createSession(pkp)}>{pkp.ethAddress}</button>
		{/each}
	{:else if view === 'MINTING'}
		<h1>Minting your PKP...</h1>
	{:else if view === 'MINTED'}
		<h1>Minted!</h1>
	{:else if view === 'CREATING_SESSION'}
		<h1>Creating session...</h1>
	{:else if view === 'SESSION_CREATED'}
		<h1>Ready for the open web</h1>
		<div>
			<p>Check out your PKP:</p>
			<p>{currentPKP.ethAddress}</p>
		</div>
	{/if}
</main>
