---
import { encrypt } from '../../plugins/encrypt';
import {siteConfig} from "../../config";

interface Props {
    password?: string;
    pwEnv?: string;
}

const { password: propPassword, pwEnv } = Astro.props;
// Get password from props, environment variable, or site config
const password = (pwEnv ? import.meta.env[pwEnv] : propPassword) || siteConfig.contentPassword || import.meta.env.CONTENT_PASSWORD;

// Get the slot content
const content = await Astro.slots.render('default');

// Encrypt content at build time
const { encryptedData, iv } = encrypt(content, password);
---

<div class="encrypted-content" data-encrypted={encryptedData} data-iv={iv}>
    <div class="password-form">
        <p>This content is protected. Enter the password to view it:</p>
        <div>
            <input type="password" class="decrypt-password" title="password" />
            <button class="decrypt-button">Decrypt</button>
        </div>
    </div>
    <div class="content-container hidden"></div>
</div>

<style>
    div.password-form {
        margin: 0.25rem auto;
    }
    div.password-form div {
        margin: 0.25rem auto;
    }
    input[type="password"] {
        background: var(--accent-color);
        color: var(--bg-color);
        border: none;
        padding: 0.25rem;
    }
    button {
        background-color: var(--accent-color);
        color: var(--bg-color);
        border: none;
        padding: 0.25rem;
    }
    div.hidden {
        display: none;
    }
</style>

<script>
    // Define the function that sets up the decryption logic
    function setupDecryption() {
        const containers = document.querySelectorAll('.encrypted-content');

        containers.forEach(container => {
            const encryptedData = container.getAttribute('data-encrypted');
            const iv = container.getAttribute('data-iv');
            const passwordInput = container.querySelector<HTMLInputElement>('.decrypt-password');
            const decryptButton = container.querySelector<HTMLButtonElement>('.decrypt-button');
            const contentContainer = container.querySelector<HTMLDivElement>('.content-container');
            const passwordForm = container.querySelector<HTMLDivElement>('.password-form');

            if (!encryptedData || !iv || !passwordInput || !decryptButton || !contentContainer || !passwordForm) {
                console.error('Missing required elements for decryption');
                return;
            }

            // Skip if already initialized to prevent duplicate event listeners
            if (container.getAttribute("initialized") === 'true') {
                return;
            }

            decryptButton.addEventListener('click', async () => {
                try {
                    const password = passwordInput.value;
                    if (!password) return;

                    contentContainer.innerHTML = await decrypt(encryptedData, iv, password);
                    contentContainer.classList.remove('hidden');
                    passwordForm.classList.add('hidden');
                } catch (error) {
                    alert('Incorrect password');
                    console.error('Decryption failed:', error);
                }
            });

            // Allow pressing Enter to decrypt
            passwordInput.addEventListener('keydown', (e: KeyboardEvent) => {
                if (e.key === 'Enter') {
                    decryptButton.click();
                }
            });

            // Mark as initialized to prevent duplicate event listeners
            container.setAttribute("initialized", 'true');
        });
    }

    async function decrypt(encryptedData: string, iv: string, password: string): Promise<string> {
        // Convert base64 to array buffer
        const encryptedBytes = Uint8Array.from(atob(encryptedData), c => c.charCodeAt(0));
        const ivBytes = Uint8Array.from(atob(iv), c => c.charCodeAt(0));

        // Derive key from password
        const encoder = new TextEncoder();
        const passwordBytes = encoder.encode(password);
        const keyMaterial = await window.crypto.subtle.importKey(
            'raw',
            passwordBytes,
            { name: 'PBKDF2' },
            false,
            ['deriveBits', 'deriveKey']
        );

        const key = await window.crypto.subtle.deriveKey(
            {
                name: 'PBKDF2',
                salt: ivBytes,
                iterations: 100000,
                hash: 'SHA-256'
            },
            keyMaterial,
            { name: 'AES-GCM', length: 256 },
            false,
            ['decrypt']
        );

        // Decrypt
        const decryptedBytes = await window.crypto.subtle.decrypt(
            { name: 'AES-GCM', iv: ivBytes },
            key,
            encryptedBytes
        );

        // Convert array buffer to text
        const decoder = new TextDecoder();
        return decoder.decode(decryptedBytes);
    }

    // Initialize on page load
    document.addEventListener('DOMContentLoaded', setupDecryption);

    // Re-initialize when Astro's view transitions occur, this provides fix for SPA navigation
    document.addEventListener('astro:page-load', setupDecryption);
</script>