import express from 'express';
import bcrypt from 'bcryptjs';
import jwt from 'jsonwebtoken';
import { PrismaClient } from '@prisma/client';
import { sendEmail } from '../services/email';
import multer from 'multer';
import fs from 'fs';
import path from 'path';
import crypto from 'crypto';

const router = express.Router();
const prisma = new PrismaClient();
const JWT_SECRET = process.env.JWT_SECRET || 'ahri_super_secret_key_change_in_production';
const normalizeEmail = (email: string) => email.trim().toLowerCase();
const generateTemporaryPassword = () => {
  const alphabet = 'ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz23456789';
  const suffix = Array.from({ length: 10 }, () => alphabet[crypto.randomInt(alphabet.length)]).join('');
  return `AHRI-${suffix}`;
};

// Multer Setup for Profile Photos
const uploadDirectory = path.join(process.cwd(), 'uploads');
fs.mkdirSync(uploadDirectory, { recursive: true });

const storage = multer.diskStorage({
  destination: uploadDirectory,
  filename: (req, file, cb) => {
    cb(null, `${Date.now()}-${file.originalname}`);
  }
});

const upload = multer({ 
  storage,
  limits: { fileSize: 5 * 1024 * 1024 }, // 5MB limit
  fileFilter: (req, file, cb) => {
    const filetypes = /jpeg|jpg|png|webp/;
    const mimetype = filetypes.test(file.mimetype);
    const extname = filetypes.test(path.extname(file.originalname).toLowerCase());
    if (mimetype && extname) return cb(null, true);
    cb(new Error('Only images are allowed'));
  }
});

const handlePhotoUpload = (req: express.Request, res: express.Response, next: express.NextFunction) => {
  upload.single('profilePhoto')(req, res, (error) => {
    if (!error) {
      return next();
    }

    if (error instanceof multer.MulterError) {
      if (error.code === 'LIMIT_FILE_SIZE') {
        return res.status(400).json({ error: 'Profile photo must be 5MB or smaller.' });
      }

      return res.status(400).json({ error: error.message });
    }

    const message = error instanceof Error ? error.message : 'Failed to upload profile photo';
    return res.status(400).json({ error: message });
  });
};

const getUserWhereClause = (body: { userId?: string; email?: string }) => {
  const userId = body.userId?.trim();
  const email = normalizeEmail(body.email || '');

  if (userId) {
    return { id: userId };
  }

  if (email) {
    return { email };
  }

  return null;
};

// Upload profile photo endpoint
router.post('/upload-photo', handlePhotoUpload, (req, res) => {
  if (!req.file) {
    return res.status(400).json({ error: 'No file uploaded' });
  }
  const photoUrl = `/uploads/${req.file.filename}`;
  res.json({ photoUrl });
});

// Public self-signup is disabled — accounts are created by admins only.
router.post('/signup', (_req, res) => {
  res.status(403).json({ error: 'Public registration is disabled. Please contact an administrator to create an account.' });
});

// Login Endpoint
router.post('/login', async (req, res) => {
  try {
    const email = normalizeEmail(req.body.email || '');
    const { password } = req.body;
    console.log('Login attempt for:', email);

    const user = await prisma.user.findUnique({ where: { email } });
    if (!user) {
      console.log('User not found in DB:', email);
      return res.status(401).json({ error: 'Invalid email or password' });
    }

    const isMatch = await bcrypt.compare(password, user.password);
    console.log('Password match:', isMatch);
    
    if (!isMatch) {
      return res.status(401).json({ error: 'Invalid email or password' });
    }

    const disableEmailVerification = process.env.DISABLE_EMAIL_VERIFICATION === 'true';
    if (!user.isVerified && !disableEmailVerification) {
      console.log('User not verified:', email);
      return res.status(403).json({ error: 'Please verify your email before logging in. Check your inbox for the verification link.' });
    }

    // Generate JWT
    const token = jwt.sign(
      { id: user.id, role: user.role, email: user.email },
      JWT_SECRET,
      { expiresIn: '1d' }
    );

    res.json({
      message: 'Login successful',
      token,
      user: {
        id: user.id,
        fullName: user.fullName,
        email: user.email,
        role: user.role,
        organization: user.organization,
        profilePhoto: user.profilePhoto,
      }
    });

  } catch (error) {
    console.error('Login error:', error);
    res.status(500).json({ error: 'Internal server error during login' });
  }
});

// Get unverified user count (for navbar badge)
router.get('/unverified-count', async (req, res) => {
  try {
    const count = await prisma.user.count({ where: { isVerified: false } });
    res.json({ count });
  } catch (error) {
    console.error('Unverified count error:', error);
    res.status(500).json({ error: 'Failed to fetch count' });
  }
});

// Get All Users (Admin/Officer only)
router.get('/users', async (req, res) => {
  try {
    const users = await prisma.user.findMany({
      select: {
        id: true,
        fullName: true,
        email: true,
        role: true,
        organization: true,
        directorate: true,
        department: true,
        phoneNumber: true,
        isVerified: true,
        createdAt: true
      },
      orderBy: { createdAt: 'desc' }
    });
    res.json(users);
  } catch (error) {
    console.error('Fetch users error:', error);
    res.status(500).json({ error: 'Failed to fetch users' });
  }
});

// Forgot Password Endpoint
router.post('/forgot-password', async (req, res) => {
  try {
    const email = normalizeEmail(req.body.email || '');
    if (!email) return res.status(400).json({ error: 'Email required' });

    const user = await prisma.user.findUnique({ where: { email } });
    if (!user) return res.status(404).json({ error: 'User not found' });

    // For safety, generate a new default-format password
    const names = user.fullName.split(' ');
    const firstName = names[0] || 'U';
    const lastName = names[1] || 'N';
    const generatedPassword = (firstName[0] + lastName[0] + '@' + user.phoneNumber.slice(-4)).toUpperCase();

    const salt = await bcrypt.genSalt(10);
    const hashedPassword = await bcrypt.hash(generatedPassword, salt);

    await prisma.user.update({
      where: { id: user.id },
      data: { password: hashedPassword }
    });

    await sendEmail(
      email,
      'Your AHRI Meeting Room Password',
      `<h1>Password Resent</h1>
       <p>Registration is successfully on AHRI training room management system.</p>
       <p>Your password is: <strong>${generatedPassword}</strong></p>
       <p>Please log in and change your password in your profile settings if needed.</p>`
    );

    res.json({ message: 'Password resent successfully!' });
  } catch (error) {
    console.error('Forgot password error:', error);
    res.status(500).json({ error: 'Failed to resend password' });
  }
});

// Verify Email Endpoint
router.get('/verify', async (req, res) => {
  try {
    const email = normalizeEmail(String(req.query.email || ''));
    if (!email) return res.status(400).json({ error: 'Email missing' });
    
    await prisma.user.update({
      where: { email },
      data: { isVerified: true }
    });
    
    res.json({ message: 'Email verified successfully!' });
  } catch (error) {
    console.error('Verification error:', error);
    res.status(500).json({ error: 'Verification failed' });
  }
});

// Admin Password Reset Endpoint
router.post('/admin/reset-password', async (req, res) => {
  try {
    const { adminUserId } = req.body; 
    const targetEmail = normalizeEmail(req.body.targetEmail || '');

    if (!adminUserId || !targetEmail) return res.status(400).json({ error: 'Missing parameters' });

    const admin = await prisma.user.findUnique({ where: { id: adminUserId } });
    if (!admin || admin.role !== 'SYS_ADMIN') {
      return res.status(403).json({ error: 'Unauthorized. Only Sys Admins can perform this action.' });
    }

    const targetUser = await prisma.user.findUnique({ where: { email: targetEmail } });
    if (!targetUser || targetUser.role === 'SYS_ADMIN') {
      return res.status(404).json({ error: 'Target user or officer not found, or this account cannot be reset here.' });
    }

    const newPassword = generateTemporaryPassword();
    const salt = await bcrypt.genSalt(10);
    const hashedPassword = await bcrypt.hash(newPassword, salt);

    await prisma.user.update({
      where: { email: targetEmail },
      data: { password: hashedPassword }
    });

    const emailSent = await sendEmail(
      targetEmail,
      'Your AHRI Meeting Room Password Has Been Reset',
      `<div style="font-family: sans-serif; max-width: 600px; margin: auto; border: 1px solid #eee; padding: 20px;">
        <h1 style="color: #006039;">Password Reset</h1>
        <p>Dear ${targetUser.fullName},</p>
        <p>Your AHRI Training Room Management System password was reset by the system administrator.</p>
        <p>Your temporary password is:</p>
        <div style="font-size: 22px; font-weight: bold; letter-spacing: 1px; background: #f3f4f6; border: 1px solid #e5e7eb; padding: 14px; border-radius: 6px; text-align: center;">
          ${newPassword}
        </div>
        <p>Please log in with this temporary password and change it inside your account settings.</p>
        <hr style="border: none; border-top: 1px solid #eee; margin-top: 30px;"/>
        <p style="font-size: 12px; color: #666;">AHRI Training Room Management System</p>
      </div>`
    );

    res.json({
      message: emailSent
        ? 'Password reset successfully and emailed to the user.'
        : 'Password reset successfully. Email could not be sent, so share the generated password manually.',
      generatedPassword: newPassword,
      emailSent,
      targetUser: {
        id: targetUser.id,
        fullName: targetUser.fullName,
        email: targetUser.email,
        role: targetUser.role
      }
    });
  } catch (error) {
    console.error('Reset password error:', error);
    res.status(500).json({ error: 'Server error during password reset' });
  }
});

// Admin Create User (allows setting role)
router.post('/admin/create-user', async (req, res) => {
  try {
    const { adminUserId, fullName, organization, directorate, department, sex, password, phoneNumber, role, profilePhoto } = req.body;
    const email = normalizeEmail(req.body.email || '');

    const admin = await prisma.user.findUnique({ where: { id: adminUserId } });
    if (!admin || admin.role !== 'SYS_ADMIN') {
      return res.status(403).json({ error: 'Unauthorized. Only Sys Admins can create officers.' });
    }

    const existingUser = await prisma.user.findUnique({ where: { email } });
    if (existingUser) return res.status(400).json({ error: 'Email already exists' });

    const salt = await bcrypt.genSalt(10);
    const hashedPassword = await bcrypt.hash(password || 'temp123', salt);

    const newUser = await prisma.user.create({
      data: {
        fullName,
        organization: organization || 'AHRI',
        directorate,
        department,
        sex,
        email,
        password: hashedPassword,
        phoneNumber,
        profilePhoto: profilePhoto || null,
        role: role || 'OFFICER',
        isVerified: true, // Officers created by admin are pre-verified
      },
    });

    await sendEmail(
      email,
      'Your Officer Account for AHRI Meeting Rooms',
      `<h1>Account Created</h1><p>An officer account has been created for you. Your temporary password is: <strong>${password || 'temp123'}</strong></p><p>Please log in and change your password.</p>`
    );

    res.status(201).json(newUser);
  } catch (error) {
    console.error('Admin create user error:', error);
    res.status(500).json({ error: 'Failed to create user account' });
  }
});

// Admin Delete User Endpoint
router.post('/admin/delete-user', async (req, res) => {
  console.log('Admin Delete User Requested:', req.body);
  try {
    const { adminUserId, targetUserId } = req.body;

    if (!adminUserId || !targetUserId) {
      return res.status(400).json({ error: 'Missing parameters' });
    }

    if (adminUserId === targetUserId) {
      return res.status(400).json({ error: 'You cannot delete your own account' });
    }

    const admin = await prisma.user.findUnique({ where: { id: adminUserId } });
    if (!admin || admin.role !== 'SYS_ADMIN') {
      return res.status(403).json({ error: 'Unauthorized. Only Sys Admins can delete users.' });
    }

    // Delete associated records first to avoid foreign key constraints.
    await prisma.booking.deleteMany({ where: { userId: targetUserId } });
    await prisma.meeting.deleteMany({ where: { adminId: targetUserId } });
    await prisma.meetingParticipant.updateMany({
      where: { userId: targetUserId },
      data: { userId: null }
    });

    await prisma.user.delete({ where: { id: targetUserId } });

    res.json({ message: 'User deleted successfully' });
  } catch (error: any) {
    console.error('Admin delete user error:', error);
    res.status(500).json({ error: 'Failed to delete user account' });
  }
});

// Change Own Password
router.post('/change-password', async (req, res) => {
  try {
    const { newPassword } = req.body;
    const userWhere = getUserWhereClause(req.body);
    if (!userWhere || !newPassword) return res.status(400).json({ error: 'Missing parameters' });

    const salt = await bcrypt.genSalt(10);
    const hashedPassword = await bcrypt.hash(newPassword, salt);

    await prisma.user.update({
      where: userWhere,
      data: { password: hashedPassword }
    });

    res.json({ message: 'Password updated successfully!' });
  } catch (error: any) {
    console.error('Change password error:', error);
    if (error?.code === 'P2025') {
      return res.status(404).json({ error: 'Account not found. Please sign in again and retry.' });
    }
    res.status(500).json({ error: 'Failed to update password' });
  }
});

// Update Profile Photo Endpoint
router.post('/update-profile-photo', async (req, res) => {
  try {
    const { photoUrl } = req.body;
    const userWhere = getUserWhereClause(req.body);
    if (!userWhere || !photoUrl) return res.status(400).json({ error: 'Missing parameters' });

    await prisma.user.update({
      where: userWhere,
      data: { profilePhoto: photoUrl }
    });

    res.json({ message: 'Profile photo updated successfully!', photoUrl });
  } catch (error: any) {
    console.error('Update profile error:', error);
    if (error?.code === 'P2025') {
      return res.status(404).json({ error: 'Account not found. Please sign in again and retry.' });
    }
    res.status(500).json({ error: 'Failed to update profile photo' });
  }
});

export default router;
