import express from 'express';
import { AuthService } from '../services/auth.service';
import { authenticateToken, blacklistToken } from '../middleware/auth';
import config from '../config';

// Temporary mock implementations
const prisma = {
  user: {
    findUnique: async (params: any): Promise<any> => {
      return {
        id: 'mock-user-id',
        email: 'mock@example.com',
        firstName: 'Mock',
        lastName: 'User',
        subscription: 'FREE',
        isActive: true,
        passwordHash: '$2b$12$mockhashedpassword',
        createdAt: new Date(),
        usageMetrics: {
          pagesCloned: 0,
          storageUsed: 0,
          apiCalls: 0,
          lastReset: new Date()
        }
      };
    },
    create: async (params: any): Promise<any> => ({
      id: 'mock-user-id',
      email: params.data.email,
      firstName: params.data.firstName,
      lastName: params.data.lastName,
      subscription: 'FREE',
      createdAt: new Date()
    }),
    update: async (params: any): Promise<any> => ({
      id: 'mock-user-id',
      email: 'mock@example.com',
      firstName: 'Mock',
      lastName: 'User',
      subscription: 'FREE',
      updatedAt: new Date()
    })
  },
  userSession: {
    create: async (params: any): Promise<any> => ({ id: 'mock-session' }),
    deleteMany: async (params: any): Promise<any> => ({ count: 0 })
  }
};

const validateUserRegistration = (data: any) => {
  if (!data.email || !data.password) {
    throw new Error('Email and password are required');
  }
  return data;
};

const validateUserLogin = (data: any) => {
  if (!data.email || !data.password) {
    throw new Error('Email and password are required');
  }
  return data;
};

const router = express.Router();

// Register new user
router.post('/register', async (req, res, next) => {
  try {
    // Validate input
    const validatedData = validateUserRegistration(req.body);
    
    // Check if user already exists
    const existingUser = await prisma.user.findUnique({
      where: { email: validatedData.email }
    });
    
    if (existingUser) {
      return res.status(400).json({
        success: false,
        error: 'User with this email already exists',
        code: 'USER_EXISTS'
      });
    }
    
    // Hash password
    const passwordHash = await AuthService.hashPassword(validatedData.password);
    
    // Create user
    const user = await prisma.user.create({
      data: {
        email: validatedData.email,
        passwordHash,
        firstName: validatedData.firstName,
        lastName: validatedData.lastName,
        subscription: 'FREE',
        usageMetrics: {
          create: {
            pagesCloned: 0,
            storageUsed: 0,
            apiCalls: 0
          }
        }
      },
      select: {
        id: true,
        email: true,
        firstName: true,
        lastName: true,
        subscription: true,
        createdAt: true
      }
    });
    
    // Generate JWT token pair
    const tokenPair = AuthService.generateTokenPair(
      user.id,
      user.email,
      user.subscription
    );
    
    res.status(201).json({
      success: true,
      data: {
        user,
        ...tokenPair
      },
      message: 'User registered successfully'
    });
  } catch (error) {
    next(error);
  }
});

// Login user
router.post('/login', async (req, res, next) => {
  try {
    // Validate input
    const validatedData = validateUserLogin(req.body);
    
    // Find user
    const user = await prisma.user.findUnique({
      where: { email: validatedData.email },
      select: {
        id: true,
        email: true,
        passwordHash: true,
        firstName: true,
        lastName: true,
        subscription: true,
        isActive: true
      }
    });
    
    if (!user || !user.isActive) {
      return res.status(401).json({
        success: false,
        error: 'Invalid email or password',
        code: 'INVALID_CREDENTIALS'
      });
    }
    
    // Verify password
    const isValidPassword = await AuthService.verifyPassword(validatedData.password, user.passwordHash);
    
    if (!isValidPassword) {
      return res.status(401).json({
        success: false,
        error: 'Invalid email or password',
        code: 'INVALID_CREDENTIALS'
      });
    }
    
    // Generate JWT token pair
    const tokenPair = AuthService.generateTokenPair(
      user.id,
      user.email,
      user.subscription
    );
    
    // Create session record
    await prisma.userSession.create({
      data: {
        userId: user.id,
        token: tokenPair.accessToken,
        expiresAt: new Date(Date.now() + tokenPair.expiresIn * 1000)
      }
    });
    
    res.json({
      success: true,
      data: {
        user: {
          id: user.id,
          email: user.email,
          firstName: user.firstName,
          lastName: user.lastName,
          subscription: user.subscription
        },
        ...tokenPair
      },
      message: 'Login successful'
    });
  } catch (error) {
    next(error);
  }
});

// Logout user
router.post('/logout', authenticateToken, async (req, res, next) => {
  try {
    const authHeader = req.headers.authorization;
    const token = authHeader && authHeader.split(' ')[1];
    
    if (token) {
      // Blacklist the access token
      blacklistToken(token);
      
      // Remove session from database
      await prisma.userSession.deleteMany({
        where: {
          userId: req.user!.id,
          token
        }
      });
    }
    
    res.json({
      success: true,
      message: 'Logout successful'
    });
  } catch (error) {
    next(error);
  }
});

// Refresh token endpoint
router.post('/refresh', async (req, res, next) => {
  try {
    const { refreshToken } = req.body;
    
    if (!refreshToken) {
      return res.status(400).json({
        success: false,
        error: 'Refresh token is required',
        code: 'VALIDATION_ERROR'
      });
    }
    
    // Generate new token pair using refresh token
    const newTokenPair = AuthService.refreshAccessToken(refreshToken);
    
    res.json({
      success: true,
      data: newTokenPair,
      message: 'Token refreshed successfully'
    });
  } catch (error) {
    return res.status(401).json({
      success: false,
      error: 'Invalid or expired refresh token',
      code: 'INVALID_REFRESH_TOKEN'
    });
  }
});

// Logout from all devices
router.post('/logout-all', authenticateToken, async (req, res, next) => {
  try {
    // Revoke all tokens for the user
    AuthService.revokeAllUserTokens(req.user!.id);
    
    // Remove all sessions from database
    await prisma.userSession.deleteMany({
      where: { userId: req.user!.id }
    });
    
    res.json({
      success: true,
      message: 'Logged out from all devices successfully'
    });
  } catch (error) {
    next(error);
  }
});

// Get current user profile
router.get('/me', authenticateToken, async (req, res, next) => {
  try {
    const user = await prisma.user.findUnique({
      where: { id: req.user!.id },
      select: {
        id: true,
        email: true,
        firstName: true,
        lastName: true,
        avatar: true,
        subscription: true,
        emailVerified: true,
        createdAt: true,
        usageMetrics: {
          select: {
            pagesCloned: true,
            storageUsed: true,
            apiCalls: true,
            lastReset: true
          }
        }
      }
    });
    
    if (!user) {
      return res.status(404).json({
        success: false,
        error: 'User not found',
        code: 'USER_NOT_FOUND'
      });
    }
    
    res.json({
      success: true,
      data: user
    });
  } catch (error) {
    next(error);
  }
});

// Update user profile
router.patch('/me', authenticateToken, async (req, res, next) => {
  try {
    const { firstName, lastName, avatar } = req.body;
    
    const updatedUser = await prisma.user.update({
      where: { id: req.user!.id },
      data: {
        ...(firstName && { firstName }),
        ...(lastName && { lastName }),
        ...(avatar && { avatar })
      },
      select: {
        id: true,
        email: true,
        firstName: true,
        lastName: true,
        avatar: true,
        subscription: true,
        updatedAt: true
      }
    });
    
    res.json({
      success: true,
      data: updatedUser,
      message: 'Profile updated successfully'
    });
  } catch (error) {
    next(error);
  }
});

// Change password
router.post('/change-password', authenticateToken, async (req, res, next) => {
  try {
    const { currentPassword, newPassword } = req.body;
    
    if (!currentPassword || !newPassword) {
      return res.status(400).json({
        success: false,
        error: 'Current password and new password are required',
        code: 'VALIDATION_ERROR'
      });
    }
    
    if (newPassword.length < 8) {
      return res.status(400).json({
        success: false,
        error: 'New password must be at least 8 characters long',
        code: 'VALIDATION_ERROR'
      });
    }
    
    // Get current user with password
    const user = await prisma.user.findUnique({
      where: { id: req.user!.id },
      select: { passwordHash: true }
    });
    
    if (!user) {
      return res.status(404).json({
        success: false,
        error: 'User not found',
        code: 'USER_NOT_FOUND'
      });
    }
    
    // Verify current password
    const isValidPassword = await AuthService.verifyPassword(currentPassword, user.passwordHash);
    
    if (!isValidPassword) {
      return res.status(401).json({
        success: false,
        error: 'Current password is incorrect',
        code: 'INVALID_CREDENTIALS'
      });
    }
    
    // Hash new password
    const newPasswordHash = await AuthService.hashPassword(newPassword);
    
    // Update password
    await prisma.user.update({
      where: { id: req.user!.id },
      data: { passwordHash: newPasswordHash }
    });
    
    // Invalidate all existing sessions
    AuthService.revokeAllUserTokens(req.user!.id);
    await prisma.userSession.deleteMany({
      where: { userId: req.user!.id }
    });
    
    res.json({
      success: true,
      message: 'Password changed successfully. Please log in again.'
    });
  } catch (error) {
    next(error);
  }
});

export default router;
// Get active sessions
router.get('/sessions', authenticateToken, async (req, res, next) => {
  try {
    const sessions = AuthService.getUserActiveSessions(req.user!.id);
    
    res.json({
      success: true,
      data: {
        sessions: sessions.map(session => ({
          sessionId: session.sessionId,
          expiresAt: session.expiresAt,
          isCurrentSession: false // TODO: Identify current session
        }))
      }
    });
  } catch (error) {
    next(error);
  }
});

// Revoke specific session
router.delete('/sessions/:sessionId', authenticateToken, async (req, res, next) => {
  try {
    const { sessionId } = req.params;
    
    // Revoke specific session
    AuthService.revokeUserSession(req.user!.id, sessionId);
    
    res.json({
      success: true,
      message: 'Session revoked successfully'
    });
  } catch (error) {
    next(error);
  }
});

// Validate token endpoint (for debugging/testing)
router.post('/validate', async (req, res, next) => {
  try {
    const { token } = req.body;
    
    if (!token) {
      return res.status(400).json({
        success: false,
        error: 'Token is required',
        code: 'VALIDATION_ERROR'
      });
    }
    
    const payload = AuthService.verifyToken(token);
    
    res.json({
      success: true,
      data: {
        valid: true,
        payload: {
          userId: payload.userId,
          email: payload.email,
          subscription: payload.subscription,
          type: payload.type,
          sessionId: payload.sessionId,
          expiresAt: new Date(payload.exp! * 1000)
        }
      }
    });
  } catch (error) {
    res.json({
      success: true,
      data: {
        valid: false,
        error: error instanceof Error ? error.message : 'Invalid token'
      }
    });
  }
});