/**
 * User Feature Routes - Authentication endpoints with AppKit integration
 * @module {{projectName}}/user-routes
 * @file src/api/features/user/user.route.ts
 */

import express from 'express';
import { errorClass } from '@voilajsx/appkit/error';
import { authClass } from '@voilajsx/appkit/auth';
import { userService } from './user.service.js';

// Initialize AppKit modules
const router = express.Router();
const error = errorClass.get();
const auth = authClass.get();

/**
 * Register a new user
 */
router.post('/register', error.asyncRoute(async (req, res) => {
  const requestId = req.requestMetadata?.requestId || 'unknown';

  try {
    const user = await userService.register(req.body);

    res.status(201).json({
      message: 'User registered successfully',
      user,
      requestId
    });

  } catch (err: any) {
    if (err.statusCode) {
      throw err;
    }
    res.status(err.statusCode || 500).json({
      error: err.message || 'Registration failed',
      requestId
    });
  }
}));

/**
 * Login user and generate JWT token
 */
router.post('/login', error.asyncRoute(async (req, res) => {
  const requestId = req.requestMetadata?.requestId || 'unknown';
  const { email, password } = req.body;

  try {
    const result = await userService.login(email, password);

    res.json({
      message: 'Login successful',
      ...result,
      requestId
    });

  } catch (err: any) {
    if (err.statusCode) {
      throw err;
    }
    res.status(err.statusCode || 500).json({
      error: err.message || 'Login failed',
      requestId
    });
  }
}));

/**
 * Request password reset
 */
router.post('/forgot-password', error.asyncRoute(async (req, res) => {
  const requestId = req.requestMetadata?.requestId || 'unknown';
  const { email } = req.body;

  try {
    await userService.forgotPassword(email);

    // Always return success to prevent email enumeration
    res.json({
      message: 'If an account with that email exists, a password reset link has been sent',
      requestId
    });

  } catch (err: any) {
    // Still return success to prevent email enumeration
    res.json({
      message: 'If an account with that email exists, a password reset link has been sent',
      requestId
    });
  }
}));

/**
 * Reset password with token
 */
router.post('/reset-password', error.asyncRoute(async (req, res) => {
  const requestId = req.requestMetadata?.requestId || 'unknown';
  const { token, newPassword } = req.body;

  try {
    await userService.resetPassword(token, newPassword);

    res.json({
      message: 'Password reset successfully',
      requestId
    });

  } catch (err: any) {
    if (err.statusCode) {
      throw err;
    }
    res.status(err.statusCode || 500).json({
      error: err.message || 'Password reset failed',
      requestId
    });
  }
}));

/**
 * Get user profile by ID
 */
router.get('/profile',
  auth.requireLoginToken(),
  error.asyncRoute(async (req, res) => {
    const requestId = req.requestMetadata?.requestId || 'unknown';

    try {
      const authenticatedUser = auth.user(req as any);

      if (!authenticatedUser) {
        throw error.serverError('Authentication failed - user not found in request');
      }

      const user = await userService.getProfile(authenticatedUser.userId as number);

      res.json({
        message: 'Profile retrieved successfully',
        user,
        authenticatedAs: {
          userId: authenticatedUser.userId,
          role: authenticatedUser.role,
          level: authenticatedUser.level
        },
        requestId
      });

    } catch (err: any) {
      if (err.statusCode) {
        throw err;
      }
      res.status(err.statusCode || 500).json({
        error: err.message || 'Failed to get profile',
        requestId
      });
    }
  })
);

/**
 * Update user profile
 */
router.put('/profile',
  auth.requireLoginToken(),
  error.asyncRoute(async (req, res) => {
    const requestId = req.requestMetadata?.requestId || 'unknown';
    const { name, phone } = req.body;

    try {
      const authenticatedUser = auth.user(req as any);

      if (!authenticatedUser) {
        throw error.serverError('Authentication failed - user not found in request');
      }

      const user = await userService.updateProfile(authenticatedUser.userId as number, { name, phone });

      res.json({
        message: 'Profile updated successfully',
        user,
        requestId
      });

    } catch (err: any) {
      if (err.statusCode) {
        throw err;
      }
      res.status(err.statusCode || 500).json({
        error: err.message || 'Failed to update profile',
        requestId
      });
    }
  })
);

/**
 * Change user password
 */
router.post('/change-password',
  auth.requireLoginToken(),
  error.asyncRoute(async (req, res) => {
    const requestId = req.requestMetadata?.requestId || 'unknown';
    const { currentPassword, newPassword } = req.body;

    try {
      const authenticatedUser = auth.user(req as any);

      if (!authenticatedUser) {
        throw error.serverError('Authentication failed - user not found in request');
      }

      await userService.changePassword(authenticatedUser.userId as number, currentPassword, newPassword);

      res.json({
        message: 'Password changed successfully',
        requestId
      });

    } catch (err: any) {
      if (err.statusCode) {
        throw err;
      }
      res.status(err.statusCode || 500).json({
        error: err.message || 'Password change failed',
        requestId
      });
    }
  })
);

/**
 * Get all users (admin/moderator only)
 */
router.get('/all',
  auth.requireLoginToken(),
  auth.requireUserRoles(['admin.tenant', 'admin.org', 'admin.system']),
  error.asyncRoute(async (req, res) => {
    const requestId = req.requestMetadata?.requestId || 'unknown';
    const { tenantId } = req.query;

    try {
      const users = await userService.getAllUsers(tenantId as string);

      res.json({
        message: 'Users retrieved successfully',
        users,
        count: users.length,
        requestId
      });

    } catch (err: any) {
      if (err.statusCode) {
        throw err;
      }
      res.status(err.statusCode || 500).json({
        error: err.message || 'Failed to get users',
        requestId
      });
    }
  })
);

/**
 * Get users list (moderator+ access)
 */
router.get('/list',
  auth.requireLoginToken(),
  auth.requireUserRoles(['moderator.review', 'moderator.approve', 'moderator.manage', 'admin.tenant', 'admin.org', 'admin.system']),
  error.asyncRoute(async (req, res) => {
    const requestId = req.requestMetadata?.requestId || 'unknown';
    const { tenantId } = req.query;

    try {
      const users = await userService.getAllUsers(tenantId as string);

      res.json({
        message: 'Users retrieved successfully',
        users,
        count: users.length,
        requestId
      });

    } catch (err: any) {
      if (err.statusCode) {
        throw err;
      }
      res.status(err.statusCode || 500).json({
        error: err.message || 'Failed to get users',
        requestId
      });
    }
  })
);

/**
 * Update user by admin (admin only)
 */
router.put('/list/:id',
  auth.requireLoginToken(),
  auth.requireUserRoles(['admin.tenant', 'admin.org', 'admin.system']),
  error.asyncRoute(async (req, res) => {
    const requestId = req.requestMetadata?.requestId || 'unknown';
    const userId = parseInt(req.params.id);

    try {
      const user = await userService.updateUser(userId, req.body);

      res.json({
        message: 'User updated successfully',
        user,
        requestId
      });

    } catch (err: any) {
      if (err.statusCode) {
        throw err;
      }
      res.status(err.statusCode || 500).json({
        error: err.message || 'Failed to update user',
        requestId
      });
    }
  })
);

/**
 * Delete user (admin only)
 */
router.delete('/list/:id',
  auth.requireLoginToken(),
  auth.requireUserRoles(['admin.tenant', 'admin.org', 'admin.system']),
  error.asyncRoute(async (req, res) => {
    const requestId = req.requestMetadata?.requestId || 'unknown';
    const userId = parseInt(req.params.id);

    try {
      const authenticatedUser = auth.user(req as any);

      // Prevent self-deletion
      if (authenticatedUser?.userId === userId) {
        return res.status(400).json({
          error: 'Operation not allowed',
          message: 'Cannot delete your own account',
          requestId
        });
      }

      await userService.deleteUser(userId);

      res.json({
        message: 'User deleted successfully',
        requestId
      });

    } catch (err: any) {
      if (err.statusCode) {
        throw err;
      }
      res.status(err.statusCode || 500).json({
        error: err.message || 'Failed to delete user',
        requestId
      });
    }
  })
);

/**
 * Test route to verify discovery and functionality
 */
router.get('/test', (_req, res) => {
  res.json({
    message: 'User routes are working!',
    timestamp: new Date().toISOString(),
    status: 'success'
  });
});

export default router;