/**
 * Attendance Controller
 * Student and staff attendance tracking
 */

const express = require('express');
const router = express.Router();
const { v4: uuidv4 } = require('uuid');

// Database path
const dbPath = process.env.DB_PATH || require('path').join(__dirname, '../../data/school.db');
const Database = require('better-sqlite3');
let db;

const getDb = () => {
  if (!db) {
    db = new Database(dbPath);
    db.pragma('foreign_keys = ON');
  }
  return db;
};

// Auth middleware
const auth = (req, res, next) => {
  const token = req.headers.authorization?.split(' ')[1];
  if (!token) return res.status(401).json({ error: 'No token provided' });
  try {
    const jwt = require('jsonwebtoken');
    const JWT_SECRET = process.env.JWT_SECRET || 'africa-alert-secret-key-2024';
    req.user = jwt.verify(token, JWT_SECRET);
    next();
  } catch (err) {
    res.status(401).json({ error: 'Invalid token' });
  }
};

// Admin or teacher only
const adminOrTeacher = (req, res, next) => {
  if (req.user.role !== 'admin' && req.user.role !== 'teacher') {
    return res.status(403).json({ error: 'Admin or Teacher access required' });
  }
  next();
};

// Admin-only middleware
const adminOnly = (req, res, next) => {
  if (req.user.role !== 'admin') {
    return res.status(403).json({ error: 'Admin access required' });
  }
  next();
};

// ============ ATTENDANCE CRUD ============

// List attendance records
router.get('/', auth, (req, res) => {
  try {
    const { date, class_id, student_id, status, start_date, end_date } = req.query;
    
    let query = `
      SELECT a.*, 
        u.first_name || ' ' || u.last_name as student_name,
        c.name as class_name,
        s.name as subject_name
      FROM attendance a
      JOIN users u ON a.student_id = u.id
      LEFT JOIN classes c ON a.class_id = c.id
      LEFT JOIN subjects s ON a.subject_id = s.id
      WHERE a.is_deleted = 0
    `;
    const params = [];
    
    // Filter by user role
    if (req.user.role === 'student') {
      query += ' AND a.student_id = ?';
      params.push(req.user.id);
    } else if (req.user.role === 'teacher') {
      // Teachers see attendance for their classes
      query += ' AND (a.class_id IN (SELECT id FROM classes WHERE class_teacher_id = ?) OR a.subject_id IN (SELECT id FROM subjects WHERE teacher_id = ?))';
      params.push(req.user.id, req.user.id);
    }
    
    if (date) {
      query += ' AND a.date = ?';
      params.push(date);
    }
    if (start_date) {
      query += ' AND a.date >= ?';
      params.push(start_date);
    }
    if (end_date) {
      query += ' AND a.date <= ?';
      params.push(end_date);
    }
    if (class_id) {
      query += ' AND a.class_id = ?';
      params.push(class_id);
    }
    if (student_id && req.user.role !== 'student') {
      query += ' AND a.student_id = ?';
      params.push(student_id);
    }
    if (status) {
      query += ' AND a.status = ?';
      params.push(status);
    }
    
    query += ' ORDER BY a.date DESC, u.last_name';
    
    const records = getDb().prepare(query).all(...params);
    res.json(records);
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

// Get single attendance record
router.get('/:id', auth, (req, res) => {
  try {
    const record = getDb().prepare(`
      SELECT a.*, 
        u.first_name || ' ' || u.last_name as student_name,
        c.name as class_name,
        s.name as subject_name
      FROM attendance a
      JOIN users u ON a.student_id = u.id
      LEFT JOIN classes c ON a.class_id = c.id
      LEFT JOIN subjects s ON a.subject_id = s.id
      WHERE a.id = ? AND a.is_deleted = 0
    `).get(req.params.id);
    
    if (!record) {
      return res.status(404).json({ error: 'Attendance record not found' });
    }
    
    res.json(record);
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

// Mark attendance
router.post('/', auth, adminOrTeacher, (req, res) => {
  try {
    const { student_id, class_id, subject_id, date, status, remarks } = req.body;
    
    if (!student_id || !date || !status) {
      return res.status(400).json({ error: 'student_id, date, and status are required' });
    }
    
    // Validate status
    const validStatuses = ['present', 'absent', 'late', 'excused'];
    if (!validStatuses.includes(status)) {
      return res.status(400).json({ error: `Status must be one of: ${validStatuses.join(', ')}` });
    }
    
    // Check if already exists (upsert)
    const existing = getDb().prepare('SELECT id FROM attendance WHERE student_id = ? AND date = ? AND subject_id IS ?').get(student_id, date, subject_id || null);
    
    if (existing) {
      getDb().prepare(`
        UPDATE attendance SET
          status = ?,
          remarks = ?,
          marked_by = ?,
          class_id = COALESCE(?, class_id),
          updated_at = CURRENT_TIMESTAMP,
          sync_status = 'pending'
        WHERE id = ?
      `).run(status, remarks, req.user.id, class_id, existing.id);
      
      const updated = getDb().prepare('SELECT * FROM attendance WHERE id = ?').get(existing.id);
      return res.json(updated);
    }
    
    const uid = uuidv4();
    const result = getDb().prepare(`
      INSERT INTO attendance (uid, student_id, class_id, subject_id, date, status, remarks, marked_by)
      VALUES (?, ?, ?, ?, ?, ?, ?, ?)
    `).run(uid, student_id, class_id, subject_id, date, status, remarks, req.user.id);
    
    const record = getDb().prepare(`
      SELECT a.*, u.first_name || ' ' || u.last_name as student_name, c.name as class_name
      FROM attendance a
      JOIN users u ON a.student_id = u.id
      LEFT JOIN classes c ON a.class_id = c.id
      WHERE a.id = ?
    `).get(result.lastInsertRowid);
    
    res.status(201).json(record);
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

// Bulk mark attendance
router.post('/bulk', auth, adminOrTeacher, (req, res) => {
  try {
    const { records } = req.body;
    
    if (!Array.isArray(records) || records.length === 0) {
      return res.status(400).json({ error: 'Records array required' });
    }
    
    // Validate all records first
    for (const record of records) {
      if (!record.student_id || !record.date || !record.status) {
        return res.status(400).json({ error: 'Each record must have student_id, date, and status' });
      }
    }
    
    const upsert = getDb().prepare(`
      INSERT INTO attendance (uid, student_id, class_id, subject_id, date, status, remarks, marked_by)
      VALUES (?, ?, ?, ?, ?, ?, ?, ?)
    `);
    
    const upsertMany = getDb().transaction((records) => {
      let inserted = 0;
      let updated = 0;
      
      for (const record of records) {
        const existing = getDb().prepare('SELECT id FROM attendance WHERE student_id = ? AND date = ?').get(record.student_id, record.date);
        
        if (existing) {
          getDb().prepare(`
            UPDATE attendance SET status = ?, remarks = ?, marked_by = ?, updated_at = CURRENT_TIMESTAMP, sync_status = 'pending'
            WHERE id = ?
          `).run(record.status, record.remarks, req.user.id, existing.id);
          updated++;
        } else {
          const uid = uuidv4();
          upsert.run(uid, record.student_id, record.class_id, record.subject_id, record.date, record.status, record.remarks, req.user.id);
          inserted++;
        }
      }
      
      return { inserted, updated };
    });
    
    const result = upsertMany(records);
    res.status(201).json({ success: true, ...result });
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

// Update attendance
router.put('/:id', auth, adminOrTeacher, (req, res) => {
  try {
    const { status, remarks } = req.body;
    
    if (!status) {
      return res.status(400).json({ error: 'Status is required' });
    }
    
    getDb().prepare(`
      UPDATE attendance SET
        status = ?,
        remarks = COALESCE(?, remarks),
        marked_by = ?,
        updated_at = CURRENT_TIMESTAMP,
        sync_status = 'pending'
      WHERE id = ? AND is_deleted = 0
    `).run(status, remarks, req.user.id, req.params.id);
    
    const updated = getDb().prepare(`
      SELECT a.*, u.first_name || ' ' || u.last_name as student_name
      FROM attendance a
      JOIN users u ON a.student_id = u.id
      WHERE a.id = ?
    `).get(req.params.id);
    
    if (!updated) {
      return res.status(404).json({ error: 'Attendance record not found' });
    }
    
    res.json(updated);
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

// ============ DAILY ATTENDANCE ============

// Get class attendance for a date
router.get('/class/:classId/date/:date', auth, (req, res) => {
  try {
    const { class_id, date } = req.params;
    
    // Get all enrolled students
    const students = getDb().prepare(`
      SELECT u.id, u.first_name, u.last_name, e.roll_number
      FROM enrollments e
      JOIN users u ON e.student_id = u.id
      WHERE e.class_id = ? AND e.status = 'active' AND e.is_deleted = 0 AND u.is_deleted = 0
      ORDER BY e.roll_number, u.last_name
    `).all(class_id);
    
    // Get attendance for that date
    const attendance = getDb().prepare(`
      SELECT * FROM attendance
      WHERE class_id = ? AND date = ? AND is_deleted = 0
    `).all(class_id, date);
    
    // Map attendance to students
    const attendanceMap = {};
    attendance.forEach(a => { attendanceMap[a.student_id] = a; });
    
    const result = students.map(s => ({
      ...s,
      attendance: attendanceMap[s.id] || null
    }));
    
    res.json({
      date,
      class_id: parseInt(class_id),
      total_students: students.length,
      marked: attendance.length,
      records: result
    });
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

// ============ ATTENDANCE REPORTS ============

// Get attendance summary
router.get('/reports/summary', auth, adminOrTeacher, (req, res) => {
  try {
    const { class_id, start_date, end_date } = req.query;
    
    let whereClause = 'a.is_deleted = 0';
    const params = [];
    
    if (class_id) {
      whereClause += ' AND a.class_id = ?';
      params.push(class_id);
    }
    if (start_date) {
      whereClause += ' AND a.date >= ?';
      params.push(start_date);
    }
    if (end_date) {
      whereClause += ' AND a.date <= ?';
      params.push(end_date);
    }
    
    const summary = getDb().prepare(`
      SELECT 
        COUNT(*) as total_records,
        SUM(CASE WHEN a.status = 'present' THEN 1 ELSE 0 END) as present,
        SUM(CASE WHEN a.status = 'absent' THEN 1 ELSE 0 END) as absent,
        SUM(CASE WHEN a.status = 'late' THEN 1 ELSE 0 END) as late,
        SUM(CASE WHEN a.status = 'excused' THEN 1 ELSE 0 END) as excused
      FROM attendance a
      WHERE ${whereClause}
    `).get(...params);
    
    res.json({
      ...summary,
      present_percentage: summary.total_records > 0 ? ((summary.present / summary.total_records) * 100).toFixed(1) : 0,
      absent_percentage: summary.total_records > 0 ? ((summary.absent / summary.total_records) * 100).toFixed(1) : 0
    });
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

// Get student attendance report
router.get('/reports/student/:studentId', auth, (req, res) => {
  try {
    const studentId = parseInt(req.params.studentId);
    
    // Check access
    if (req.user.role === 'student' && req.user.id !== studentId) {
      return res.status(403).json({ error: 'Access denied' });
    }
    
    const { start_date, end_date } = req.query;
    
    let query = `
      SELECT a.*, c.name as class_name, s.name as subject_name
      FROM attendance a
      LEFT JOIN classes c ON a.class_id = c.id
      LEFT JOIN subjects s ON a.subject_id = s.id
      WHERE a.student_id = ? AND a.is_deleted = 0
    `;
    const params = [studentId];
    
    if (start_date) {
      query += ' AND a.date >= ?';
      params.push(start_date);
    }
    if (end_date) {
      query += ' AND a.date <= ?';
      params.push(end_date);
    }
    
    query += ' ORDER BY a.date DESC';
    
    const records = getDb().prepare(query).all(...params);
    
    // Calculate summary
    const summary = {
      total: records.length,
      present: records.filter(r => r.status === 'present').length,
      absent: records.filter(r => r.status === 'absent').length,
      late: records.filter(r => r.status === 'late').length,
      excused: records.filter(r => r.status === 'excused').length
    };
    
    res.json({ records, summary });
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

// ============ MY ATTENDANCE (Student) ============

router.get('/my', auth, (req, res) => {
  try {
    const { start_date, end_date } = req.query;
    
    let query = `
      SELECT a.*, c.name as class_name
      FROM attendance a
      LEFT JOIN classes c ON a.class_id = c.id
      WHERE a.student_id = ? AND a.is_deleted = 0
    `;
    const params = [req.user.id];
    
    if (start_date) {
      query += ' AND a.date >= ?';
      params.push(start_date);
    }
    if (end_date) {
      query += ' AND a.date <= ?';
      params.push(end_date);
    }
    
    query += ' ORDER BY a.date DESC';
    
    const records = getDb().prepare(query).all(...params);
    
    const summary = {
      total: records.length,
      present: records.filter(r => r.status === 'present').length,
      absent: records.filter(r => r.status === 'absent').length,
      late: records.filter(r => r.status === 'late').length,
      excused: records.filter(r => r.status === 'excused').length
    };
    
    res.json({ records, summary });
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

module.exports = router;