// Nostr Authentication Module
class NostrAuth {
    constructor() {
        this.sessionToken = localStorage.getItem('session_token');
        this.pubkey = localStorage.getItem('user_pubkey');
    }

    // Check if user is authenticated
    isAuthenticated() {
        return !!this.sessionToken && !!this.pubkey;
    }

    // Get current user pubkey
    getCurrentUser() {
        return this.pubkey;
    }

    // NIP-07 Login via browser extension (Alby, nos2x, etc.)
    async loginNIP07() {
        try {
            if (!window.nostr) {
                return {
                    success: false,
                    message: 'No Nostr extension detected. Please install a Nostr browser extension like Alby or nos2x, then refresh the page.'
                };
            }

            // Get challenge from server
            const challengeResponse = await fetch('/api/auth/challenge');
            
            if (!challengeResponse.ok) {
                if (challengeResponse.status === 429) {
                    return {
                        success: false,
                        message: 'Too many login attempts. Please wait a moment and try again.'
                    };
                }
                return {
                    success: false,
                    message: 'Server unavailable. Please try again later.'
                };
            }
            
            const challengeData = await challengeResponse.json();
            if (!challengeData.challenge) {
                return {
                    success: false,
                    message: 'Invalid server response. Please try again.'
                };
            }

            // Get pubkey from extension
            let pubkey;
            try {
                pubkey = await window.nostr.getPublicKey();
            } catch (error) {
                return {
                    success: false,
                    message: 'Extension denied access or is locked. Please unlock your Nostr extension and try again.'
                };
            }
            
            if (!pubkey || pubkey.length !== 64) {
                return {
                    success: false,
                    message: 'Invalid public key from extension. Please check your Nostr extension setup.'
                };
            }
            
            // Create authentication event (using kind 27235 for HTTP auth per NIP-98)
            const authEvent = {
                kind: 27235,
                created_at: Math.floor(Date.now() / 1000),
                tags: [
                    ['u', window.location.origin + '/api/auth/login'],
                    ['method', 'POST'],
                    ['challenge', challengeData.challenge]
                ],
                content: '',
                pubkey: pubkey
            };

            // Sign the event
            let signedEvent;
            try {
                signedEvent = await window.nostr.signEvent(authEvent);
            } catch (error) {
                return {
                    success: false,
                    message: 'Signing was cancelled or failed. Please try again and approve the signature request.'
                };
            }
            
            if (!signedEvent || !signedEvent.sig) {
                return {
                    success: false,
                    message: 'Invalid signature from extension. Please try again.'
                };
            }

            // Send to server for validation
            const loginResponse = await fetch('/api/auth/login', {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json',
                },
                body: JSON.stringify({
                    auth_type: 'nip07',
                    auth_event: JSON.stringify({
                        event: signedEvent,
                        challenge: challengeData.challenge
                    })
                })
            });

            const loginData = await loginResponse.json();

            if (!loginResponse.ok) {
                if (loginResponse.status === 429) {
                    return {
                        success: false,
                        message: 'Too many login attempts. Please wait a minute and try again.'
                    };
                } else if (loginResponse.status === 401) {
                    return {
                        success: false,
                        message: 'Authentication failed. Please check your Nostr extension and try again.'
                    };
                } else if (loginResponse.status >= 500) {
                    return {
                        success: false,
                        message: 'Server error. Please try again later.'
                    };
                }
                return {
                    success: false,
                    message: loginData.message || 'Login failed. Please try again.'
                };
            }

            // Store session info
            this.sessionToken = loginData.session_token;
            this.pubkey = loginData.pubkey;
            localStorage.setItem('session_token', this.sessionToken);
            localStorage.setItem('user_pubkey', this.pubkey);

            return {
                success: true,
                pubkey: this.pubkey,
                message: 'Successfully logged in via NIP-07'
            };

        } catch (error) {
            console.error('NIP-07 login failed:', error);
            return {
                success: false,
                message: error.message
            };
        }
    }

    // NIP-46 Login via bunker URL
    async loginNIP46(bunkerURL) {
        try {
            if (!bunkerURL || (!bunkerURL.startsWith('bunker://') && !bunkerURL.startsWith('nostrconnect://'))) {
                throw new Error('Invalid bunker URL format. Expected: bunker://... or nostrconnect://...');
            }

            // Send bunker URL to server for validation
            const loginResponse = await fetch('/api/auth/login', {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json',
                },
                body: JSON.stringify({
                    auth_type: 'nip46',
                    bunker_url: bunkerURL
                })
            });

            const loginData = await loginResponse.json();

            if (!loginResponse.ok) {
                throw new Error(loginData.message || 'NIP-46 login failed');
            }

            // Store session info
            this.sessionToken = loginData.session_token;
            this.pubkey = loginData.pubkey;
            localStorage.setItem('session_token', this.sessionToken);
            localStorage.setItem('user_pubkey', this.pubkey);

            return {
                success: true,
                pubkey: this.pubkey,
                message: 'Successfully logged in via NIP-46'
            };

        } catch (error) {
            console.error('NIP-46 login failed:', error);
            return {
                success: false,
                message: error.message
            };
        }
    }

    // Logout
    async logout() {
        try {
            await fetch('/api/auth/logout', {
                method: 'POST',
                credentials: 'include'
            });
        } catch (error) {
            console.error('Logout request failed:', error);
        }

        // Clear local storage
        this.sessionToken = null;
        this.pubkey = null;
        localStorage.removeItem('session_token');
        localStorage.removeItem('user_pubkey');
    }

    // Get user statistics
    async getUserStats() {
        if (!this.isAuthenticated()) {
            throw new Error('Not authenticated');
        }

        const response = await fetch('/api/users/me/stats', {
            credentials: 'include',
            headers: {
                'Authorization': `Bearer ${this.sessionToken}`
            }
        });

        if (!response.ok) {
            if (response.status === 401 || response.status === 403) {
                // Clear invalid session data
                this.sessionToken = null;
                this.pubkey = null;
                localStorage.removeItem('session_token');
                localStorage.removeItem('user_pubkey');
                throw new Error(`${response.status} Unauthorized - session expired`);
            }
            throw new Error(`Failed to get user stats (${response.status})`);
        }

        return await response.json();
    }

    // Get user's files
    async getUserFiles() {
        if (!this.isAuthenticated()) {
            throw new Error('Not authenticated');
        }

        const response = await fetch('/api/users/me/files', {
            credentials: 'include',
            headers: {
                'Authorization': `Bearer ${this.sessionToken}`
            }
        });

        if (!response.ok) {
            if (response.status === 401 || response.status === 403) {
                // Clear invalid session data
                this.sessionToken = null;
                this.pubkey = null;
                localStorage.removeItem('session_token');
                localStorage.removeItem('user_pubkey');
                throw new Error(`${response.status} Unauthorized - session expired`);
            }
            throw new Error(`Failed to get user files (${response.status})`);
        }

        return await response.json();
    }

    // Delete a file
    async deleteFile(hash) {
        if (!this.isAuthenticated()) {
            throw new Error('Not authenticated');
        }

        const response = await fetch(`/api/users/me/files/${hash}`, {
            method: 'DELETE',
            credentials: 'include',
            headers: {
                'Authorization': `Bearer ${this.sessionToken}`
            }
        });

        if (!response.ok) {
            if (response.status === 401 || response.status === 403) {
                // Clear invalid session data
                this.sessionToken = null;
                this.pubkey = null;
                localStorage.removeItem('session_token');
                localStorage.removeItem('user_pubkey');
                throw new Error(`${response.status} Unauthorized - session expired`);
            }
            const errorData = await response.text();
            throw new Error(errorData || `Failed to delete file (${response.status})`);
        }

        return await response.json();
    }

    // Update file access level
    async updateFileAccess(hash, accessLevel) {
        if (!this.isAuthenticated()) {
            throw new Error('Not authenticated');
        }

        const response = await fetch(`/api/users/me/files/${hash}/access`, {
            method: 'PUT',
            credentials: 'include',
            headers: {
                'Authorization': `Bearer ${this.sessionToken}`,
                'Content-Type': 'application/json'
            },
            body: JSON.stringify({ access_level: accessLevel })
        });

        if (!response.ok) {
            if (response.status === 401 || response.status === 403) {
                // Clear invalid session data
                this.sessionToken = null;
                this.pubkey = null;
                localStorage.removeItem('session_token');
                localStorage.removeItem('user_pubkey');
                throw new Error(`${response.status} Unauthorized - session expired`);
            }
            const errorData = await response.text();
            throw new Error(errorData || `Failed to update file access (${response.status})`);
        }

        return await response.json();
    }

    // Make authenticated request
    async makeAuthenticatedRequest(url, options = {}) {
        if (!this.isAuthenticated()) {
            throw new Error('Not authenticated');
        }

        const authOptions = {
            ...options,
            credentials: 'include',
            headers: {
                ...options.headers,
                'Authorization': `Bearer ${this.sessionToken}`
            }
        };

        return fetch(url, authOptions);
    }
}

// Global instance
window.nostrAuth = new NostrAuth();