const path = require('path');
require('dotenv').config({ path: path.join(__dirname, '.env') });
const express = require('express');
const cors = require('cors');
const jwt = require('jsonwebtoken');
const bcrypt = require('bcryptjs');
const axios = require('axios');
const db = require('./db');
const body_parser = require('body-parser');

const app = express();
const PORT = process.env.PORT || 3001;
const JWT_SECRET = process.env.JWT_SECRET || 'super-secret-key-change-it';

app.use(cors());
app.use(express.json({ limit: '50mb' }));
app.use(body_parser.urlencoded({ limit: '50mb', extended: true }));

// Auth Middleware
const authenticateAdmin = (req, res, next) => {
    const authHeader = req.headers.authorization;
    if (!authHeader) return res.status(401).json({ error: 'No token provided' });

    const token = authHeader.split(' ')[1];
    try {
        const decoded = jwt.verify(token, JWT_SECRET);
        req.adminId = decoded.id;
        next();
    } catch (err) {
        res.status(401).json({ error: 'Invalid token' });
    }
};

// --- AUTH ENDPOINTS ---

app.post('/api/admin/login', (req, res) => {
    const { username, password } = req.body;
    const user = db.prepare('SELECT * FROM admin_users WHERE username = ?').get(username);

    if (!user || !bcrypt.compareSync(password, user.password_hash)) {
        return res.status(401).json({ error: 'Invalid credentials' });
    }

    const token = jwt.sign({ id: user.id, username: user.username }, JWT_SECRET, { expiresIn: '8h' });
    res.json({ token, username: user.username });
});

app.post('/api/admin/add', authenticateAdmin, (req, res) => {
    const { username, password } = req.body;
    try {
        const hash = bcrypt.hashSync(password, 10);
        db.prepare('INSERT INTO admin_users (username, password_hash) VALUES (?, ?)').run(username, hash);
        res.json({ success: true, message: 'Admin user added successfully' });
    } catch (err) {
        res.status(400).json({ error: 'Username already exists or invalid data' });
    }
});

app.get('/api/admin/users', authenticateAdmin, (req, res) => {
    try {
        const users = db.prepare('SELECT id, username, created_at FROM admin_users ORDER BY created_at DESC').all();
        res.json(users);
    } catch (err) {
        res.status(500).json({ error: 'Failed to fetch users' });
    }
});

app.put('/api/admin/users/:id/password', authenticateAdmin, (req, res) => {
    const { id } = req.params;
    const { password } = req.body;

    if (!password || password.length < 6) {
        return res.status(400).json({ error: 'Password must be at least 6 characters' });
    }

    try {
        const hash = bcrypt.hashSync(password, 10);
        const result = db.prepare('UPDATE admin_users SET password_hash = ? WHERE id = ?').run(hash, id);

        if (result.changes === 0) return res.status(404).json({ error: 'User not found' });
        res.json({ success: true, message: 'Password updated successfully' });
    } catch (err) {
        res.status(500).json({ error: 'Failed to update password' });
    }
});

app.delete('/api/admin/users/:id', authenticateAdmin, (req, res) => {
    const { id } = req.params;

    // Prevent deleting the last admin
    const adminCount = db.prepare('SELECT COUNT(*) as count FROM admin_users').get().count;
    if (adminCount <= 1) {
        return res.status(400).json({ error: 'Cannot delete the only administrator' });
    }

    try {
        const result = db.prepare('DELETE FROM admin_users WHERE id = ?').run(id);
        if (result.changes === 0) return res.status(404).json({ error: 'User not found' });
        res.json({ success: true, message: 'User deleted successfully' });
    } catch (err) {
        res.status(500).json({ error: 'Failed to delete user' });
    }
});
// --- SETTINGS ENDPOINTS ---

app.get('/api/admin/settings/:key', authenticateAdmin, (req, res) => {
    const { key } = req.params;
    const setting = db.prepare('SELECT value FROM settings WHERE key = ?').get(key);
    if (!setting) return res.status(404).json({ error: 'Setting not found' });
    res.json(JSON.parse(setting.value));
});

// Public endpoint for specific config (legacy fallback)
app.get('/api/config/:key', (req, res) => {
    const { key } = req.params;
    const setting = db.prepare('SELECT value FROM settings WHERE key = ?').get(key);
    if (!setting) return res.status(404).json({ error: 'Config not found' });

    let data = JSON.parse(setting.value);

    // SECURITY: Filter out sensitive credentials
    if (key === 'whmcs_api') {
        const { identifier, secret, ...safeConfig } = data;
        data = safeConfig;
    } else if (key === 'virtualizor_servers') {
        // Filter out keys and passwords from server list
        const safeServers = {};
        Object.keys(data).forEach(k => {
            const { key, pass, ...safeServer } = data[k];
            safeServers[k] = safeServer;
        });
        data = safeServers;
    } else if (key === 'uddoktapay_config') {
        const { api_key, ...safeConfig } = data;
        data = { ...safeConfig, enabled: !!api_key };
    }

    res.json(data);
});

app.post('/api/admin/settings/:key', authenticateAdmin, (req, res) => {
    const { key } = req.params;
    const { value } = req.body;

    db.prepare('INSERT OR REPLACE INTO settings (key, value, updated_at) VALUES (?, ?, CURRENT_TIMESTAMP)')
        .run(key, JSON.stringify(value));

    res.json({ success: true });
});

// --- WHMCS UTILS ---
const getWHMCSEndpoint = (config) => {
    if (!config.url) return null;
    return config.url.endsWith('api.php')
        ? config.url
        : `${config.url.replace(/\/$/, '')}/includes/api.php`;
};

const getUddoktaPayBaseUrl = (url) => {
    if (!url) return '';
    let cleaned = url.trim();
    if (cleaned.endsWith('/')) cleaned = cleaned.slice(0, -1);
    // Strip /api/checkout-v2 or /api/verify-payment if user pasted full URL
    return cleaned.replace(/\/api\/.*$/, '');
};

// --- WHMCS PROXY ENDPOINT ---

app.post('/api/proxy/whmcs', async (req, res) => {
    const { action, params } = req.body;

    // Fetch config from DB
    const configRow = db.prepare('SELECT value FROM settings WHERE key = ?').get('whmcs_api');
    if (!configRow) {
        return res.status(400).json({ result: 'error', message: 'WHMCS API not configured in Admin Panel' });
    }

    const config = JSON.parse(configRow.value);
    if (!config.url) {
        return res.status(400).json({ result: 'error', message: 'WHMCS API URL is empty' });
    }

    // Clean URL
    const endpoint = config.url.endsWith('api.php')
        ? config.url
        : `${config.url.replace(/\/$/, '')}/includes/api.php`;

    // WHMCS expects form-urlencoded for the API
    const formData = new URLSearchParams();
    formData.append('identifier', config.identifier);
    formData.append('secret', config.secret);
    formData.append('action', action);
    formData.append('responsetype', 'json');

    if (params) {
        Object.entries(params).forEach(([key, value]) => {
            if (Array.isArray(value)) {
                value.forEach((v, i) => formData.append(`${key}[${i}]`, v));
            } else if (value !== undefined) {
                formData.append(key, value);
            }
        });
    }

    try {
        const response = await axios.post(endpoint, formData.toString(), {
            headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
        });
        res.json(response.data);
    } catch (err) {
        if (err.response) {
            console.warn('[PROXY-WHMCS-API-ERROR]', err.response.status, err.response.data);
            return res.status(err.response.status).json({
                result: 'error',
                message: `WHMCS API Error (${err.response.status}): ` + (err.response.data?.message || err.message),
                details: err.response.data
            });
        }
        console.error('[PROXY-ERROR]', err.message);
        res.status(500).json({ result: 'error', message: 'Backend Proxy Error: ' + err.message });
    }
});

// --- VIRTUALIZOR PROXY ENDPOINT ---

const generateRandStr = (length) => {
    let result = '';
    const characters = 'abcdefghijklmnopqrstuvwxyz0123456789';
    for (let i = 0; i < length; i++) {
        result += characters.charAt(Math.floor(Math.random() * characters.length));
    }
    return result;
};

const crypto = require('crypto');
const md5 = (str) => crypto.createHash('md5').update(str).digest('hex');

app.post('/api/proxy/virtualizor', async (req, res) => {
    const { serverId, action, params, useAdmin = false, method = 'GET' } = req.body;

    // Fetch Virtualizor servers from DB
    const serversRow = db.prepare('SELECT value FROM settings WHERE key = ?').get('virtualizor_servers');
    if (!serversRow) {
        return res.status(400).json({ error: 'Virtualizor servers not configured' });
    }

    const servers = JSON.parse(serversRow.value);
    const creds = servers[serverId];

    if (!creds) {
        return res.status(400).json({ error: `Credentials for Server ID ${serverId} not found` });
    }

    // 1. Signature Step
    const salt = generateRandStr(8);
    const signature = md5(creds.pass + salt);
    const apikey = salt + signature;

    // 2. Port Mapping
    // Admin: 4084 (HTTPS: 4085)
    // Client: 4082 (HTTPS: 4083)
    const port = useAdmin ? 4084 : 4082;
    const protocol = 'http'; // Default to HTTP for now, could be dynamic
    const endpoint = `${protocol}://${creds.ip}:${port}/index.php`;

    // 3. Assemble parameters
    const allParams = {
        act: action,
        api: 'json',
        adminapikey: creds.key,
        adminapipass: creds.pass,
        apikey: apikey,
        ...params
    };

    try {
        let response;
        if (method === 'POST') {
            const formData = new URLSearchParams();
            // Core routing params must usually be in URL for Virtualizor, 
            // but we'll try standard POST body first or mix as needed.
            // Following virtualizorService.ts logic:
            const urlParams = new URLSearchParams({
                act: action,
                api: 'json',
                apikey: apikey
            });
            if (params.svs) urlParams.append('svs', params.svs);
            if (params.do) urlParams.append('do', params.do);

            Object.entries(allParams).forEach(([k, v]) => {
                formData.append(k, v);
            });

            response = await axios.post(`${endpoint}?${urlParams.toString()}`, formData.toString(), {
                headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
            });
        } else {
            response = await axios.get(endpoint, { params: allParams });
        }

        res.json(response.data);
    } catch (err) {
        console.error('[VIRTUALIZOR-PROXY-ERROR]', err.message);
        res.status(err.response?.status || 500).json({
            error: err.message,
            details: err.response?.data
        });
    }
});

// --- UDDOKTAPAY PAYMENT ENDPOINTS ---

app.post('/api/payment/uddoktapay/checkout', async (req, res) => {
    const { invoiceId, amount, customerName, customerEmail } = req.body;

    const configRow = db.prepare('SELECT value FROM settings WHERE key = ?').get('uddoktapay_config');
    if (!configRow) return res.status(500).json({ error: 'UddoktaPay not configured' });
    const config = JSON.parse(configRow.value);

    // Clean URL: ensure it handles trailing slashes in config
    let baseUrl = config.api_url.trim();
    if (baseUrl.endsWith('/')) baseUrl = baseUrl.slice(0, -1);
    const apiUrl = baseUrl.endsWith('/api/checkout-v2') ? baseUrl : `${baseUrl}/api/checkout-v2`;

    const protocol = req.headers['x-forwarded-proto'] || 'http';
    const host = req.headers['x-forwarded-host'] || req.headers.host;
    const baseServerUrl = `${protocol}://${host}`;

    // IMPORTANT: UddoktaPay needs the frontend port during redirection in dev
    // If host is localhost:3001, we want to redirect back to localhost:3000
    const redirectBaseUrl = host.includes('localhost:3001') ? baseServerUrl.replace(':3001', ':3000') : baseServerUrl;

    const checkoutData = {
        full_name: customerName,
        email: customerEmail,
        amount: amount,
        order_id: `${invoiceId}-${Math.floor(Math.random() * 100000).toString().padStart(5, '0')}`,
        metadata: {
            invoice_id: invoiceId
        },
        redirect_url: `${redirectBaseUrl}/api/payment/uddoktapay/verify/${invoiceId}?redirect=1`,
        cancel_url: `${redirectBaseUrl}/billing?invoice=${invoiceId}&status=cancel`,
        webhook_url: `${baseServerUrl}/api/payment/uddoktapay/webhook`
    };

    console.log('[UDDOKTAPAY-CHECKOUT] Initiating with:', JSON.stringify(checkoutData, null, 2));

    try {
        const response = await axios.post(apiUrl, checkoutData, {
            headers: {
                'RT-UDDOKTAPAY-API-KEY': config.api_key,
                'Content-Type': 'application/json'
            }
        });

        console.log('[UDDOKTAPAY-CHECKOUT-SUCCESS]', response.data);
        res.json(response.data);
    } catch (err) {
        console.error('[UDDOKTAPAY-CHECKOUT-ERROR]', err.message);
        if (err.response) {
            console.error('[UDDOKTAPAY-API-DETAIL]', JSON.stringify(err.response.data, null, 2));
        }
        res.status(500).json({ error: 'Failed to initiate checkout', details: err.response?.data || err.message });
    }
});

app.post('/api/payment/uddoktapay/webhook', async (req, res) => {
    const { status, metadata, amount } = req.body;
    const invoiceId = metadata?.invoice_id;

    console.log(`[UDDOKTAPAY-WEBHOOK] Received status ${status} for invoice ${invoiceId}`);

    if (status === 'COMPLETED' && invoiceId) {
        try {
            const whmcsRow = db.prepare('SELECT value FROM settings WHERE key = ?').get('whmcs_api');
            if (whmcsRow) {
                const whmcs = JSON.parse(whmcsRow.value);
                const endpoint = getWHMCSEndpoint(whmcs);
                if (endpoint) {
                    const params = new URLSearchParams({
                        identifier: whmcs.identifier,
                        secret: whmcs.secret,
                        action: 'AddInvoicePayment',
                        invoiceid: invoiceId,
                        transid: req.body.order_id || 'UDD-' + Date.now(),
                        gateway: 'uddoktapay',
                        amount: amount,
                        responsetype: 'json'
                    });
                    const whmcsRes = await axios.post(endpoint, params.toString());
                    console.log(`[UDDOKTAPAY-WEBHOOK] WHMCS Response:`, JSON.stringify(whmcsRes.data));
                    if (whmcsRes.data.result === 'success') {
                        console.log(`[UDDOKTAPAY-WEBHOOK] WHMCS Invoice ${invoiceId} updated successfully`);
                    } else {
                        console.warn(`[UDDOKTAPAY-WEBHOOK] WHMCS API error:`, whmcsRes.data.message);
                    }
                }
            }
        } catch (err) {
            console.error('[UDDOKTAPAY-WEBHOOK-WHMCS-ERROR]', err.message);
            if (err.response) console.error('[UDDOKTAPAY-WEBHOOK-WHMCS-DETAIL]', err.response.data);
        }
    }

    res.sendStatus(200);
});

app.all('/api/payment/uddoktapay/verify/:invoiceId', async (req, res) => {
    const { invoiceId } = req.params;
    console.log(`\n--- [UDDOKTAPAY-VERIFY-START] ---`);
    console.log(`[VERIFY] Invoice: ${invoiceId} | Method: ${req.method} | Host: ${req.headers.host}`);

    const configRow = db.prepare('SELECT value FROM settings WHERE key = ?').get('uddoktapay_config');
    if (!configRow) return res.status(500).json({ error: 'UddoktaPay not configured' });
    const config = JSON.parse(configRow.value);

    // Clean URL
    const baseUrl = getUddoktaPayBaseUrl(config.api_url);
    const apiUrl = `${baseUrl}/api/verify-payment`;
    console.log(`[VERIFY] API URL: ${apiUrl}`);

    try {
        const uddoktaInvoiceId = req.body.invoice_id || req.query.invoice_id || invoiceId;
        console.log(`[VERIFY] Verifying with UddoktaPay ID: ${uddoktaInvoiceId}`);

        const response = await axios.post(apiUrl, {
            invoice_id: uddoktaInvoiceId
        }, {
            headers: {
                'RT-UDDOKTAPAY-API-KEY': config.api_key,
                'Content-Type': 'application/json'
            }
        });

        console.log(`[VERIFY] UP Response:`, JSON.stringify(response.data));

        // Update WHMCS if payment completed (idempotent)
        if (response.data.status === 'COMPLETED' || response.data.status === 'SUCCESS') {
            console.log(`[VERIFY] Payment SUCCESS - Marking as PAID in WHMCS...`);
            try {
                const whmcsRow = db.prepare('SELECT value FROM settings WHERE key = ?').get('whmcs_api');
                if (whmcsRow) {
                    const whmcs = JSON.parse(whmcsRow.value);
                    const endpoint = getWHMCSEndpoint(whmcs);
                    console.log(`[VERIFY] WHMCS Endpoint: ${endpoint}`);
                    if (endpoint) {
                        const amount = response.data.amount || response.data.amount_original || 0;
                        const transid = response.data.transaction_id || `UDD-${Date.now()}`;

                        // DIRECT API CALL TO WHMCS - NO MODULE
                        const params = new URLSearchParams({
                            identifier: whmcs.identifier,
                            secret: whmcs.secret,
                            action: 'AddInvoicePayment',
                            invoiceid: invoiceId,
                            transid: transid,
                            gateway: 'uddoktapay', // Just a label for the record
                            amount: amount,
                            responsetype: 'json'
                        });

                        const whmcsRes = await axios.post(endpoint, params.toString());
                        console.log(`[VERIFY] WHMCS Response:`, JSON.stringify(whmcsRes.data));

                        if (whmcsRes.data.result === 'success') {
                            console.log(`[VERIFY] SUCCESS: Invoice ${invoiceId} marked as PAID`);
                        } else {
                            console.warn(`[VERIFY] WHMCS Error: ${whmcsRes.data.message}`);
                        }
                    }
                }
            } catch (whmcsErr) {
                console.error('[VERIFY] WHMCS Update Error:', whmcsErr.message);
                if (whmcsErr.response) console.error('[VERIFY] WHMCS Detail:', whmcsErr.response.data);
            }
        }

        if (req.query.redirect === '1') {
            const status = (response.data.status === 'COMPLETED' || response.data.status === 'SUCCESS') ? 'success' : 'pending';
            const protocol = req.headers['x-forwarded-proto'] || 'http';
            const host = req.headers['x-forwarded-host'] || req.headers.host;
            // Ensure redirect back to frontend port in dev
            const redirectHost = host.includes('localhost:3001') ? host.replace('3001', '3000') : host;
            const finalUrl = `${protocol}://${redirectHost}/billing?invoice=${invoiceId}&status=${status}`;
            console.log(`[VERIFY] Redirecting to: ${finalUrl}`);
            return res.redirect(finalUrl);
        }

        res.json(response.data);
    } catch (err) {
        console.error(`[VERIFY] Global Error:`, err.message);
        if (err.response) console.error(`[VERIFY] Detail:`, typeof err.response.data === 'string' ? 'HTML Error' : JSON.stringify(err.response.data));

        if (req.query.redirect === '1') {
            const protocol = req.headers['x-forwarded-proto'] || 'http';
            const host = req.headers['x-forwarded-host'] || req.headers.host;
            const redirectHost = host.includes('localhost:3001') ? host.replace('3001', '3000') : host;
            return res.redirect(`${protocol}://${redirectHost}/billing?invoice=${invoiceId}&status=error`);
        }
        res.status(500).json({ error: 'Failed to verify payment', details: err.response?.data || err.message });
    }
    console.log(`--- [UDDOKTAPAY-VERIFY-END] ---\n`);
});

// --- STATIC ASSETS (Frontend) ---
// Serve the built dist folder if it exists
app.use(express.static(path.join(__dirname, '../dist')));

// Catch-all route to serve the SPA (index.html) for any non-API routes
app.get(/^((?!\/api).)*$/, (req, res) => {
    // Only redirect if not an API call
    if (!req.path.startsWith('/api/')) {
        res.sendFile(path.join(__dirname, '../dist/index.html'));
    }
});

app.listen(PORT, () => {
    console.log(`Backend Admin Server running on http://localhost:${PORT}`);
    console.log(`Frontend Secure Access available through this port (once built)`);
});
