const express = require('express');
const session = require('express-session');
const bcrypt = require('bcrypt');
const path = require('path');
const db = require('./src/database');
const { runScraperWeb } = require('./src/scraper_module');

const app = express();
const PORT = 3000;

// Middleware
app.set('view engine', 'ejs');
app.set('views', path.join(__dirname, 'views'));
app.use(express.static(path.join(__dirname, 'public')));
app.use(express.urlencoded({ extended: true }));
app.use(express.json());

// Session Configuration
app.use(session({
  secret: 'botscraping-secret-key-2026',
  resave: false,
  saveUninitialized: false,
  cookie: { maxAge: 24 * 60 * 60 * 1000 } // 1 day
}));

// Authentication Middleware
const requireAuth = (req, res, next) => {
  if (req.session.userId) return next();
  res.redirect('/login');
};

const requireAdmin = (req, res, next) => {
  if (req.session.userId && req.session.role === 'admin') return next();
  res.status(403).send('Forbidden: Admins only');
};

// ── ROUTES ───────────────────────────────────────────────────

// Root -> Redirect based on session
app.get('/', (req, res) => {
  if (!req.session.userId) return res.redirect('/login');
  if (req.session.role === 'admin') return res.redirect('/admin');
  return res.redirect('/dashboard');
});

// Login Page
app.get('/login', (req, res) => {
  if (req.session.userId) return res.redirect('/');
  res.render('login', { error: null, success: null });
});

// Login Action
app.post('/login', (req, res) => {
  const { username, password } = req.body;
  db.get("SELECT * FROM users WHERE username = ?", [username], async (err, user) => {
    if (err) return res.render('login', { error: 'Database error', success: null });
    if (!user) return res.render('login', { error: 'Invalid username or password', success: null });

    const match = await bcrypt.compare(password, user.password);
    if (match) {
      req.session.userId = user.id;
      req.session.username = user.username;
      req.session.role = user.role;
      res.redirect('/');
    } else {
      res.render('login', { error: 'Invalid username or password', success: null });
    }
  });
});

// Register Page
app.get('/register', (req, res) => {
  if (req.session.userId) return res.redirect('/');
  res.render('register', { error: null, success: null });
});

// Register Action
app.post('/register', async (req, res) => {
  const { username, password, confirm_password } = req.body;
  if (password !== confirm_password) {
    return res.render('register', { error: 'Passwords do not match', success: null });
  }

  const hashedPw = await bcrypt.hash(password, 10);
  db.run("INSERT INTO users (username, password) VALUES (?, ?)", [username, hashedPw], function(err) {
    if (err) {
      if (err.message.includes('UNIQUE')) {
        return res.render('register', { error: 'Username already exists', success: null });
      }
      return res.render('register', { error: 'Database error', success: null });
    }
    res.render('login', { error: null, success: 'Registration successful! Please login.' });
  });
});

// Logout
app.get('/logout', (req, res) => {
  req.session.destroy();
  res.redirect('/login');
});

// ── USER ROUTES ──────────────────────────────────────────────
app.get('/dashboard', requireAuth, (req, res) => {
  if (req.session.role === 'admin') return res.redirect('/admin');
  res.render('dashboard_user', { username: req.session.username });
});

app.post('/dashboard/change-password', requireAuth, async (req, res) => {
  const { current_password, new_password, confirm_new_password } = req.body;
  if (new_password !== confirm_new_password) {
    return res.status(400).json({ error: 'New passwords do not match' });
  }

  db.get("SELECT password FROM users WHERE id = ?", [req.session.userId], async (err, user) => {
    if (err || !user) return res.status(500).json({ error: 'Server error' });
    const match = await bcrypt.compare(current_password, user.password);
    if (!match) return res.status(400).json({ error: 'Incorrect current password' });

    const hashedPw = await bcrypt.hash(new_password, 10);
    db.run("UPDATE users SET password = ? WHERE id = ?", [hashedPw, req.session.userId], (err) => {
      if (err) return res.status(500).json({ error: 'Failed to update password' });
      res.json({ success: 'Password updated successfully' });
    });
  });
});

app.post('/api/scrape', requireAuth, async (req, res) => {
  const { token, keyword, limit, since, until } = req.body;
  if (!token || !keyword) return res.status(400).json({ error: 'Token and keyword required' });
  
  try {
    const result = await runScraperWeb(keyword, limit || 100, token, req.session.userId, since, until);
    if (!result) return res.status(404).json({ error: 'No tweets found for this keyword' });
    
    // Save to history
    db.run("INSERT INTO scraping_history (user_id, keyword, total_tweets) VALUES (?, ?, ?)", 
      [req.session.userId, keyword, result.stats.total]);
      
    res.json({
      stats: result.stats,
      downloadUrl: '/' + result.filename
    });
  } catch (error) {
    console.error(error);
    res.status(500).json({ error: 'Scraping failed: ' + error.message });
  }
});

// ── ADMIN ROUTES ─────────────────────────────────────────────
app.get('/admin', requireAdmin, (req, res) => {
  db.all("SELECT id, username, role, created_at FROM users", [], (err, users) => {
    if (err) return res.status(500).send("Database error");
    res.render('dashboard_admin', { username: req.session.username, users });
  });
});

app.post('/admin/create-user', requireAdmin, async (req, res) => {
  const { username, password, role } = req.body;
  const userRole = role === 'admin' ? 'admin' : 'user';
  const hashedPw = await bcrypt.hash(password, 10);

  db.run("INSERT INTO users (username, password, role) VALUES (?, ?, ?)", [username, hashedPw, userRole], (err) => {
    if (err) {
      if (err.message.includes('UNIQUE')) return res.status(400).json({ error: 'Username exists' });
      return res.status(500).json({ error: 'Database error' });
    }
    res.json({ success: 'User created' });
  });
});

app.post('/admin/reset-password', requireAdmin, async (req, res) => {
  const { user_id, new_password } = req.body;
  const hashedPw = await bcrypt.hash(new_password, 10);

  db.run("UPDATE users SET password = ? WHERE id = ?", [hashedPw, user_id], (err) => {
    if (err) return res.status(500).json({ error: 'Database error' });
    res.json({ success: 'Password reset' });
  });
});


app.listen(PORT, () => {
  console.log(`🚀 Server running on http://localhost:${PORT}`);
});
