const bcrypt = require('bcrypt');
const {
  Admin
} = require('../models');
const logger = require('../utils/logger');
const BaseController = require('./base.controller');

class AdminController extends BaseController {
  constructor() {
    super(Admin, 'Admin', ['Name', 'LastName', 'Email', 'Phone']);
  }

  // Sobrescribir getById para excluir password
  getById = async (req, res, next) => {
    try {
      const {
        id
      } = req.params;
      const data = await this.model.findByPk(id, {
        attributes: {
          exclude: ['Password']
        }
      });

      if (!data) {
        return res.status(404).json({
          success: false,
          message: `${this.modelName} no encontrado`
        });
      }

      res.json({
        success: true,
        message: `${this.modelName} obtenido exitosamente`,
        data
      });
    } catch (error) {
      next(error);
    }
  };

  // Sobrescribir getAll para excluir password
  getAll = async (req, res, next) => {
    try {
      const {
        search, sortBy, sortOrder, ...filters
      } = req.query;

      const {
        buildQueryOptions
      } = require('../utils/queryBuilder');

      const queryOptions = buildQueryOptions({
        search,
        searchFields: this.searchFields,
        sortBy,
        sortOrder,
        ...filters
      });

      queryOptions.attributes = {
        exclude: ['Password']
      };

      const data = await this.model.findAndCountAll(queryOptions);

      res.json({
        success: true,
        message: `${this.modelName} obtenidos exitosamente`,
        ...data
      });
    } catch (error) {
      next(error);
    }
  };

  // Buscar por email
  findByEmail = async (req, res, next) => {
    try {
      const {
        email
      } = req.params;
      const admin = await Admin.findOne({
        where: {
          Email: email
        },
        attributes: {
          exclude: ['Password']
        }
      });

      if (!admin) {
        logger.warn('Admin no encontrado', {
          email,
          ip: req.ip
        });
        return res.status(404).json({
          success: false,
          message: 'Admin no encontrado'
        });
      }
      logger.info('Admin encontrado', {
        email,
        ip: req.ip
      });
      res.json({
        success: true,
        data: admin
      });
    } catch (error) {
      next(error);
    }
  };

  updateAdminCode = async (req, res) => {
    try {
      const { id } = req.params;           // ID del admin en la URL
      const { code } = req.body;           // Código que llega en el body
      // Validar que el ID esté presente
      if (!id) {
        return res.status(400).json({
          success: false,
          message: 'El ID del admin es requerido en la URL',
        });
      }
      // Validar que el código llegue y no esté vacío
      if (!code || typeof code !== 'string' || code.trim() === '') {
        return res.status(400).json({
          success: false,
          message: 'El campo "code" es requerido y no puede estar vacío',
        });
      }

      // Buscar al admin por ID
      const admin = await Admin.findByPk(id);

      if (!admin) {
        logger.warn('Intento de actualizar Code - Admin no encontrado', {
          adminId: id,
          ip: req.ip,
        });
        return res.status(404).json({
          success: false,
          message: 'Admin no encontrado',
        });
      }

      // ACTUALIZAR SOLO EL CAMPO Code
      await admin.update({
        Code: code.trim(),   // Guardamos exactamente el código recibido
        // Si también usas CodeExpiresAt y quieres actualizarlo, descomenta:
        // CodeExpiresAt: new Date(Date.now() + 15 * 60 * 1000), // 15 min de vida
      });
      
      logger.auth('Código actualizado exitosamente - Admin', {
        adminId: admin.Id,
        codeLength: code.trim().length,
        ip: req.ip,
      });

      return res.json({
        success: true,
        message: 'Código actualizado correctamente',
        data: {
          adminId: admin.Id,
          updatedCode: code.trim(), // opcional: solo en dev si quieres verlo
        },
      });

    } catch (error) {
      logger.error('Error al actualizar el código del admin', {
        error: error.message,
        stack: error.stack,
        adminId: req.params.id,
      });

      return res.status(500).json({
        success: false,
        message: 'Error en el servidor',
        error: process.env.NODE_ENV === 'development' ? error.message : undefined,
      });
    }
  };

  /**
   * Resetear contraseña de Admin usando Phone
   */
  resetPasswordByPhone = async (req, res) => {
    try {
      const {
        adminId,
        newPassword
      } = req.body;

      // Validar campos requeridos
      if (!adminId || !newPassword) {
        return res.status(400).json({
          success: false,
          message: 'ID de admin y nueva contraseña son requeridos'
        });
      }

      // Validar longitud de contraseña
      if (newPassword.length < 2) {
        return res.status(400).json({
          success: false,
          message: 'La contraseña debe tener al menos 2 caracteres'
        });
      }

      // Buscar admin por teléfono
      const admin = await Admin.findOne({
        where: {
          id: adminId
        }
      });

      if (!admin) {
        logger.warn('Reset password fallido - Admin no encontrado', {
          phone,
          ip: req.ip
        });
        return res.status(404).json({
          success: false,
          message: 'No se encontró un administrador con ese número de teléfono'
        });
      }

      // Hashear nueva contraseña
      const hashedPassword = await bcrypt.hash(
        newPassword,
        parseInt(process.env.BCRYPT_ROUNDS) || 10
      );

      // Actualizar contraseña
      await admin.update({
        Password: hashedPassword
      });

      // Log exitoso
      logger.auth('Contraseña reseteada exitosamente - Admin', {
        adminId: admin.Id,
        phone: admin.Phone,
        ip: req.ip
      });

      res.json({
        success: true,
        message: 'Contraseña reseteada exitosamente',
        data: {
          email: admin.Email,
          name: admin.Name
        }
      });

    } catch (error) {
      logger.error('Error al resetear contraseña de admin', {
        error: error.message,
        stack: error.stack
      });
      res.status(500).json({
        success: false,
        message: 'Error en el servidor',
        error: process.env.NODE_ENV === 'development' ? error.message : undefined
      });
    }
  };

  /**
   * Verificar si existe un admin por teléfono (para validación previa)
   */
  verifyPhoneExists = async (req, res) => {
    try {
      const {
        phone
      } = req.params;

      const admin = await Admin.findOne({
        where: {
          Phone: phone
        },
        attributes: ['Id', 'Name', 'Email']
      });

      if (!admin) {
        return res.status(404).json({
          success: false,
          message: 'No se encontró un administrador con ese teléfono'
        });
      }

      res.json({
        success: true,
        message: 'Administrador encontrado',
        data: {
          name: admin.Name,
          email: admin.Email.replace(/(.{2})(.*)(@.*)/, '$1***$3') // Ocultar parte del email
        }
      });

    } catch (error) {
      logger.error('Error al verificar teléfono de admin', {
        error: error.message
      });
      res.status(500).json({
        success: false,
        message: 'Error en el servidor'
      });
    }
  };

  /**
   * Solicitar código de verificación (opcional - para implementar 2FA)
   */
  requestVerificationCode = async (req, res) => {
    try {
      const {
        phone
      } = req.body;

      const admin = await Admin.findOne({
        where: {
          Phone: phone
        }
      });

      if (!admin) {
        return res.status(404).json({
          success: false,
          message: 'No se encontró un administrador con ese teléfono'
        });
      }

      // Generar código de 6 dígitos
      const verificationCode = Math.floor(100000 + Math.random() * 900000).toString();

      // TODO: Aquí deberías enviar el código por SMS
      // Por ahora solo lo guardamos en memoria o base de datos temporal

      logger.auth('Código de verificación generado - Admin', {
        adminId: admin.Id,
        phone: admin.Phone,
        code: verificationCode, // En producción NO logear el código
        ip: req.ip
      });

      // En desarrollo, devolver el código (NUNCA en producción)
      if (process.env.NODE_ENV === 'development') {
        return res.json({
          success: true,
          message: 'Código de verificación generado',
          code: verificationCode // Solo para desarrollo
        });
      }

      res.json({
        success: true,
        message: 'Código de verificación enviado al teléfono registrado'
      });

    } catch (error) {
      logger.error('Error al solicitar código de verificación', {
        error: error.message
      });
      res.status(500).json({
        success: false,
        message: 'Error en el servidor'
      });
    }

  }
}

module.exports = new AdminController();