import express from "express";
import multer from "multer";
import path from "path";
import {
  login,
  createAdmin,
  verifySession,
  getCurrentUser,
  refreshToken,
  logout,
  getUsers,
  getUserById,
  confirmEmail,
  editUser,
  forgotPassword,
  subscribePush,
  unsubscribePush,
  generateToken,
} from "../controllers/adminController";
import { authorizeModules, verifyToken } from "../middlewares/authJwt";
import { fileURLToPath } from "url";

const routes = express.Router();

/**
 * @swagger
 * tags:
 *   name: Admin
 *   description: Autenticación y gestión de administradores
 */

// Configuración de almacenamiento
const storage = multer.diskStorage({
  destination: (req: any, file: any, cb: any) => {
    const __filename = fileURLToPath(import.meta.url);
    const __dirname = path.dirname(__filename);
    cb(null, path.join(__dirname, "../public/profile-pics"));
  },
  filename: (req: any, file: any, cb: any) => {
    const ext = path.extname(file.originalname);
    cb(null, `user-${Date.now()}${ext}`);
  },
});

// Filtros y límites
const upload = multer({
  storage,
  limits: { fileSize: 5 * 1024 * 1024 }, // 5MB
  fileFilter: (req: any, file: any, cb: any) => {
    if (/^image\/(jpeg|png|gif)$/.test(file.mimetype)) {
      cb(null, true);
    } else {
      cb(new Error("Solo JPG, PNG o GIF"));
    }
  },
});

/**
 * @swagger
 * /admin/login:
 *   post:
 *     operationId: adminLogin
 *     tags: [Admin]
 *     summary: Login de administrador
 *     requestBody:
 *       required: true
 *       content:
 *         application/json:
 *           schema:
 *             type: object
 *             required: [email, password]
 *             properties:
 *               email:
 *                 type: string
 *                 format: email
 *               password:
 *                 type: string
 *               rememberMe:
 *                 type: boolean
 *                 description: Extender duración de la sesión
 *     responses:
 *       200:
 *         description: Login exitoso
 *         content:
 *           application/json:
 *             schema:
 *               type: object
 *               required: [success, message, data, token]
 *               properties:
 *                 success:
 *                   type: boolean
 *                   example: true
 *                 message:
 *                   type: string
 *                   example: Login successful
 *                 data:
 *                   type: object
 *                   properties:
 *                     id:
 *                       type: string
 *                     name:
 *                       type: string
 *                     lastname:
 *                       type: string
 *                     email:
 *                       type: string
 *                 token:
 *                   type: string
 *                   description: JWT token
 *             example:
 *               success: true
 *               message: Login successful
 *               data:
 *                 id: "507f1f77bcf86cd799439011"
 *                 name: Juan
 *                 lastname: Pérez
 *                 email: admin@example.com
 *               token: "eyJhbGciOiJIUzI1NiIs..."
 *       400:
 *         description: Campos requeridos faltantes
 *         content:
 *           application/json:
 *             schema:
 *               type: object
 *               properties:
 *                 success:
 *                   type: boolean
 *                   example: false
 *                 message:
 *                   type: string
 *                   example: Correo y contraseña son requeridos.
 *                 code:
 *                   type: string
 *                   example: field_missing
 *       401:
 *         description: Credenciales inválidas
 *         content:
 *           application/json:
 *             schema:
 *               type: object
 *               properties:
 *                 success:
 *                   type: boolean
 *                   example: false
 *                 message:
 *                   type: string
 *                 code:
 *                   type: string
 *             examples:
 *               user_not_found:
 *                 summary: Correo no registrado
 *                 value:
 *                   success: false
 *                   message: El correo ingresado no esta registrado.
 *                   code: user_not_found
 *               user_not_active:
 *                 summary: Usuario desactivado
 *                 value:
 *                   success: false
 *                   message: El usuario ha sido desactivado, por favor contacte con el administrador.
 *                   code: user_not_active
 *               invalid_password:
 *                 summary: Contraseña incorrecta
 *                 value:
 *                   success: false
 *                   message: La contraseña ingresada es incorrecta.
 *                   code: invalid_password
 */
routes.route("/login").post(login);

/**
 * @swagger
 * /admin/logout:
 *   post:
 *     operationId: adminLogout
 *     tags: [Admin]
 *     summary: Cerrar sesión
 *     responses:
 *       200:
 *         description: Sesión cerrada correctamente
 *         content:
 *           application/json:
 *             schema:
 *               type: object
 *               properties:
 *                 success:
 *                   type: boolean
 *                   example: true
 *                 message:
 *                   type: string
 *                   example: Logout successful
 *             example:
 *               success: true
 *               message: Logout successful
 */
routes.route("/logout").post(logout);

/**
 * @swagger
 * /admin/users/confirm-email:
 *   post:
 *     tags: [Admin]
 *     summary: Confirmar email y establecer contraseña
 *     requestBody:
 *       required: true
 *       content:
 *         application/json:
 *           schema:
 *             type: object
 *             required: [userId, token, password]
 *             properties:
 *               userId:
 *                 type: string
 *               token:
 *                 type: string
 *               password:
 *                 type: string
 *     responses:
 *       200:
 *         description: Contraseña actualizada correctamente
 *         content:
 *           application/json:
 *             schema:
 *               type: object
 *               properties:
 *                 success:
 *                   type: boolean
 *                   example: true
 *                 message:
 *                   type: string
 *                   example: Password updated successfully
 *                 data:
 *                   type: object
 *                   properties:
 *                     userId:
 *                       type: string
 *             example:
 *               success: true
 *               message: Password updated successfully
 *               data:
 *                 userId: "507f1f77bcf86cd799439011"
 *       404:
 *         description: Usuario o token no encontrado
 *         content:
 *           application/json:
 *             schema:
 *               type: object
 *               properties:
 *                 success:
 *                   type: boolean
 *                   example: false
 *                 message:
 *                   type: string
 *                 code:
 *                   type: string
 *             examples:
 *               user_not_found:
 *                 summary: Usuario no encontrado
 *                 value:
 *                   success: false
 *                   message: User not found
 *                   code: user_not_found
 *               token_not_found:
 *                 summary: Token inválido o expirado
 *                 value:
 *                   success: false
 *                   message: Token es incorrecto o ha expirado. Por favor, contacte con el administrador para volver a enviar el correo de confirmación.
 *                   code: token_not_found
 */
routes.route("/users/confirm-email").post(confirmEmail);

/**
 * @swagger
 * /admin/users/forgot-password:
 *   post:
 *     operationId: adminForgotPassword
 *     tags: [Admin]
 *     summary: Solicitar recuperación de contraseña
 *     requestBody:
 *       required: true
 *       content:
 *         application/json:
 *           schema:
 *             type: object
 *             required: [email]
 *             properties:
 *               email:
 *                 type: string
 *                 format: email
 *     responses:
 *       201:
 *         description: Correo de recuperación enviado
 *         content:
 *           application/json:
 *             schema:
 *               type: object
 *               properties:
 *                 success:
 *                   type: boolean
 *                   example: true
 *                 message:
 *                   type: string
 *                   example: Email sent successfully
 *             example:
 *               success: true
 *               message: Email sent successfully
 *       400:
 *         description: Error en la solicitud
 *         content:
 *           application/json:
 *             schema:
 *               type: object
 *             examples:
 *               email_required:
 *                 summary: Email faltante
 *                 value: "email is required"
 *               email_not_registered:
 *                 summary: Correo no registrado
 *                 value: "Correo no registrado"
 *               smtp_error:
 *                 summary: Error enviando correo
 *                 value: "Hubo un error enviando el correo de confirmación"
 */
routes.route("/users/forgot-password").post(forgotPassword);

routes.use(verifyToken);

/**
 * @swagger
 * /admin/subscribe-push:
 *   post:
 *     operationId: adminSubscribePush
 *     tags: [Admin]
 *     summary: Suscribir push notifications
 *     security:
 *       - bearerAuth: []
 *     requestBody:
 *       required: true
 *       content:
 *         application/json:
 *           schema:
 *             type: object
 *             required: [token]
 *             properties:
 *               token:
 *                 type: string
 *                 description: Token de dispositivo para push
 *     responses:
 *       200:
 *         description: Suscripción registrada correctamente
 *         content:
 *           application/json:
 *             schema:
 *               type: object
 *               properties:
 *                 success:
 *                   type: boolean
 *                   example: true
 *                 message:
 *                   type: string
 *                   example: Push token subscribed successfully
 *                 data:
 *                   type: object
 *                   properties:
 *                     tokens:
 *                       type: number
 *                       description: Cantidad de tokens activos
 *             example:
 *               success: true
 *               message: Push token subscribed successfully
 *               data:
 *                 tokens: 1
 *       404:
 *         description: Usuario no encontrado
 *         content:
 *           application/json:
 *             schema:
 *               type: object
 *               properties:
 *                 success:
 *                   type: boolean
 *                   example: false
 *                 message:
 *                   type: string
 *                   example: User not found
 *                 code:
 *                   type: string
 *                   example: user_not_found
 *       401:
 *         $ref: "#/components/responses/Unauthorized"
 */
routes.route("/subscribe-push").post(subscribePush);

/**
 * @swagger
 * /admin/unsubscribe-push:
 *   post:
 *     operationId: adminUnsubscribePush
 *     tags: [Admin]
 *     summary: Desuscribir push notifications
 *     security:
 *       - bearerAuth: []
 *     requestBody:
 *       required: true
 *       content:
 *         application/json:
 *           schema:
 *             type: object
 *             required: [token]
 *             properties:
 *               token:
 *                 type: string
 *                 description: Token de dispositivo a desuscribir
 *     responses:
 *       200:
 *         description: Desuscripción registrada correctamente
 *         content:
 *           application/json:
 *             schema:
 *               type: object
 *               properties:
 *                 success:
 *                   type: boolean
 *                   example: true
 *                 message:
 *                   type: string
 *                   example: Push token unsubscribed successfully
 *                 data:
 *                   type: object
 *                   properties:
 *                     tokens:
 *                       type: number
 *                       description: Cantidad de tokens activos restantes
 *             example:
 *               success: true
 *               message: Push token unsubscribed successfully
 *               data:
 *                 tokens: 0
 *       404:
 *         description: Usuario no encontrado
 *         content:
 *           application/json:
 *             schema:
 *               type: object
 *               properties:
 *                 success:
 *                   type: boolean
 *                   example: false
 *                 message:
 *                   type: string
 *                   example: User not found
 *                 code:
 *                   type: string
 *                   example: user_not_found
 *       401:
 *         $ref: "#/components/responses/Unauthorized"
 */
routes.route("/unsubscribe-push").post(unsubscribePush);

routes.use(authorizeModules("users"));

/**
 * @swagger
 * /admin/create:
 *   post:
 *     operationId: adminCreate
 *     tags: [Admin]
 *     summary: Crear administrador
 *     security:
 *       - bearerAuth: []
 *     requestBody:
 *       required: true
 *       content:
 *         application/json:
 *           schema:
 *             type: object
 *             required: [name, lastname, email]
 *             properties:
 *               name:
 *                 type: string
 *               lastname:
 *                 type: string
 *               email:
 *                 type: string
 *                 format: email
 *               roles:
 *                 type: array
 *                 items:
 *                   type: string
 *     responses:
 *       201:
 *         description: Administrador creado correctamente
 *         content:
 *           application/json:
 *             schema:
 *               type: object
 *               properties:
 *                 success:
 *                   type: boolean
 *                   example: true
 *                 message:
 *                   type: string
 *                   example: Admin created successfully
 *             example:
 *               success: true
 *               message: Admin created successfully
 *       400:
 *         description: Error de validación
 *         content:
 *           application/json:
 *             schema:
 *               type: object
 *             examples:
 *               fields_required:
 *                 summary: Campos requeridos faltantes
 *                 value: "name, lastname, email are required"
 *               email_exists:
 *                 summary: Correo ya registrado
 *                 value: "Correo ya esta registrado."
 *               smtp_error:
 *                 summary: Error enviando correo
 *                 value: "Hubo un error enviando el correo de confirmación"
 *       401:
 *         $ref: "#/components/responses/Unauthorized"
 *       403:
 *         $ref: "#/components/responses/Forbidden"
 */
routes.route("/create").post(createAdmin);

/**
 * @swagger
 * /admin/users:
 *   get:
 *     operationId: adminGetUsers
 *     tags: [Admin]
 *     summary: Listar administradores
 *     security:
 *       - bearerAuth: []
 *     responses:
 *       200:
 *         description: Lista de administradores obtenida correctamente
 *         content:
 *           application/json:
 *             schema:
 *               type: object
 *               required: [success, message, data]
 *               properties:
 *                 success:
 *                   type: boolean
 *                   example: true
 *                 message:
 *                   type: string
 *                   example: Users retrieved successfully
 *                 data:
 *                   type: array
 *                   items:
 *                     type: object
 *                     description: Objeto Admin con roles poblados
 *             example:
 *               success: true
 *               message: Users retrieved successfully
 *               data: []
 *       401:
 *         $ref: "#/components/responses/Unauthorized"
 *       403:
 *         $ref: "#/components/responses/Forbidden"
 */
routes.route("/users").get(getUsers);

/**
 * @swagger
 * /admin/users/{id}:
 *   get:
 *     operationId: adminGetUserById
 *     tags: [Admin]
 *     summary: Obtener administrador por ID
 *     security:
 *       - bearerAuth: []
 *     parameters:
 *       - in: path
 *         name: id
 *         required: true
 *         schema:
 *           type: string
 *     responses:
 *       200:
 *         description: Datos del administrador obtenidos correctamente
 *         content:
 *           application/json:
 *             schema:
 *               type: object
 *               required: [success, message, data]
 *               properties:
 *                 success:
 *                   type: boolean
 *                   example: true
 *                 message:
 *                   type: string
 *                   example: User retrieved successfully
 *                 data:
 *                   type: object
 *                   description: Objeto Admin con roles poblados
 *             example:
 *               success: true
 *               message: User retrieved successfully
 *               data:
 *                 _id: "507f1f77bcf86cd799439011"
 *                 name: Juan
 *                 lastname: Pérez
 *                 email: admin@example.com
 *       404:
 *         description: Administrador no encontrado
 *         content:
 *           application/json:
 *             schema:
 *               type: object
 *               properties:
 *                 success:
 *                   type: boolean
 *                   example: false
 *                 message:
 *                   type: string
 *                   example: User not found
 *                 code:
 *                   type: string
 *                   example: user_not_found
 *       401:
 *         $ref: "#/components/responses/Unauthorized"
 *       403:
 *         $ref: "#/components/responses/Forbidden"
 *   patch:
 *     operationId: adminEditUser
 *     tags: [Admin]
 *     summary: Editar administrador
 *     security:
 *       - bearerAuth: []
 *     parameters:
 *       - in: path
 *         name: id
 *         required: true
 *         schema:
 *           type: string
 *     requestBody:
 *       content:
 *         multipart/form-data:
 *           schema:
 *             type: object
 *             properties:
 *               name:
 *                 type: string
 *               lastname:
 *                 type: string
 *               email:
 *                 type: string
 *               roles:
 *                 type: array
 *                 items:
 *                   type: string
 *               status:
 *                 type: string
 *               profilePicture:
 *                 type: string
 *                 format: binary
 *     responses:
 *       200:
 *         description: Administrador actualizado correctamente
 *         content:
 *           application/json:
 *             schema:
 *               type: object
 *               properties:
 *                 success:
 *                   type: boolean
 *                   example: true
 *                 message:
 *                   type: string
 *                   example: User updated successfully
 *             example:
 *               success: true
 *               message: User updated successfully
 *       400:
 *         description: Error de validación
 *         content:
 *           application/json:
 *             schema:
 *               type: object
 *               properties:
 *                 success:
 *                   type: boolean
 *                   example: false
 *                 message:
 *                   type: string
 *                 code:
 *                   type: string
 *             examples:
 *               user_exists:
 *                 summary: Correo duplicado
 *                 value:
 *                   success: false
 *                   code: user_exists
 *                   message: "Error: Ya existe un registro con este correo electrónico (email@example.com)."
 *       404:
 *         description: Administrador no encontrado
 *         content:
 *           application/json:
 *             schema:
 *               type: object
 *               properties:
 *                 message:
 *                   type: string
 *                   example: User not found
 *       401:
 *         $ref: "#/components/responses/Unauthorized"
 *       403:
 *         $ref: "#/components/responses/Forbidden"
 */
routes
  .route("/users/:id")
  .get(getUserById)
  .patch(upload.single("profilePicture"), editUser);

routes.use(authorizeModules("all"));

/**
 * @swagger
 * /admin/generate-token:
 *   post:
 *     operationId: adminGenerateToken
 *     tags: [Admin]
 *     summary: Generar token de prueba
 *     security:
 *       - bearerAuth: []
 *     requestBody:
 *       content:
 *         application/json:
 *           schema:
 *             type: object
 *             properties:
 *               roles:
 *                 type: string
 *                 description: Módulos/roles para el token
 *     responses:
 *       200:
 *         description: Token generado correctamente
 *         content:
 *           application/json:
 *             schema:
 *               type: object
 *               required: [success, message, data]
 *               properties:
 *                 success:
 *                   type: boolean
 *                   example: true
 *                 message:
 *                   type: string
 *                   example: Token generated successfully
 *                 data:
 *                   type: object
 *                   properties:
 *                     token:
 *                       type: string
 *             example:
 *               success: true
 *               message: Token generated successfully
 *               data:
 *                 token: "eyJhbGciOiJIUzI1NiIs..."
 *       401:
 *         $ref: "#/components/responses/Unauthorized"
 *       403:
 *         $ref: "#/components/responses/Forbidden"
 */
routes.route("/generate-token").post(generateToken);

export default routes;
