const express = require('express');
const cors = require('cors');
const bodyParser = require('body-parser');
const fs = require('fs-extra');
const path = require('path');
const helmet = require('helmet');
const compression = require('compression');
const bcrypt = require('bcryptjs');
const jwt = require('jsonwebtoken');
const { v4: uuidv4 } = require('uuid');

const app = express();
const PORT = process.env.PORT || 3000;
const JWT_SECRET = process.env.JWT_SECRET || 'neuroconnect-therapy-secret-key-2024';

// Security middleware
app.use(helmet({
    contentSecurityPolicy: {
        directives: {
            defaultSrc: ["'self'"],
            styleSrc: ["'self'", "'unsafe-inline'", "https://cdnjs.cloudflare.com"],
            scriptSrc: ["'self'", "'unsafe-inline'"],
            imgSrc: ["'self'", "data:", "https:"],
            fontSrc: ["'self'", "https://cdnjs.cloudflare.com"],
            connectSrc: ["'self'"]
        }
    }
}));

// Middleware
app.use(compression());
app.use(cors());
app.use(bodyParser.json({ limit: '10mb' }));
app.use(bodyParser.urlencoded({ extended: true, limit: '10mb' }));

// Serve static files
app.use(express.static(path.join(__dirname)));

// Data storage paths
const DATA_DIR = path.join(__dirname, 'data');
const USERS_FILE = path.join(DATA_DIR, 'users.json');
const STAFF_FILE = path.join(DATA_DIR, 'staff.json');
const PATIENTS_FILE = path.join(DATA_DIR, 'patients.json');
const SCHEDULES_FILE = path.join(DATA_DIR, 'schedules.json');
const EXPENSES_FILE = path.join(DATA_DIR, 'expenses.json');
const STOCK_FILE = path.join(DATA_DIR, 'stock.json');

// Ensure data directory exists
fs.ensureDirSync(DATA_DIR);

// Initialize data files with default data
async function initializeDataFiles() {
    // Initialize users with hashed passwords
    if (!await fs.pathExists(USERS_FILE)) {
        const defaultUsers = {
            admin: {
                password: await bcrypt.hash('admin123', 10),
                role: 'admin',
                name: 'Administrator',
                email: 'admin@neuroconnect.com',
                permissions: {
                    dashboard: true,
                    staff: true,
                    payroll: true,
                    expenses: true,
                    patients: true,
                    schedule: true,
                    stock: true,
                    reports: true
                }
            },
            user: {
                password: await bcrypt.hash('user123', 10),
                role: 'user',
                name: 'Staff User',
                email: 'user@neuroconnect.com',
                permissions: {
                    dashboard: true,
                    staff: false,
                    payroll: false,
                    expenses: true,
                    patients: true,
                    schedule: true,
                    stock: true,
                    reports: true
                }
            }
        };
        await fs.writeJson(USERS_FILE, defaultUsers, { spaces: 2 });
    }

    // Initialize other data files
    const dataFiles = [
        { file: STAFF_FILE, data: [] },
        { file: PATIENTS_FILE, data: [] },
        { file: SCHEDULES_FILE, data: [] },
        { file: EXPENSES_FILE, data: [] },
        { file: STOCK_FILE, data: [] }
    ];

    for (const { file, data } of dataFiles) {
        if (!await fs.pathExists(file)) {
            await fs.writeJson(file, data, { spaces: 2 });
        }
    }
}

// Authentication middleware
function authenticateToken(req, res, next) {
    const authHeader = req.headers['authorization'];
    const token = authHeader && authHeader.split(' ')[1];

    if (!token) {
        return res.status(401).json({ error: 'Access token required' });
    }

    jwt.verify(token, JWT_SECRET, (err, user) => {
        if (err) {
            return res.status(403).json({ error: 'Invalid or expired token' });
        }
        req.user = user;
        next();
    });
}

// API Routes

// Login endpoint
app.post('/api/login', async (req, res) => {
    try {
        const { username, password } = req.body;
        
        if (!username || !password) {
            return res.status(400).json({ error: 'Username and password required' });
        }

        const users = await fs.readJson(USERS_FILE);
        const user = users[username];

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

        const token = jwt.sign(
            { 
                username: username,
                role: user.role,
                name: user.name,
                permissions: user.permissions
            },
            JWT_SECRET,
            { expiresIn: '24h' }
        );

        res.json({
            token,
            user: {
                username: username,
                role: user.role,
                name: user.name,
                permissions: user.permissions
            }
        });
    } catch (error) {
        console.error('Login error:', error);
        res.status(500).json({ error: 'Internal server error' });
    }
});

// Generic data endpoints
const dataEndpoints = [
    { route: '/api/staff', file: STAFF_FILE },
    { route: '/api/patients', file: PATIENTS_FILE },
    { route: '/api/schedules', file: SCHEDULES_FILE },
    { route: '/api/expenses', file: EXPENSES_FILE },
    { route: '/api/stock', file: STOCK_FILE }
];

dataEndpoints.forEach(({ route, file }) => {
    // GET data
    app.get(route, authenticateToken, async (req, res) => {
        try {
            const data = await fs.readJson(file);
            res.json(data);
        } catch (error) {
            console.error(`Error reading ${file}:`, error);
            res.status(500).json({ error: 'Failed to read data' });
        }
    });

    // POST data (save entire array)
    app.post(route, authenticateToken, async (req, res) => {
        try {
            const data = req.body;
            await fs.writeJson(file, data, { spaces: 2 });
            res.json({ success: true, message: 'Data saved successfully' });
        } catch (error) {
            console.error(`Error writing ${file}:`, error);
            res.status(500).json({ error: 'Failed to save data' });
        }
    });
});

// Serve the main application
app.get('/', (req, res) => {
    res.sendFile(path.join(__dirname, 'login.html'));
});

app.get('/app', (req, res) => {
    res.sendFile(path.join(__dirname, 'index.html'));
});

// Handle 404s
app.get('*', (req, res) => {
    res.status(404).sendFile(path.join(__dirname, 'login.html'));
});

// Error handling middleware
app.use((error, req, res, next) => {
    console.error('Server error:', error);
    res.status(500).json({ error: 'Internal server error' });
});

// Start server
async function startServer() {
    try {
        await initializeDataFiles();
        app.listen(PORT, () => {
            console.log('🚀 NeuroConnect Therapy Management System');
            console.log(`🌐 Server running on http://localhost:${PORT}`);
            console.log(`📱 Access from anywhere at your deployed URL`);
            console.log(`🔐 Default credentials: admin/admin123 or user/user123`);
            console.log('📊 Data files initialized in ./data directory');
        });
    } catch (error) {
        console.error('Failed to start server:', error);
        process.exit(1);
    }
}

startServer();

module.exports = app;