const router = require('express').Router();
const bcrypt = require('bcryptjs');
const fs = require('fs');
const path = require('path');
const pool = require('../config/db');
const auth = require('../middleware/auth');
const { requireRole } = require('../middleware/auth');
const { uploadProfile } = require('../middleware/upload');
const { logActivity } = require('../models/helpers');
const { createNotification } = require('../models/notifications');

const userFields = 'id, username, full_name, birth_place, birth_date, email, phone, profile_photo, role, status, created_at';

router.use(auth);

// Update own profile (all roles) — must be before /:id routes
router.put('/profile/me', (req, res, next) => {
  uploadProfile(req, res, (err) => {
    if (err) return res.status(400).json({ error: err.message });
    next();
  });
}, async (req, res) => {
  try {
    const { full_name, birth_place, birth_date, email, phone } = req.body;

    const [existing] = await pool.query('SELECT * FROM users WHERE id = ?', [req.user.id]);
    if (existing.length === 0) return res.status(404).json({ error: 'User not found' });

    if (email) {
      const [dup] = await pool.query('SELECT id FROM users WHERE email = ? AND id != ?', [email, req.user.id]);
      if (dup.length > 0) return res.status(400).json({ error: 'Email already exists' });
    }

    let photo = existing[0].profile_photo;
    if (req.file) {
      if (photo) {
        const oldPath = path.join(__dirname, '..', photo);
        if (fs.existsSync(oldPath)) fs.unlinkSync(oldPath);
      }
      photo = `/uploads/profiles/${req.file.filename}`;
    }

    await pool.query(
      'UPDATE users SET full_name=?, birth_place=?, birth_date=?, email=?, phone=?, profile_photo=? WHERE id=?',
      [full_name || existing[0].full_name, birth_place || null, birth_date || null, email || null, phone || null, photo, req.user.id]
    );

    const [rows] = await pool.query(`SELECT ${userFields} FROM users WHERE id = ?`, [req.user.id]);
    res.json(rows[0]);
  } catch (err) {
    res.status(500).json({ error: err.message });
  }
});

// Get all users (master_admin only)
router.get('/', requireRole('master_admin'), async (req, res) => {
  try {
    const [rows] = await pool.query(`SELECT ${userFields} FROM users ORDER BY created_at DESC`);
    res.json(rows);
  } catch (err) {
    res.status(500).json({ error: err.message });
  }
});

// Get single user (master_admin only)
router.get('/:id', requireRole('master_admin'), async (req, res) => {
  try {
    const [rows] = await pool.query(`SELECT ${userFields} FROM users WHERE id = ?`, [req.params.id]);
    if (rows.length === 0) return res.status(404).json({ error: 'User not found' });
    res.json(rows[0]);
  } catch (err) {
    res.status(500).json({ error: err.message });
  }
});

// Create user (master_admin only)
router.post('/', requireRole('master_admin'), (req, res, next) => {
  uploadProfile(req, res, (err) => {
    if (err) return res.status(400).json({ error: err.message });
    next();
  });
}, async (req, res) => {
  try {
    const { username, full_name, birth_place, birth_date, email, phone, password, role } = req.body;

    if (!username || !password) return res.status(400).json({ error: 'Username and password required' });
    if (!full_name) return res.status(400).json({ error: 'Full name required' });
    if (password.length < 4) return res.status(400).json({ error: 'Password must be at least 4 characters' });

    const validRoles = ['master_admin', 'cashier', 'supplier'];
    if (!validRoles.includes(role)) return res.status(400).json({ error: 'Invalid role' });

    // Check unique username
    const [existing] = await pool.query('SELECT id FROM users WHERE username = ?', [username]);
    if (existing.length > 0) return res.status(400).json({ error: 'Username already exists' });

    // Check unique email if provided
    if (email) {
      const [dup] = await pool.query('SELECT id FROM users WHERE email = ?', [email]);
      if (dup.length > 0) return res.status(400).json({ error: 'Email already exists' });
    }

    const hash = await bcrypt.hash(password, 10);
    const photo = req.file ? `/uploads/profiles/${req.file.filename}` : null;

    await pool.query(
      'INSERT INTO users (username, full_name, birth_place, birth_date, email, phone, profile_photo, password_hash, role, status) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)',
      [username, full_name, birth_place || null, birth_date || null, email || null, phone || null, photo, hash, role, 'active']
    );

    const [rows] = await pool.query(`SELECT ${userFields} FROM users WHERE username = ?`, [username]);
    await logActivity(pool, 'create', 'user', String(rows[0].id), `${full_name} (${role})`);
    await createNotification(pool, { type: 'user', action: 'created', title: 'User Created', message: `${full_name} (${role}) was added`, detail: { user: rows[0] }, entity: 'user', entityId: String(rows[0].id), triggeredBy: req.user.id });
    res.status(201).json(rows[0]);
  } catch (err) {
    res.status(500).json({ error: err.message });
  }
});

// Update user (master_admin only)
router.put('/:id', requireRole('master_admin'), (req, res, next) => {
  uploadProfile(req, res, (err) => {
    if (err) return res.status(400).json({ error: err.message });
    next();
  });
}, async (req, res) => {
  try {
    const { full_name, birth_place, birth_date, email, phone, password, role, status } = req.body;

    const [existing] = await pool.query('SELECT * FROM users WHERE id = ?', [req.params.id]);
    if (existing.length === 0) return res.status(404).json({ error: 'User not found' });

    const validRoles = ['master_admin', 'cashier', 'supplier'];
    if (role && !validRoles.includes(role)) return res.status(400).json({ error: 'Invalid role' });

    // Check unique email if changed
    if (email) {
      const [dup] = await pool.query('SELECT id FROM users WHERE email = ? AND id != ?', [email, req.params.id]);
      if (dup.length > 0) return res.status(400).json({ error: 'Email already exists' });
    }

    // Prevent removing last master_admin
    if (role && role !== 'master_admin' && existing[0].role === 'master_admin') {
      const [admins] = await pool.query("SELECT COUNT(*) as cnt FROM users WHERE role = 'master_admin' AND status = 'active'");
      if (admins[0].cnt <= 1) return res.status(400).json({ error: 'Cannot remove the last master admin' });
    }

    let photo = existing[0].profile_photo;
    if (req.file) {
      // Delete old photo file
      if (photo) {
        const oldPath = path.join(__dirname, '..', photo);
        if (fs.existsSync(oldPath)) fs.unlinkSync(oldPath);
      }
      photo = `/uploads/profiles/${req.file.filename}`;
    }

    let hash = existing[0].password_hash;
    if (password && password.length >= 4) {
      hash = await bcrypt.hash(password, 10);
    }

    await pool.query(
      'UPDATE users SET full_name=?, birth_place=?, birth_date=?, email=?, phone=?, profile_photo=?, password_hash=?, role=?, status=? WHERE id=?',
      [full_name || existing[0].full_name, birth_place || null, birth_date || null, email || null, phone || null, photo, hash, role || existing[0].role, status || existing[0].status, req.params.id]
    );

    await logActivity(pool, 'edit', 'user', req.params.id, full_name || existing[0].full_name);
    const [rows] = await pool.query(`SELECT ${userFields} FROM users WHERE id = ?`, [req.params.id]);
    await createNotification(pool, { type: 'user', action: 'edited', title: 'User Updated', message: `${rows[0].full_name || rows[0].username} was updated`, detail: { user: rows[0] }, entity: 'user', entityId: req.params.id, triggeredBy: req.user.id });
    res.json(rows[0]);
  } catch (err) {
    res.status(500).json({ error: err.message });
  }
});

// Delete user (master_admin only)
router.delete('/:id', requireRole('master_admin'), async (req, res) => {
  try {
    if (parseInt(req.params.id) === req.user.id) {
      return res.status(400).json({ error: 'Cannot delete your own account' });
    }

    const [existing] = await pool.query('SELECT * FROM users WHERE id = ?', [req.params.id]);
    if (existing.length === 0) return res.status(404).json({ error: 'User not found' });

    // Prevent deleting last master_admin
    if (existing[0].role === 'master_admin') {
      const [admins] = await pool.query("SELECT COUNT(*) as cnt FROM users WHERE role = 'master_admin' AND status = 'active'");
      if (admins[0].cnt <= 1) return res.status(400).json({ error: 'Cannot delete the last master admin' });
    }

    // Delete photo file
    if (existing[0].profile_photo) {
      const photoPath = path.join(__dirname, '..', existing[0].profile_photo);
      if (fs.existsSync(photoPath)) fs.unlinkSync(photoPath);
    }

    await pool.query('DELETE FROM users WHERE id = ?', [req.params.id]);
    await logActivity(pool, 'delete', 'user', req.params.id, existing[0].full_name || existing[0].username);
    await createNotification(pool, { type: 'user', action: 'deleted', title: 'User Deleted', message: `${existing[0].full_name || existing[0].username} was removed`, detail: { username: existing[0].username, role: existing[0].role }, entity: 'user', entityId: req.params.id, triggeredBy: req.user.id });
    res.json({ message: 'User deleted' });
  } catch (err) {
    res.status(500).json({ error: err.message });
  }
});

module.exports = router;
