// static/shared/js/api-client.js
// noqa: js-001 - Core infrastructure, uses its own logger (apiLog)
/**
 * API Client for Multi-Tenant Ecommerce Platform
 *
 * Provides utilities for:
 * - Making authenticated API calls
 * - Token management
 * - Error handling
 * - Request/response interceptors
 */

// Log levels: 0 = None, 1 = Error, 2 = Warning, 3 = Info, 4 = Debug
const API_LOG_LEVEL = 3; // Set to 3 for production, 4 for full debugging

const apiLog = {
    error: (...args) => API_LOG_LEVEL >= 1 && console.error('❌ [API ERROR]', ...args),
    warn: (...args) => API_LOG_LEVEL >= 2 && console.warn('⚠️ [API WARN]', ...args),
    info: (...args) => API_LOG_LEVEL >= 3 && console.info('ℹ️ [API INFO]', ...args),
    debug: (...args) => API_LOG_LEVEL >= 4 && console.log('🔍 [API DEBUG]', ...args)
};

const API_BASE_URL = '/api/v1';

/**
 * API Client Class
 */
class APIClient {
    constructor(baseURL = API_BASE_URL) {
        this.baseURL = baseURL;
        apiLog.info('API Client initialized with base URL:', baseURL);
    }

    /**
     * Get stored authentication token
     *
     * Uses path-based detection to return the correct token:
     * - /admin/* routes use admin_token
     * - /store/* routes use store_token
     * - /shop/* routes use customer_token
     * - Other routes fall back to admin_token || store_token || customer_token
     */
    getToken() {
        const adminToken = localStorage.getItem('admin_token');
        const storeToken = localStorage.getItem('store_token');
        const customerToken = localStorage.getItem('customer_token');
        const currentPath = window.location.pathname;

        let token;
        let source;

        // Path-based token selection
        if (currentPath.startsWith('/store/') || currentPath.startsWith('/api/v1/store/')) {
            token = storeToken;
            source = 'store (path-based)';
        } else if (currentPath.startsWith('/admin/') || currentPath.startsWith('/api/v1/admin/')) {
            token = adminToken;
            source = 'admin (path-based)';
        } else if (currentPath.includes('/shop/') || currentPath.startsWith('/api/v1/shop/')) {
            token = customerToken;
            source = 'customer (path-based)';
        } else if (currentPath.startsWith('/merchants/') || currentPath.startsWith('/api/v1/merchants/')) {
            token = localStorage.getItem('merchant_token');
            source = 'merchant (path-based)';
        } else {
            // Default fallback for other paths
            token = adminToken || storeToken || customerToken;
            source = token === adminToken ? 'admin (fallback)' :
                     token === storeToken ? 'store (fallback)' : 'customer (fallback)';
        }

        apiLog.debug('Getting token:', {
            hasAdminToken: !!adminToken,
            hasStoreToken: !!storeToken,
            hasCustomerToken: !!customerToken,
            currentPath,
            source,
            usingToken: token ? source : 'none'
        });

        return token;
    }

    /**
     * Get default headers with authentication
     */
    getHeaders(additionalHeaders = {}) {
        const headers = {
            'Content-Type': 'application/json',
            ...additionalHeaders
        };

        const token = this.getToken();
        if (token) {
            headers['Authorization'] = `Bearer ${token}`;
            apiLog.debug('Authorization header added');
        } else {
            apiLog.debug('No token available, request will be unauthenticated');
        }

        return headers;
    }

    /**
     * Make API request
     */
    async request(endpoint, options = {}) {
        const url = `${this.baseURL}${endpoint}`;
        const method = options.method || 'GET';

        apiLog.info(`${method} ${url}`);
        apiLog.debug('Request options:', {
            method,
            hasBody: !!options.body,
            customHeaders: Object.keys(options.headers || {})
        });

        const config = {
            ...options,
            headers: this.getHeaders(options.headers)
        };

        try {
            const startTime = Date.now();
            const response = await fetch(url, config);
            const duration = Date.now() - startTime;

            apiLog.info(`Response: ${response.status} ${response.statusText} (${duration}ms)`);

            // Parse response (handle 204 No Content gracefully)
            let data;
            if (response.status === 204) {
                data = null;
            } else {
                try {
                    data = await response.json();
                    apiLog.debug('Response data received:', {
                        hasData: !!data,
                        dataType: typeof data,
                        keys: data ? Object.keys(data) : []
                    });
                } catch (parseError) {
                    apiLog.error('Failed to parse JSON response:', parseError);
                    throw new Error('Invalid JSON response from server');
                }
            }

            // Handle 401 Unauthorized - Just clear tokens, DON'T redirect
            if (response.status === 401) {
                apiLog.warn('401 Unauthorized - Authentication failed');
                apiLog.debug('Error details:', data);
                apiLog.info('Clearing authentication tokens');
                this.clearTokens();

                const errorMessage = data.message || data.detail || 'Unauthorized - please login again';
                apiLog.error('Throwing authentication error:', errorMessage);
                const authError = new Error(errorMessage);
                authError.status = response.status;
                authError.errorCode = data.error_code;
                throw authError;
            }

            // Handle non-OK responses
            if (!response.ok) {
                const errorMessage = data.detail || data.message || `Request failed with status ${response.status}`;
                apiLog.error('Request failed:', {
                    status: response.status,
                    message: errorMessage,
                    errorCode: data.error_code
                });
                const apiError = new Error(errorMessage);
                apiError.status = response.status;
                apiError.errorCode = data.error_code;
                throw apiError;
            }

            apiLog.info('Request completed successfully');
            return data;

        } catch (error) {
            // Log error details
            if (error.name === 'TypeError' && error.message.includes('fetch')) {
                apiLog.error('Network error - Failed to connect to server');
            } else {
                apiLog.error('Request error:', error.message);
            }

            apiLog.debug('Full error:', error);
            throw error;
        }
    }

    /**
     * GET request
     */
    async get(endpoint, params = {}) {
        const queryString = new URLSearchParams(params).toString();
        const url = queryString ? `${endpoint}?${queryString}` : endpoint;

        apiLog.debug('GET request params:', params);

        return this.request(url, {
            method: 'GET'
        });
    }

    /**
     * POST request
     */
    async post(endpoint, data = null) {
        apiLog.debug('POST request data:', {
            hasData: !!data,
            dataKeys: data ? Object.keys(data) : []
        });

        var opts = { method: 'POST' };
        if (data != null) opts.body = JSON.stringify(data);
        return this.request(endpoint, opts);
    }

    /**
     * PUT request
     */
    async put(endpoint, data = {}) {
        apiLog.debug('PUT request data:', {
            hasData: !!data,
            dataKeys: Object.keys(data)
        });

        return this.request(endpoint, {
            method: 'PUT',
            body: JSON.stringify(data)
        });
    }

    /**
     * PATCH request
     */
    async patch(endpoint, data = {}) {
        apiLog.debug('PATCH request data:', {
            hasData: !!data,
            dataKeys: Object.keys(data)
        });

        return this.request(endpoint, {
            method: 'PATCH',
            body: JSON.stringify(data)
        });
    }

    /**
     * DELETE request
     */
    async delete(endpoint) {
        apiLog.debug('DELETE request');

        return this.request(endpoint, {
            method: 'DELETE'
        });
    }

    /**
     * POST with FormData (for file uploads)
     * Does not set Content-Type header - browser sets it with boundary
     */
    async postFormData(endpoint, formData) {
        const url = `${this.baseURL}${endpoint}`;
        apiLog.info(`POST (FormData) ${url}`);

        const token = this.getToken();
        const headers = {};
        if (token) {
            headers['Authorization'] = `Bearer ${token}`;
        }

        try {
            const startTime = Date.now();
            const response = await fetch(url, {
                method: 'POST',
                headers,
                body: formData
            });
            const duration = Date.now() - startTime;

            apiLog.info(`Response: ${response.status} ${response.statusText} (${duration}ms)`);

            let data;
            try {
                data = await response.json();
            } catch (parseError) {
                apiLog.error('Failed to parse JSON response:', parseError);
                throw new Error('Invalid JSON response from server');
            }

            if (response.status === 401) {
                apiLog.warn('401 Unauthorized - Authentication failed');
                this.clearTokens();
                throw new Error(data.message || data.detail || 'Unauthorized');
            }

            if (!response.ok) {
                throw new Error(data.detail || data.message || `Request failed with status ${response.status}`);
            }

            return data;
        } catch (error) {
            apiLog.error('FormData request error:', error.message);
            throw error;
        }
    }

    /**
     * GET request that returns a Blob (for file downloads)
     */
    async getBlob(endpoint) {
        const url = `${this.baseURL}${endpoint}`;
        apiLog.info(`GET (Blob) ${url}`);

        const token = this.getToken();
        const headers = {};
        if (token) {
            headers['Authorization'] = `Bearer ${token}`;
        }

        try {
            const startTime = Date.now();
            const response = await fetch(url, {
                method: 'GET',
                headers
            });
            const duration = Date.now() - startTime;

            apiLog.info(`Response: ${response.status} ${response.statusText} (${duration}ms)`);

            if (response.status === 401) {
                apiLog.warn('401 Unauthorized - Authentication failed');
                this.clearTokens();
                throw new Error('Unauthorized');
            }

            if (!response.ok) {
                let errorMessage = `Request failed with status ${response.status}`;
                try {
                    const errorData = await response.json();
                    errorMessage = errorData.detail || errorData.message || errorMessage;
                } catch (e) {
                    // Response wasn't JSON
                }
                throw new Error(errorMessage);
            }

            return response.blob();
        } catch (error) {
            apiLog.error('Blob request error:', error.message);
            throw error;
        }
    }

    /**
     * Clear authentication tokens for current context only.
     *
     * Uses path-based detection to clear only the relevant token:
     * - /admin/* paths clear admin_token
     * - /store/* paths clear store_token
     * - /shop/* paths clear customer_token
     * - Other paths clear all tokens (fallback)
     */
    clearTokens() {
        const currentPath = window.location.pathname;

        apiLog.info('Clearing authentication tokens for path:', currentPath);

        const tokensBefore = {
            admin_token: !!localStorage.getItem('admin_token'),
            admin_user: !!localStorage.getItem('admin_user'),
            store_token: !!localStorage.getItem('store_token'),
            store_user: !!localStorage.getItem('store_user'),
            customer_token: !!localStorage.getItem('customer_token'),
            token: !!localStorage.getItem('token')
        };
        apiLog.debug('Tokens before clear:', tokensBefore);

        // Context-aware token clearing to prevent cross-context interference
        if (currentPath.startsWith('/admin/') || currentPath.startsWith('/api/v1/admin/')) {
            apiLog.info('Clearing admin tokens only');
            localStorage.removeItem('admin_token');
            localStorage.removeItem('admin_user');
        } else if (currentPath.startsWith('/store/') || currentPath.startsWith('/api/v1/store/')) {
            apiLog.info('Clearing store tokens only');
            localStorage.removeItem('store_token');
            localStorage.removeItem('store_user');
            localStorage.removeItem('currentUser');
            localStorage.removeItem('storeCode');
        } else if (currentPath.includes('/shop/') || currentPath.startsWith('/api/v1/shop/')) {
            apiLog.info('Clearing customer tokens only');
            localStorage.removeItem('customer_token');
        } else if (currentPath.startsWith('/merchants/') || currentPath.startsWith('/api/v1/merchants/')) {
            apiLog.info('Clearing merchant tokens only');
            localStorage.removeItem('merchant_token');
        } else {
            // Fallback: clear all tokens for unknown paths
            apiLog.info('Unknown path context, clearing all tokens');
            localStorage.removeItem('admin_token');
            localStorage.removeItem('admin_user');
            localStorage.removeItem('store_token');
            localStorage.removeItem('store_user');
            localStorage.removeItem('customer_token');
            localStorage.removeItem('currentUser');
            localStorage.removeItem('storeCode');
            localStorage.removeItem('token');
        }

        const tokensAfter = {
            admin_token: !!localStorage.getItem('admin_token'),
            admin_user: !!localStorage.getItem('admin_user'),
            store_token: !!localStorage.getItem('store_token'),
            store_user: !!localStorage.getItem('store_user'),
            customer_token: !!localStorage.getItem('customer_token'),
            token: !!localStorage.getItem('token')
        };
        apiLog.debug('Tokens after clear:', tokensAfter);
        apiLog.info('Context-specific tokens cleared');
    }

    /**
     * Handle unauthorized access
     * DEPRECATED - Now just clears tokens, doesn't redirect
     * Server handles redirects via exception handler
     */
    handleUnauthorized() {
        apiLog.warn('handleUnauthorized called (DEPRECATED) - use clearTokens instead');
        this.clearTokens();
    }
}

// Create global API client instance
const apiClient = new APIClient();
apiLog.info('Global API client created');

/**
 * Authentication helpers
 */
const Auth = {
    /**
     * Check if user is authenticated
     */
    isAuthenticated() {
        const token = localStorage.getItem('admin_token') || localStorage.getItem('store_token');
        const isAuth = !!token;
        apiLog.debug('Auth check:', isAuth ? 'authenticated' : 'not authenticated');
        return isAuth;
    },

    /**
     * Get current user
     */
    getCurrentUser() {
        const userStr = localStorage.getItem('admin_user') || localStorage.getItem('store_user');
        if (!userStr) {
            apiLog.debug('No user found in storage');
            return null;
        }

        try {
            const user = JSON.parse(userStr);
            apiLog.debug('Current user:', {
                username: user.username,
                role: user.role,
                id: user.id
            });
            return user;
        } catch (e) {
            apiLog.error('Failed to parse user data:', e);
            return null;
        }
    },

    /**
     * Check if user is admin
     */
    isAdmin() {
        const user = this.getCurrentUser();
        const isAdmin = user && ['super_admin', 'platform_admin'].includes(user.role);
        apiLog.debug('Admin check:', isAdmin ? 'is admin' : 'not admin');
        return isAdmin;
    },

    /**
     * Login
     */
    async login(username, password) {
        apiLog.info('Auth.login called');
        const response = await apiClient.post('/auth/login', {
            username,
            password
        });

        // Store token and user
        if (['super_admin', 'platform_admin'].includes(response.user.role)) {
            apiLog.info('Storing admin credentials');
            localStorage.setItem('admin_token', response.access_token);
            localStorage.setItem('admin_user', JSON.stringify(response.user));
        } else {
            apiLog.info('Storing store credentials');
            localStorage.setItem('store_token', response.access_token);
            localStorage.setItem('store_user', JSON.stringify(response.user));
        }

        return response;
    },

    /**
     * Logout
     */
    logout() {
        apiLog.info('Auth.logout called');
        apiClient.clearTokens();
        apiLog.info('User logged out');
    }
};

// Add animation styles
const style = document.createElement('style');
style.textContent = `
    @keyframes slideIn {
        from {
            transform: translateX(400px);
            opacity: 0;
        }
        to {
            transform: translateX(0);
            opacity: 1;
        }
    }

    @keyframes slideOut {
        from {
            transform: translateX(0);
            opacity: 1;
        }
        to {
            transform: translateX(400px);
            opacity: 0;
        }
    }
`;
document.head.appendChild(style);

// Export for use in other scripts
if (typeof module !== 'undefined' && module.exports) {
    module.exports = { APIClient, apiClient, Auth, Utils };
}

// Table scroll detection helper
function initTableScrollDetection() {
    const observer = new MutationObserver(() => {
        const tables = document.querySelectorAll('.table-responsive');
        tables.forEach(table => {
            if (!table.hasAttribute('data-scroll-initialized')) {
                table.setAttribute('data-scroll-initialized', 'true');

                table.addEventListener('scroll', function() {
                    if (this.scrollLeft > 0) {
                        this.classList.add('is-scrolled');
                    } else {
                        this.classList.remove('is-scrolled');
                    }
                });

                // Check initial state
                if (table.scrollLeft > 0) {
                    table.classList.add('is-scrolled');
                }
            }
        });
    });

    observer.observe(document.body, {
        childList: true,
        subtree: true
    });
}

// Initialize when DOM is ready
if (document.readyState === 'loading') {
    document.addEventListener('DOMContentLoaded', initTableScrollDetection);
} else {
    initTableScrollDetection();
}

apiLog.info('API Client module loaded');
