require('dotenv').config();
const express = require('express');
const cors = require('cors');
const mysql = require('mysql2/promise');

const app = express();
const PORT = process.env.PORT || 3000;

// Middleware
app.use(cors());
app.use(express.json());

// Configuración de base de datos
const pool = mysql.createPool({
  host: process.env.DB_HOST || 'localhost',
  user: process.env.DB_USER || 'root',
  password: process.env.DB_PASS || '',
  database: process.env.DB_NAME || 'boletas_db',
  waitForConnections: true,
  connectionLimit: 10,
  queueLimit: 0
});

// Probar conexión
async function testConnection() {
  try {
    const connection = await pool.getConnection();
    console.log('✅ Conexión a MySQL exitosa');
    connection.release();
    return true;
  } catch (error) {
    console.log('❌ Error de conexión:', error.message);
    return false;
  }
}

// Middleware de autenticación
const authenticateToken = (req, res, next) => {
  const authHeader = req.headers['authorization'];
  const token = authHeader && authHeader.split(' ')[1];
  
  if (!token) {
    return res.status(401).json({ error: 'Token requerido' });
  }
  
  const jwt = require('jsonwebtoken');
  jwt.verify(token, process.env.JWT_SECRET || 'secreto_sistema_2025', (err, user) => {
    if (err) return res.status(403).json({ error: 'Token inválido' });
    req.user = user;
    next();
  });
};

// ============ AUTH ============
app.post('/api/login', async (req, res) => {
  try {
    const { email, password } = req.body;
    const bcrypt = require('bcryptjs');
    
    const [users] = await pool.query(
      'SELECT * FROM usuarios WHERE email = ? OR usuario = ?',
      [email, email]
    );
    
    if (users.length === 0) {
      return res.status(401).json({ error: 'Usuario no encontrado' });
    }
    
    const user = users[0];
    const validPassword = await bcrypt.compare(password, user.password);
    
    if (!validPassword) {
      return res.status(401).json({ error: 'Contraseña incorrecta' });
    }
    
    const jwt = require('jsonwebtoken');
    const token = jwt.sign(
      { id: user.id, email: user.email, rol: user.rol },
      process.env.JWT_SECRET || 'secreto_sistema_2025',
      { expiresIn: '24h' }
    );
    
    res.json({ token, user: { id: user.id, nombre: user.nombre, email: user.email, rol: user.rol } });
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

app.post('/api/registro', async (req, res) => {
  try {
    const { nombre, email, password, unidad_id } = req.body;
    const bcrypt = require('bcryptjs');
    
    const hashedPassword = await bcrypt.hash(password, 10);
    
    const [result] = await pool.query(
      'INSERT INTO usuarios (nombre, email, password, rol, unidad_id) VALUES (?, ?, ?, ?, ?)',
      [nombre, email, hashedPassword, 'docente', unidad_id || null]
    );
    
    res.json({ success: true, id: result.insertId });
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

app.post('/api/recuperar-password', async (req, res) => {
  try {
    const { email } = req.body;
    const bcrypt = require('bcryptjs');
    
    const [users] = await pool.query('SELECT * FROM usuarios WHERE email = ?', [email]);
    
    if (users.length === 0) {
      return res.json({ success: true, message: 'Si el email existe, recibirás las instrucciones' });
    }
    
    const nuevaPassword = Math.random().toString(36).slice(-10);
    const hashedPassword = await bcrypt.hash(nuevaPassword, 10);
    
    await pool.query('UPDATE usuarios SET password = ? WHERE id = ?', [hashedPassword, users[0].id]);
    
    res.json({ success: true, message: 'Nueva contraseña: ' + nuevaPassword + ' (cambiala después de iniciar sesión)' });
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

// ============ UNIDADES ============
app.get('/api/unidades', async (req, res) => {
  try {
    const [rows] = await pool.query('SELECT * FROM unidades ORDER BY nombre');
    res.json(rows);
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

app.post('/api/unidades', async (req, res) => {
  try {
    const { nombre, codigo, director, telefono } = req.body;
    const [result] = await pool.query(
      'INSERT INTO unidades (nombre, codigo, director, telefono) VALUES (?, ?, ?, ?)',
      [nombre, codigo, director, telefono]
    );
    
    // Crear configuración por defecto
    await pool.query(
      'INSERT INTO configuracion (unidad_id, momento1, momento2, momento3, ano_escolar) VALUES (?, ?, ?, ?, ?)',
      [result.insertId, '1er Lapso', '2do Lapso', '3er Lapso', '2025-2026']
    );
    
    res.json({ id: result.insertId, success: true });
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

// ============ CONFIGURACIÓN ============
app.get('/api/configuracion/:unidad_id', async (req, res) => {
  try {
    const [rows] = await pool.query(
      'SELECT * FROM configuracion WHERE unidad_id = ?',
      [req.params.unidad_id]
    );
    res.json(rows[0] || {});
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

app.post('/api/configuracion', async (req, res) => {
  try {
    const { unidad_id, momento1, momento2, momento3, ano_escolar } = req.body;
    
    const [existing] = await pool.query('SELECT * FROM configuracion WHERE unidad_id = ?', [unidad_id]);
    
    if (existing.length > 0) {
      await pool.query(
        'UPDATE configuracion SET momento1=?, momento2=?, momento3=?, ano_escolar=? WHERE unidad_id=?',
        [momento1, momento2, momento3, ano_escolar, unidad_id]
      );
    } else {
      await pool.query(
        'INSERT INTO configuracion (unidad_id, momento1, momento2, momento3, ano_escolar) VALUES (?, ?, ?, ?, ?)',
        [unidad_id, momento1, momento2, momento3, ano_escolar]
      );
    }
    
    res.json({ success: true });
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

// ============ CURSOS ============
app.get('/api/cursos', async (req, res) => {
  try {
    const { unidad_id } = req.query;
    let query = 'SELECT * FROM cursos';
    let params = [];
    
    if (unidad_id) {
      query += ' WHERE unidad_id = ?';
      params = [unidad_id];
    }
    
    query += ' ORDER BY grado, seccion, nombre';
    const [rows] = await pool.query(query, params);
    res.json(rows);
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

app.post('/api/cursos', async (req, res) => {
  try {
    const { unidad_id, nombre, grado, seccion } = req.body;
    const [result] = await pool.query(
      'INSERT INTO cursos (unidad_id, nombre, grado, seccion) VALUES (?, ?, ?, ?)',
      [unidad_id, nombre, grado, seccion]
    );
    res.json({ id: result.insertId, success: true });
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

app.put('/api/cursos/:id', async (req, res) => {
  try {
    const { nombre, grado, seccion } = req.body;
    await pool.query(
      'UPDATE cursos SET nombre=?, grado=?, seccion=? WHERE id=?',
      [nombre, grado, seccion, req.params.id]
    );
    res.json({ success: true });
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

app.delete('/api/cursos/:id', async (req, res) => {
  try {
    await pool.query('DELETE FROM cursos WHERE id=?', [req.params.id]);
    res.json({ success: true });
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

// ============ ALUMNOS ============
app.get('/api/alumnos', async (req, res) => {
  try {
    const { unidad_id, curso_id } = req.query;
    let query = `SELECT a.*, c.nombre as curso_nombre, c.grado, c.seccion 
                 FROM alumnos a 
                 LEFT JOIN cursos c ON a.curso_id = c.id 
                 WHERE 1=1`;
    let params = [];
    
    if (unidad_id) { query += ' AND a.unidad_id = ?'; params.push(unidad_id); }
    if (curso_id) { query += ' AND a.curso_id = ?'; params.push(curso_id); }
    
    query += ' ORDER BY a.apellido, a.nombre';
    const [rows] = await pool.query(query, params);
    res.json(rows);
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

app.post('/api/alumnos', async (req, res) => {
  try {
    const { unidad_id, nombre, apellido, sexo, curso_id } = req.body;
    const [result] = await pool.query(
      'INSERT INTO alumnos (unidad_id, nombre, apellido, sexo, curso_id) VALUES (?, ?, ?, ?, ?)',
      [unidad_id, nombre, apellido, sexo, curso_id]
    );
    res.json({ id: result.insertId, success: true });
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

app.put('/api/alumnos/:id', async (req, res) => {
  try {
    const { nombre, apellido, sexo, curso_id } = req.body;
    await pool.query(
      'UPDATE alumnos SET nombre=?, apellido=?, sexo=?, curso_id=? WHERE id=?',
      [nombre, apellido, sexo, curso_id, req.params.id]
    );
    res.json({ success: true });
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

app.delete('/api/alumnos/:id', async (req, res) => {
  try {
    await pool.query('DELETE FROM alumnos WHERE id=?', [req.params.id]);
    res.json({ success: true });
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

// ============ MATERIAS ============
app.get('/api/materias', async (req, res) => {
  try {
    const { unidad_id } = req.query;
    let query = 'SELECT * FROM materias';
    let params = [];
    
    if (unidad_id) { query += ' WHERE unidad_id = ?'; params.push(unidad_id); }
    
    query += ' ORDER BY nombre';
    const [rows] = await pool.query(query, params);
    res.json(rows);
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

app.post('/api/materias', async (req, res) => {
  try {
    const { unidad_id, nombre, descripcion, icono } = req.body;
    const [result] = await pool.query(
      'INSERT INTO materias (unidad_id, nombre, descripcion, icono) VALUES (?, ?, ?, ?)',
      [unidad_id, nombre, descripcion, icono]
    );
    res.json({ id: result.insertId, success: true });
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

app.put('/api/materias/:id', async (req, res) => {
  try {
    const { nombre, descripcion, icono } = req.body;
    await pool.query(
      'UPDATE materias SET nombre=?, descripcion=?, icono=? WHERE id=?',
      [nombre, descripcion, icono, req.params.id]
    );
    res.json({ success: true });
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

app.delete('/api/materias/:id', async (req, res) => {
  try {
    await pool.query('DELETE FROM materias WHERE id=?', [req.params.id]);
    res.json({ success: true });
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

// ============ COMPETENCIAS ============
app.get('/api/competencias', async (req, res) => {
  try {
    const { unidad_id } = req.query;
    let query = `SELECT c.*, m.nombre as materia_nombre, m.icono as materia_icono 
                 FROM competencias c 
                 LEFT JOIN materias m ON c.materia_id = m.id 
                 WHERE 1=1`;
    let params = [];
    
    if (unidad_id) { query += ' AND c.unidad_id = ?'; params.push(unidad_id); }
    
    query += ' ORDER BY c.id DESC';
    const [rows] = await pool.query(query, params);
    res.json(rows);
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

app.post('/api/competencias', async (req, res) => {
  try {
    const { unidad_id, nombre, descripcion, materia_id } = req.body;
    const [result] = await pool.query(
      'INSERT INTO competencias (unidad_id, nombre, descripcion, materia_id) VALUES (?, ?, ?, ?)',
      [unidad_id, nombre, descripcion, materia_id]
    );
    res.json({ id: result.insertId, success: true });
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

app.put('/api/competencias/:id', async (req, res) => {
  try {
    const { nombre, descripcion, materia_id } = req.body;
    await pool.query(
      'UPDATE competencias SET nombre=?, descripcion=?, materia_id=? WHERE id=?',
      [nombre, descripcion, materia_id, req.params.id]
    );
    res.json({ success: true });
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

app.delete('/api/competencias/:id', async (req, res) => {
  try {
    await pool.query('DELETE FROM competencias WHERE id=?', [req.params.id]);
    res.json({ success: true });
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

app.post('/api/competencias/:id/completar', async (req, res) => {
  try {
    const { completada } = req.body;
    await pool.query(
      'UPDATE competencias SET completada=? WHERE id=?',
      [completada ? 1 : 0, req.params.id]
    );
    res.json({ success: true });
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

// ============ INDICADORES ============
app.get('/api/indicadores', async (req, res) => {
  try {
    const { unidad_id, materia_id } = req.query;
    let query = 'SELECT i.*, m.nombre as materia_nombre FROM indicadores i LEFT JOIN materias m ON i.materia_id = m.id WHERE 1=1';
    let params = [];
    
    if (unidad_id) { query += ' AND i.unidad_id = ?'; params.push(unidad_id); }
    if (materia_id) { query += ' AND i.materia_id = ?'; params.push(materia_id); }
    
    query += ' ORDER BY i.id DESC';
    const [rows] = await pool.query(query, params);
    res.json(rows);
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

app.post('/api/indicadores', async (req, res) => {
  try {
    const { unidad_id, descripcion, materia_id, grado } = req.body;
    const [result] = await pool.query(
      'INSERT INTO indicadores (unidad_id, descripcion, materia_id, grado) VALUES (?, ?, ?, ?)',
      [unidad_id, descripcion, materia_id, grado]
    );
    res.json({ id: result.insertId, success: true });
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

app.put('/api/indicadores/:id', async (req, res) => {
  try {
    const { descripcion, materia_id, grado } = req.body;
    await pool.query(
      'UPDATE indicadores SET descripcion=?, materia_id=?, grado=? WHERE id=?',
      [descripcion, materia_id, grado, req.params.id]
    );
    res.json({ success: true });
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

app.delete('/api/indicadores/:id', async (req, res) => {
  try {
    await pool.query('DELETE FROM indicadores WHERE id=?', [req.params.id]);
    res.json({ success: true });
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

// ============ EVALUACIONES ============
app.get('/api/evaluaciones', async (req, res) => {
  try {
    const { unidad_id, curso_id, materia_id } = req.query;
    let query = `SELECT e.*, m.nombre as materia_nombre, c.nombre as curso_nombre 
                 FROM evaluaciones e 
                 LEFT JOIN materias m ON e.materia_id = m.id 
                 LEFT JOIN cursos c ON e.curso_id = c.id 
                 WHERE 1=1`;
    let params = [];
    
    if (unidad_id) { query += ' AND e.unidad_id = ?'; params.push(unidad_id); }
    if (curso_id) { query += ' AND e.curso_id = ?'; params.push(curso_id); }
    if (materia_id) { query += ' AND e.materia_id = ?'; params.push(materia_id); }
    
    query += ' ORDER BY e.fecha DESC';
    const [rows] = await pool.query(query, params);
    res.json(rows);
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

app.post('/api/evaluaciones', async (req, res) => {
  try {
    const { unidad_id, nombre, fecha, curso_id, materia_id, periodo, indicador_ids } = req.body;
    const [result] = await pool.query(
      'INSERT INTO evaluaciones (unidad_id, nombre, fecha, curso_id, materia_id, periodo) VALUES (?, ?, ?, ?, ?, ?)',
      [unidad_id, nombre, fecha, curso_id, materia_id, periodo]
    );
    
    // Agregar indicadores
    if (indicador_ids && indicador_ids.length > 0) {
      for (const indicador_id of indicador_ids) {
        await pool.query(
          'INSERT INTO evaluacion_indicador (evaluacion_id, indicador_id) VALUES (?, ?)',
          [result.insertId, indicador_id]
        );
      }
    }
    
    res.json({ id: result.insertId, success: true });
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

app.delete('/api/evaluaciones/:id', async (req, res) => {
  try {
    await pool.query('DELETE FROM evaluacion_indicador WHERE evaluacion_id=?', [req.params.id]);
    await pool.query('DELETE FROM evaluaciones WHERE id=?', [req.params.id]);
    res.json({ success: true });
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

// ============ RESULTADOS ============
app.get('/api/resultados', async (req, res) => {
  try {
    const { evaluacion_id } = req.query;
    const [rows] = await pool.query(
      'SELECT * FROM resultados WHERE evaluacion_id = ?',
      [evaluacion_id]
    );
    res.json(rows);
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

app.post('/api/resultados', async (req, res) => {
  try {
    const { resultados } = req.body;
    
    for (const r of resultados) {
      // Upsert
      await pool.query(
        `INSERT INTO resultados (alumno_id, evaluacion_id, indicador_id, nivel_logro) 
         VALUES (?, ?, ?, ?) 
         ON DUPLICATE KEY UPDATE nivel_logro = ?`,
        [r.alumno_id, r.evaluacion_id, r.indicador_id, r.nivel_logro, r.nivel_logro]
      );
    }
    
    res.json({ success: true });
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

// ============ ASISTENCIA ============
app.get('/api/asistencia', async (req, res) => {
  try {
    const { curso_id, fecha } = req.query;
    const [alumnos] = await pool.query(
      'SELECT * FROM alumnos WHERE curso_id = ?',
      [curso_id]
    );
    
    const [asistencias] = await pool.query(
      'SELECT * FROM asistencia WHERE curso_id = ? AND fecha = ?',
      [curso_id, fecha]
    );
    
    res.json({ alumnos, estadisticas: { presentes: 0, faltas: 0, tardanzas: 0 } });
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

app.post('/api/asistencia', async (req, res) => {
  try {
    const { curso_id, fecha, asistencia } = req.body;
    
    for (const a of asistencia) {
      // Verificar si existe
      const [existing] = await pool.query(
        'SELECT * FROM asistencia WHERE alumno_id = ? AND fecha = ?',
        [a.alumno_id, fecha]
      );
      
      if (existing.length > 0) {
        await pool.query(
          'UPDATE asistencia SET presente=?, falta=?, tardanza=? WHERE id=?',
          [a.presente ? 1 : 0, a.falta ? 1 : 0, a.tardanza ? 1 : 0, existing[0].id]
        );
      } else {
        await pool.query(
          'INSERT INTO asistencia (alumno_id, curso_id, fecha, presente, falta, tardanza) VALUES (?, ?, ?, ?, ?, ?)',
          [a.alumno_id, curso_id, fecha, a.presente ? 1 : 0, a.falta ? 1 : 0, a.tardanza ? 1 : 0]
        );
      }
    }
    
    res.json({ success: true });
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

// ============ CALENDARIO ============
app.get('/api/calendario', async (req, res) => {
  try {
    const { unidad_id } = req.query;
    const [rows] = await pool.query(
      'SELECT * FROM calendario WHERE unidad_id = ? ORDER BY fecha',
      [unidad_id]
    );
    res.json(rows);
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

app.post('/api/calendario', async (req, res) => {
  try {
    const { unidad_id, titulo, descripcion, fecha, tipo } = req.body;
    const [result] = await pool.query(
      'INSERT INTO calendario (unidad_id, titulo, descripcion, fecha, tipo) VALUES (?, ?, ?, ?, ?)',
      [unidad_id, titulo, descripcion, fecha, tipo]
    );
    res.json({ id: result.insertId, success: true });
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

// ============ ESTADÍSTICAS ============
app.get('/api/estadisticas', async (req, res) => {
  try {
    const { unidad_id } = req.query;
    
    const [[alumnos]] = await pool.query('SELECT COUNT(*) as total FROM alumnos WHERE unidad_id = ?', [unidad_id]);
    const [[cursos]] = await pool.query('SELECT COUNT(*) as total FROM cursos WHERE unidad_id = ?', [unidad_id]);
    const [[materias]] = await pool.query('SELECT COUNT(*) as total FROM materias WHERE unidad_id = ?', [unidad_id]);
    const [[competencias]] = await pool.query('SELECT COUNT(*) as total, SUM(completada) as completadas FROM competencias WHERE unidad_id = ?', [unidad_id]);
    
    res.json({
      total_alumnos: alumnos?.total || 0,
      total_cursos: cursos?.total || 0,
      total_materias: materias?.total || 0,
      total_competencias: competencias?.total || 0,
      competencias_completadas: competencias?.completadas || 0
    });
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

// ============ BOLETAS ============
app.get('/api/boletas', async (req, res) => {
  try {
    const { alumno_id, periodo } = req.query;
    
    // Obtener datos del alumno
    const [alumnos] = await pool.query(
      'SELECT a.*, c.nombre as curso_nombre FROM alumnos a LEFT JOIN cursos c ON a.curso_id = c.id WHERE a.id = ?',
      [alumno_id]
    );
    
    if (alumnos.length === 0) {
      return res.status(404).json({ error: 'Alumno no encontrado' });
    }
    
    const alumno = alumnos[0];
    
    // Obtener materias con promedio
    const [materias] = await pool.query(
      'SELECT m.*, AVG(r.nivel_logro) as promedio FROM materias m LEFT JOIN resultados r ON m.id = r.indicador_id LEFT JOIN evaluaciones e ON r.evaluacion_id = e.id WHERE e.unidad_id = ? GROUP BY m.id',
      [alumno.unidad_id]
    );
    
    res.json({
      alumno,
      curso: { nombre: alumno.curso_nombre },
      materias,
      periodo: periodo || '1er Lapso'
    });
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

// Iniciar servidor
app.listen(PORT, async () => {
  console.log(`🚀 Servidor corriendo en puerto ${PORT}`);
  await testConnection();
});
