// Main server file - refactored and organized
const express = require('express');
const path = require('path');
const fs = require('fs');
const { v4: uuidv4 } = require('uuid');

// Import configuration and utilities
const config = require('./config/environment');
const { auditLog, tokenLog } = require('./utils/logging');
const rateLimit = require('./middleware/rate-limit');
const { authenticateBasicAuth } = require('./middleware/auth');
const { validateApiKey } = require('./middleware/api-key-auth');

// Import routes
const paymentsRouter = require('./routes/payments');
const adminRouter = require('./routes/admin');
const adminLoginRouter = require('./routes/admin-login');
const adminTransactionsRouter = require('./routes/admin-transactions');
const adminCustomersRouter = require('./routes/admin-customers');
const adminCustomerDetailsRouter = require('./routes/admin-customer-details');
const adminApiRouter = require('./routes/admin-api');

// Import services (for token management)
const QuickBooksPaymentsService = require('./services/quickbooks-payments');
const QuickBooksOnlineService = require('./services/quickbooks-online');

// Validate environment variables
try {
    config.validateRequired();
} catch (error) {
    console.error('❌ Environment validation failed:', error.message);
    process.exit(1);
}

const app = express();

// === GLOBAL STATE ===
let accessToken = null;
let refreshToken = null;
let tokenExpiresAt = null;
let realmId = null;

// Token persistence
const TOKENS_FILE = path.join(__dirname, '..', '.tokens.json');

// === MIDDLEWARE ===
app.use(express.json({ limit: '10mb' }));
app.use(express.urlencoded({ extended: true, limit: '10mb' }));

// Request ID middleware
app.use((req, res, next) => {
    req.requestId = uuidv4();
    next();
});

// API Key validation middleware (for admin API endpoints)
app.use(validateApiKey);

// CORS middleware
app.use((req, res, next) => {
    res.header('Access-Control-Allow-Origin', '*');
    res.header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');
    res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Admin-API-Key');
    
    if (req.method === 'OPTIONS') {
        res.sendStatus(200);
    } else {
        next();
    }
});

// Make QuickBooks state available to routes
app.use((req, res, next) => {
    req.app.locals.quickbooks = {
        accessToken,
        refreshToken,
        realmId,
        environment: config.QB_ENVIRONMENT
    };
    next();
});

// === TOKEN PERSISTENCE ===

const saveTokens = () => {
    try {
        const tokenData = {
            accessToken,
            refreshToken,
            tokenExpiresAt: tokenExpiresAt,
            realmId
        };
        fs.writeFileSync(TOKENS_FILE, JSON.stringify(tokenData, null, 2));
        tokenLog('Tokens saved to file');
    } catch (error) {
        tokenLog('Error saving tokens', { error: error.message });
    }
};

// Token refresh function
const refreshAccessToken = async (retryCount = 0) => {
    if (!refreshToken) return false;
    
    const maxRetries = 3;
    const baseDelay = 1000; // 1 second base delay
    
    try {
        const querystring = require('querystring');
        const postData = querystring.stringify({
            grant_type: 'refresh_token',
            refresh_token: refreshToken
        });
        
        const options = {
            method: 'POST',
            headers: {
                'Authorization': `Basic ${Buffer.from(`${config.QB_CLIENT_ID}:${config.QB_CLIENT_SECRET}`).toString('base64')}`,
                'Content-Type': 'application/x-www-form-urlencoded',
                'Content-Length': Buffer.byteLength(postData)
            },
            timeout: 10000 // 10 second timeout for token refresh
        };
        
        const tokenEndpoint = 'https://oauth.platform.intuit.com/oauth2/v1/tokens/bearer';
        const { makeHttpsRequest } = require('./utils/network');
        const response = await makeHttpsRequest(tokenEndpoint, options, postData);
        
        if (response.data && response.data.access_token) {
            accessToken = response.data.access_token;
            tokenExpiresAt = Date.now() + (response.data.expires_in * 1000);
            if (response.data.refresh_token) refreshToken = response.data.refresh_token;
            
            // Save refreshed tokens to file
            saveTokens();
            
            auditLog('TOKEN_REFRESHED', { 
                expiresIn: response.data.expires_in,
                retryAttempt: retryCount > 0 ? retryCount : 'first_attempt'
            });
            return true;
        }
    } catch (error) {
        const isNetworkError = error.message.includes('ECONNRESET') || 
                              error.message.includes('socket hang up') || 
                              error.message.includes('timeout') ||
                              error.message.includes('ETIMEDOUT') ||
                              error.message.includes('ENOTFOUND');
        
        auditLog('TOKEN_REFRESH_FAILED', { 
            error: error.message,
            retryAttempt: retryCount,
            isNetworkError: isNetworkError,
            willRetry: isNetworkError && retryCount < maxRetries
        });
        
        // Retry on network errors with exponential backoff
        if (isNetworkError && retryCount < maxRetries) {
            const delay = baseDelay * Math.pow(2, retryCount); // Exponential backoff: 1s, 2s, 4s
            auditLog('TOKEN_REFRESH_RETRY_SCHEDULED', { 
                retryAttempt: retryCount + 1,
                delayMs: delay,
                maxRetries: maxRetries
            });
            
            // Wait before retrying
            await new Promise(resolve => setTimeout(resolve, delay));
            
            // Recursive retry
            return await refreshAccessToken(retryCount + 1);
        }
    }
    return false;
};

// Load tokens from file
const loadTokens = () => {
    try {
        if (fs.existsSync(TOKENS_FILE)) {
            const data = JSON.parse(fs.readFileSync(TOKENS_FILE, 'utf8'));
            console.error('TOKENS_LOADED:', { 
                hasAccessToken: !!data.accessToken, 
                hasRefreshToken: !!data.refreshToken,
                expiresAt: data.tokenExpiresAt ? new Date(data.tokenExpiresAt).toISOString() : null
            });
            
            // Update global variables
            accessToken = data.accessToken;
            refreshToken = data.refreshToken;
            tokenExpiresAt = data.tokenExpiresAt;
            realmId = data.realmId;
            
            return {
                accessToken: data.accessToken,
                refreshToken: data.refreshToken,
                tokenExpiresAt: data.tokenExpiresAt,
                realmId: data.realmId
            };
        }
    } catch (error) {
        console.error('TOKEN_LOAD_ERROR:', error.message);
    }
    console.error('TOKENS_NOT_FOUND:', { file: TOKENS_FILE });
    return { accessToken: null, refreshToken: null, tokenExpiresAt: 0, realmId: null };
};

// Initialize tokens immediately on startup (like server.js.old)
const initTokens = () => {
    const tokens = loadTokens();
    accessToken = tokens.accessToken;
    refreshToken = tokens.refreshToken;
    tokenExpiresAt = tokens.tokenExpiresAt;
    realmId = tokens.realmId;
    
    if (accessToken) {
        console.error('TOKENS_INITIALIZED: QuickBooks connection restored from file');
        console.error('TOKEN_STATUS:', {
            hasAccessToken: !!accessToken,
            hasRefreshToken: !!refreshToken,
            expiresAt: tokenExpiresAt ? new Date(tokenExpiresAt).toISOString() : null,
            realmId: realmId
        });
    } else {
        console.error('TOKENS_INITIALIZED: No saved tokens found - will need to connect to QuickBooks');
    }
};

// Note: initTokens() will be called during server startup to avoid hoisting issues

// === TOKEN MONITORING SYSTEM ===
let tokenMonitorInterval = null;

const startTokenMonitor = () => {
    if (tokenMonitorInterval) {
        clearInterval(tokenMonitorInterval);
    }
    
    tokenMonitorInterval = setInterval(async () => {
        const now = Date.now();
        const timeUntilExpiry = tokenExpiresAt - now;
        
        // Log token status every 30 minutes (but check every minute)
        if (now % 1800000 < 60000) { // Every 30 minutes
            auditLog('TOKEN_STATUS_CHECK', {
                hasAccessToken: !!accessToken,
                hasRefreshToken: !!refreshToken,
                timeUntilExpiry: Math.floor(timeUntilExpiry / 1000),
                timeUntilExpiryMinutes: Math.floor(timeUntilExpiry / (60 * 1000)),
                expiresAt: tokenExpiresAt ? new Date(tokenExpiresAt).toISOString() : null,
                realmId: realmId
            });
            console.error('TOKEN_STATUS_CHECK:', {
                timeUntilExpiryMinutes: Math.floor(timeUntilExpiry / (60 * 1000)),
                expiresAt: tokenExpiresAt ? new Date(tokenExpiresAt).toISOString() : null
            });
        }
        
        // Refresh token if it expires in less than 10 minutes (600,000 ms) - CRITICAL TIMING
        if (accessToken && refreshToken && timeUntilExpiry < 600000 && timeUntilExpiry > 0) {
            console.error('TOKEN_REFRESH_SCHEDULED: Token expires in', Math.floor(timeUntilExpiry / 1000), 'seconds - refreshing now!');
            auditLog('TOKEN_REFRESH_SCHEDULED', { 
                timeUntilExpiry: Math.floor(timeUntilExpiry / 1000),
                timeUntilExpiryMinutes: Math.floor(timeUntilExpiry / (60 * 1000)),
                reason: 'proactive_refresh'
            });
            
            const refreshed = await refreshAccessToken();
            if (refreshed) {
                console.error('TOKEN_REFRESH_SUCCESS: Token refreshed successfully, new expiry:', new Date(tokenExpiresAt).toISOString());
                auditLog('TOKEN_REFRESH_SUCCESS', { 
                    newExpiresAt: new Date(tokenExpiresAt).toISOString(),
                    newTimeUntilExpiry: Math.floor((tokenExpiresAt - Date.now()) / (60 * 1000))
                });
            } else {
                console.error('TOKEN_REFRESH_FAILED: Failed to refresh token!');
                auditLog('TOKEN_REFRESH_FAILED_SCHEDULED', { 
                    timeUntilExpiry: Math.floor(timeUntilExpiry / 1000)
                });
            }
        }
        
        // Log if token is expired
        if (timeUntilExpiry <= 0 && accessToken) {
            console.error('TOKEN_EXPIRED: Token has expired!', new Date(tokenExpiresAt).toISOString());
            auditLog('TOKEN_EXPIRED', { 
                expiredAt: new Date(tokenExpiresAt).toISOString(),
                hasRefreshToken: !!refreshToken
            });
        }
    }, 60000); // Check every minute - CRITICAL FOR TIMELY REFRESH
    
    console.error('TOKEN_MONITOR_STARTED: Checking every 60 seconds, refreshing when <10 minutes remain');
    auditLog('TOKEN_MONITOR_STARTED', { interval: '60000ms', refreshThreshold: '600000ms' });
};

const stopTokenMonitor = () => {
    if (tokenMonitorInterval) {
        clearInterval(tokenMonitorInterval);
        tokenMonitorInterval = null;
        console.error('TOKEN_MONITOR_STOPPED');
        auditLog('TOKEN_MONITOR_STOPPED');
    }
};

// === ROUTES ===

// Middleware to pass QuickBooks tokens to routes
const qbTokenMiddleware = (req, res, next) => {
    req.qbTokens = {
        accessToken,
        refreshToken,
        tokenExpiresAt,
        realmId,
        refreshAccessToken
    };
    next();
};

// Mount route modules
app.use('/api/payments', paymentsRouter);
app.use('/admin', qbTokenMiddleware, adminRouter);
app.use('/admin', qbTokenMiddleware, adminLoginRouter);
app.use('/admin', qbTokenMiddleware, adminTransactionsRouter);
app.use('/admin', qbTokenMiddleware, adminCustomersRouter);
app.use('/admin', qbTokenMiddleware, adminCustomerDetailsRouter);

// Mount admin API routes (for QuickBooks Elementor widget compatibility)
app.use('/admin/api', qbTokenMiddleware, adminApiRouter);

// Health check
app.get('/health', (req, res) => {
    res.json({
        status: 'healthy',
        timestamp: new Date().toISOString(),
        environment: config.NODE_ENV,
        nodeVersion: process.version,
        platform: process.platform,
        uptime: process.uptime(),
        quickbooks: {
            connected: !!accessToken && !!realmId,
            tokenExpiry: tokenExpiresAt ? new Date(tokenExpiresAt).toISOString() : null,
            environment: config.QB_ENVIRONMENT,
            realmId: realmId || null
        }
    });
});

// QuickBooks OAuth endpoints
app.get('/auth/quickbooks', (req, res) => {
    const state = uuidv4();
    const scope = 'com.intuit.quickbooks.accounting com.intuit.quickbooks.payment';
    
    console.error('QB_AUTH_DEBUG: Redirect URI being used:', config.QB_REDIRECT_URI);
    console.error('QB_AUTH_DEBUG: Client ID:', config.QB_CLIENT_ID);
    console.error('QB_AUTH_DEBUG: Environment:', config.QB_ENVIRONMENT);
    
    const authUrl = `https://appcenter.intuit.com/connect/oauth2?` +
        `client_id=${config.QB_CLIENT_ID}&` +
        `scope=${encodeURIComponent(scope)}&` +
        `redirect_uri=${encodeURIComponent(config.QB_REDIRECT_URI)}&` +
        `response_type=code&` +
        `access_type=offline&` +
        `state=${state}`;
    
    console.error('QB_AUTH_DEBUG: Full auth URL:', authUrl);
    
    auditLog('QB_AUTH_REDIRECT', { 
        state, 
        scope, 
        redirectUri: config.QB_REDIRECT_URI,
        clientId: config.QB_CLIENT_ID 
    }, req);
    res.redirect(authUrl);
});

app.get('/auth/callback', async (req, res) => {
    const { code, realmId: callbackRealmId, error } = req.query;
    
    if (error) {
        auditLog('QB_AUTH_ERROR', { error }, req);
        return res.status(400).send(`Authentication error: ${error}`);
    }
    
    if (!code || !callbackRealmId) {
        auditLog('QB_AUTH_MISSING_PARAMS', { hasCode: !!code, hasRealmId: !!callbackRealmId }, req);
        return res.status(400).send('Missing authorization code or realm ID');
    }
    
    try {
        // Exchange code for tokens
        const tokenData = await exchangeCodeForTokens(code);
        
        accessToken = tokenData.access_token;
        refreshToken = tokenData.refresh_token;
        tokenExpiresAt = Date.now() + (tokenData.expires_in * 1000);
        realmId = callbackRealmId;
        
        saveTokens();
        
        auditLog('QB_AUTH_SUCCESS', { 
            realmId: callbackRealmId,
            expiresIn: tokenData.expires_in
        }, req);
        
        res.send(`
            <h1>✅ QuickBooks Connected Successfully!</h1>
            <p><strong>Company ID:</strong> ${callbackRealmId}</p>
            <p><strong>Token expires:</strong> ${new Date(tokenExpiresAt).toLocaleString()}</p>
            <p><a href="/admin/dashboard">Go to Admin Dashboard</a></p>
        `);
    } catch (error) {
        auditLog('QB_TOKEN_EXCHANGE_ERROR', { error: error.message }, req);
        res.status(500).send(`Token exchange failed: ${error.message}`);
    }
});

// Admin dashboard
app.get('/admin/dashboard', authenticateBasicAuth, (req, res) => {
    const isConnected = !!accessToken && !!realmId;
    const tokenExpiry = tokenExpiresAt ? new Date(tokenExpiresAt) : null;
    const isTokenValid = tokenExpiry && tokenExpiry > new Date();
    const tokenExpiresIn = tokenExpiry ? Math.max(0, Math.floor((tokenExpiry - new Date()) / 1000 / 60)) : 0;
    
    res.send(`
        <!DOCTYPE html>
        <html>
        <head>
            <title>QuickBooks Payment Gateway - Admin Dashboard</title>
            <meta name="viewport" content="width=device-width, initial-scale=1.0">
            <style>
                * { box-sizing: border-box; }
                body { 
                    font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; 
                    margin: 0; 
                    padding: 20px; 
                    background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
                    min-height: 100vh;
                }
                .container { 
                    max-width: 1200px; 
                    margin: 0 auto; 
                    background: white; 
                    border-radius: 12px; 
                    box-shadow: 0 10px 30px rgba(0,0,0,0.2);
                    overflow: hidden;
                }
                .header {
                    background: linear-gradient(135deg, #007cba, #005a87);
                    color: white;
                    padding: 30px;
                    text-align: center;
                }
                .header h1 {
                    margin: 0;
                    font-size: 28px;
                    font-weight: 300;
                }
                .header p {
                    margin: 10px 0 0 0;
                    opacity: 0.9;
                    font-size: 16px;
                }
                .content {
                    padding: 30px;
                }
                .dashboard-grid {
                    display: grid;
                    grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
                    gap: 20px;
                    margin-bottom: 30px;
                }
                .card {
                    background: #f8f9fa;
                    border-radius: 8px;
                    padding: 20px;
                    border-left: 4px solid #007cba;
                }
                .card h3 {
                    margin: 0 0 15px 0;
                    color: #333;
                    font-size: 18px;
                }
                .status-indicator {
                    display: inline-flex;
                    align-items: center;
                    padding: 8px 12px;
                    border-radius: 20px;
                    font-size: 14px;
                    font-weight: 500;
                    margin-bottom: 10px;
                }
                .status-connected {
                    background: #d4edda;
                    color: #155724;
                    border: 1px solid #c3e6cb;
                }
                .status-disconnected {
                    background: #f8d7da;
                    color: #721c24;
                    border: 1px solid #f5c6cb;
                }
                .status-warning {
                    background: #fff3cd;
                    color: #856404;
                    border: 1px solid #ffeaa7;
                }
                .info-row {
                    display: flex;
                    justify-content: space-between;
                    align-items: center;
                    padding: 8px 0;
                    border-bottom: 1px solid #eee;
                }
                .info-row:last-child {
                    border-bottom: none;
                }
                .info-label {
                    font-weight: 500;
                    color: #666;
                }
                .info-value {
                    color: #333;
                    font-family: monospace;
                }
                .actions {
                    display: flex;
                    gap: 10px;
                    flex-wrap: wrap;
                    margin-top: 20px;
                }
                .btn {
                    display: inline-flex;
                    align-items: center;
                    padding: 12px 20px;
                    border: none;
                    border-radius: 6px;
                    text-decoration: none;
                    font-size: 14px;
                    font-weight: 500;
                    cursor: pointer;
                    transition: all 0.2s;
                }
                .btn-primary {
                    background: linear-gradient(135deg, #007cba, #005a87);
                    color: white;
                }
                .btn-primary:hover {
                    transform: translateY(-2px);
                    box-shadow: 0 4px 12px rgba(0,124,186,0.3);
                }
                .btn-success {
                    background: linear-gradient(135deg, #28a745, #20c997);
                    color: white;
                }
                .btn-success:hover {
                    transform: translateY(-2px);
                    box-shadow: 0 4px 12px rgba(40,167,69,0.3);
                }
                .btn-warning {
                    background: linear-gradient(135deg, #ffc107, #fd7e14);
                    color: #333;
                }
                .btn-warning:hover {
                    transform: translateY(-2px);
                    box-shadow: 0 4px 12px rgba(255,193,7,0.3);
                }
                .btn-danger {
                    background: linear-gradient(135deg, #dc3545, #c82333);
                    color: white;
                }
                .btn-danger:hover {
                    transform: translateY(-2px);
                    box-shadow: 0 4px 12px rgba(220,53,69,0.3);
                }
                .btn-secondary {
                    background: #6c757d;
                    color: white;
                }
                .btn-secondary:hover {
                    background: #545b62;
                    transform: translateY(-2px);
                }
                .refresh-indicator {
                    display: none;
                    margin-left: 8px;
                }
                .refresh-indicator.spinning {
                    display: inline-block;
                    animation: spin 1s linear infinite;
                }
                @keyframes spin {
                    from { transform: rotate(0deg); }
                    to { transform: rotate(360deg); }
                }
                .footer {
                    background: #f8f9fa;
                    padding: 20px 30px;
                    border-top: 1px solid #eee;
                    text-align: center;
                    color: #666;
                    font-size: 14px;
                }
                @media (max-width: 768px) {
                    .dashboard-grid {
                        grid-template-columns: 1fr;
                    }
                    .actions {
                        flex-direction: column;
                    }
                    .btn {
                        justify-content: center;
                    }
                }
            </style>
        </head>
        <body>
            <div class="container">
                <div class="header">
                    <h1>🏢 QuickBooks Payment Gateway</h1>
                    <p>Admin Dashboard & System Control Panel</p>
                </div>
                
                <div class="content">
                    <div class="dashboard-grid">
                        <!-- Gateway Status Card -->
                        <div class="card">
                            <h3>🚀 Gateway Status</h3>
                            <div class="status-indicator status-connected">
                                ✅ Online & Operational
                            </div>
                            <div class="info-row">
                                <span class="info-label">Server Status:</span>
                                <span class="info-value">Running</span>
                            </div>
                            <div class="info-row">
                                <span class="info-label">Uptime:</span>
                                <span class="info-value" id="uptime">Loading...</span>
                            </div>
                            <div class="info-row">
                                <span class="info-label">Port:</span>
                                <span class="info-value">${config.PORT}</span>
                            </div>
                            <div class="info-row">
                                <span class="info-label">Environment:</span>
                                <span class="info-value">${config.NODE_ENV}</span>
                            </div>
                        </div>

                        <!-- QuickBooks Connection Card -->
                        <div class="card">
                            <h3>📊 QuickBooks Connection</h3>
                            <div class="status-indicator ${isConnected && isTokenValid ? 'status-connected' : 'status-disconnected'}">
                                ${isConnected && isTokenValid ? '✅ Connected' : '❌ Disconnected'}
                            </div>
                            ${isConnected ? `
                                <div class="info-row">
                                    <span class="info-label">Company ID:</span>
                                    <span class="info-value">${realmId}</span>
                                </div>
                                <div class="info-row">
                                    <span class="info-label">Token Status:</span>
                                    <span class="info-value">${isTokenValid ? 'Valid' : 'Expired'}</span>
                                </div>
                                <div class="info-row">
                                    <span class="info-label">Expires:</span>
                                    <span class="info-value">${tokenExpiry ? tokenExpiry.toLocaleString() : 'N/A'}</span>
                                </div>
                                <div class="info-row">
                                    <span class="info-label">Time Left:</span>
                                    <span class="info-value">${tokenExpiresIn > 0 ? tokenExpiresIn + ' minutes' : 'Expired'}</span>
                                </div>
                            ` : `
                                <div class="info-row">
                                    <span class="info-label">Status:</span>
                                    <span class="info-value">Not Connected</span>
                                </div>
                                <div class="info-row">
                                    <span class="info-label">Action Required:</span>
                                    <span class="info-value">Connect to QuickBooks</span>
                                </div>
                            `}
                        </div>

                        <!-- Environment Info Card -->
                        <div class="card">
                            <h3>⚙️ Environment Info</h3>
                            <div class="info-row">
                                <span class="info-label">QB Environment:</span>
                                <span class="info-value">${config.QB_ENVIRONMENT}</span>
                            </div>
                            <div class="info-row">
                                <span class="info-label">Node Version:</span>
                                <span class="info-value" id="nodeVersion">Loading...</span>
                            </div>
                            <div class="info-row">
                                <span class="info-label">Server Time:</span>
                                <span class="info-value" id="serverTime">${new Date().toLocaleString()}</span>
                            </div>
                            <div class="info-row">
                                <span class="info-label">Last Refresh:</span>
                                <span class="info-value" id="lastRefresh">Just now</span>
                            </div>
                        </div>
                    </div>

                    <!-- Action Buttons -->
                    <div class="actions">
                        <button class="btn btn-secondary" onclick="refreshDashboard()">
                            🔄 Refresh
                            <span class="refresh-indicator" id="refreshSpinner">⟳</span>
                        </button>
                        
                        ${isConnected && isTokenValid ? `
                            <a href="/admin/customers" class="btn btn-primary">🔧 Customer Payment Management</a>
                            <a href="/admin/transactions" class="btn btn-primary">🔍 Transaction Search</a>
                            <button class="btn btn-warning" onclick="disconnectQuickBooks()">🔌 Disconnect QB</button>
                        ` : `
                            <a href="/auth/quickbooks" class="btn btn-success">🔗 Connect to QuickBooks</a>
                        `}
                        
                        <a href="/health" class="btn btn-secondary" target="_blank">🏥 Health Check</a>
                        <a href="/admin/logout" class="btn btn-danger">🚪 Logout</a>
                    </div>
                </div>

                <div class="footer">
                    <p>QuickBooks Payment Gateway v2.0 | Last updated: ${new Date().toLocaleDateString()}</p>
                </div>
            </div>

            <script>
                // Auto-refresh server time
                function updateServerTime() {
                    document.getElementById('serverTime').textContent = new Date().toLocaleString();
                }
                setInterval(updateServerTime, 1000);

                // Load additional system info
                async function loadSystemInfo() {
                    try {
                        const response = await fetch('/health');
                        const health = await response.json();
                        
                        // Update Node version
                        if (health.nodeVersion) {
                            document.getElementById('nodeVersion').textContent = health.nodeVersion;
                        }
                        
                        // Update uptime from server process uptime
                        if (health.uptime) {
                            const uptimeSeconds = Math.floor(health.uptime);
                            const hours = Math.floor(uptimeSeconds / 3600);
                            const minutes = Math.floor((uptimeSeconds % 3600) / 60);
                            document.getElementById('uptime').textContent = hours + 'h ' + minutes + 'm';
                        }
                        
                    } catch (error) {
                        console.error('Failed to load system info:', error);
                        document.getElementById('nodeVersion').textContent = 'Error loading';
                    }
                }

                // Refresh dashboard
                async function refreshDashboard() {
                    const spinner = document.getElementById('refreshSpinner');
                    spinner.classList.add('spinning');
                    
                    try {
                        await loadSystemInfo();
                        document.getElementById('lastRefresh').textContent = new Date().toLocaleString();
                        
                        // Refresh the page after a short delay to show updated connection status
                        setTimeout(() => {
                            window.location.reload();
                        }, 1000);
                        
                    } catch (error) {
                        console.error('Refresh failed:', error);
                    } finally {
                        setTimeout(() => {
                            spinner.classList.remove('spinning');
                        }, 1000);
                    }
                }

                // Disconnect QuickBooks
                async function disconnectQuickBooks() {
                    if (confirm('Are you sure you want to disconnect from QuickBooks? This will require reconnection for payments to work.')) {
                        try {
                            const response = await fetch('/admin/disconnect-qb', {
                                method: 'POST',
                                headers: {
                                    'Content-Type': 'application/json'
                                }
                            });
                            
                            if (response.ok) {
                                alert('Successfully disconnected from QuickBooks');
                                window.location.reload();
                            } else {
                                alert('Failed to disconnect from QuickBooks');
                            }
                        } catch (error) {
                            alert('Error disconnecting from QuickBooks');
                        }
                    }
                }

                // Load system info on page load
                loadSystemInfo();
            </script>
        </body>
        </html>
    `);
});

// Admin login route is now handled by adminLoginRouter

// Disconnect QuickBooks endpoint
app.post('/admin/disconnect-qb', authenticateBasicAuth, (req, res) => {
    try {
        // Clear tokens
        accessToken = null;
        refreshToken = null;
        tokenExpiresAt = null;
        realmId = null;
        
        // Delete tokens file
        const fs = require('fs');
        if (fs.existsSync(TOKENS_FILE)) {
            fs.unlinkSync(TOKENS_FILE);
        }
        
        auditLog('QB_DISCONNECT', { success: true }, req);
        
        res.json({
            success: true,
            message: 'Successfully disconnected from QuickBooks'
        });
    } catch (error) {
        auditLog('QB_DISCONNECT_ERROR', { error: error.message }, req);
        res.status(500).json({
            success: false,
            message: 'Error disconnecting from QuickBooks'
        });
    }
});

// Admin logout
app.get('/admin/logout', (req, res) => {
    res.send(`
        <h1>Logged Out</h1>
        <p><a href="/admin/login">Login Again</a></p>
    `);
});

// === TOKEN MANAGEMENT ===
const exchangeCodeForTokens = async (code) => {
    const tokenEndpoint = config.QB_ENVIRONMENT === 'production' 
        ? 'https://oauth.platform.intuit.com/oauth2/v1/tokens/bearer'
        : 'https://oauth.platform.intuit.com/oauth2/v1/tokens/bearer';
    
    const postData = new URLSearchParams({
        grant_type: 'authorization_code',
        code: code,
        redirect_uri: config.QB_REDIRECT_URI
    }).toString();
    
    const auth = Buffer.from(`${config.QB_CLIENT_ID}:${config.QB_CLIENT_SECRET}`).toString('base64');
    
    const options = {
        method: 'POST',
        headers: {
            'Authorization': `Basic ${auth}`,
            'Content-Type': 'application/x-www-form-urlencoded',
            'Accept': 'application/json'
        }
    };
    
    const { makeHttpsRequest } = require('./utils/network');
    const response = await makeHttpsRequest(tokenEndpoint, options, postData);
    
    if (response.status !== 200) {
        throw new Error(`Token exchange failed: ${JSON.stringify(response.data)}`);
    }
    
    return response.data;
};

// === SERVER STARTUP ===
const server = app.listen(config.PORT, () => {
    console.log(`🚀 QuickBooks Payment Gateway running on port ${config.PORT}`);
    console.log(`📊 Environment: ${config.NODE_ENV}`);
    console.log(`🔧 QuickBooks Environment: ${config.QB_ENVIRONMENT}`);
    console.log(`🔗 Admin Dashboard: http://localhost:${config.PORT}/admin/dashboard`);
    
    // Initialize tokens first (safe to call here since loadTokens is already defined)
    initTokens();
    
    // Start token monitoring system (every minute, refresh at 10 min threshold)
    startTokenMonitor();
    console.log(`⏰ Token monitoring system started - checking every 60s, refreshing at 10min threshold`);
    
    auditLog('SERVER_START', {
        port: config.PORT,
        environment: config.NODE_ENV,
        qbEnvironment: config.QB_ENVIRONMENT
    });
});

// Graceful shutdown
const gracefulShutdown = (signal) => {
    auditLog('SERVER_SHUTDOWN', { signal });
    console.log(`🛑 Received ${signal}, shutting down gracefully...`);
    
    // Stop token monitoring
    stopTokenMonitor();
    
    server.close(() => {
        console.log('✅ Server closed');
        process.exit(0);
    });
};

// Global error handlers
process.on('unhandledRejection', (reason, promise) => {
    console.error('Unhandled Rejection at:', promise, 'reason:', reason);
    auditLog('UNHANDLED_REJECTION', { reason: reason?.message || reason });
});

process.on('uncaughtException', (error) => {
    console.error('Uncaught Exception:', error);
    auditLog('UNCAUGHT_EXCEPTION', { error: error.message, stack: error.stack });
});

process.on('SIGTERM', () => gracefulShutdown('SIGTERM'));
process.on('SIGINT', () => gracefulShutdown('SIGINT'));

module.exports = app;
