import { Router } from 'express';
import { prisma } from '../config/database.js';
import { authenticate } from '../middleware/auth.js';
import { upload } from '../middleware/upload.js';
import { validate } from '../middleware/validate.js';
import { hashPassword, comparePassword } from '../utils/password.js';
import { AppError } from '../middleware/errorHandler.js';
import { updateProfileSchema, updateSettingsSchema, deleteAccountSchema } from '../validators/user.js';

const router = Router();

const userSelect = {
  id: true, email: true, fullName: true, nickname: true, avatar: true,
  phone: true, location: true, bio: true, rating: true, ratingCount: true,
  showEmail: true, showPhone: true, showLocation: true, showOnline: true, showRating: true,
  createdAt: true,
};

// --- Avatar upload ---
router.post('/avatar', authenticate, upload.single('avatar'), async (req, res, next) => {
  try {
    const file = req.file;
    if (!file) throw new AppError(400, 'No file uploaded');

    const user = await prisma.user.update({
      where: { id: req.userId },
      data: { avatar: `/uploads/${file.filename}` },
      select: userSelect,
    });
    res.json(user);
  } catch (error) {
    next(error);
  }
});

// --- Settings ---
router.get('/settings', authenticate, async (req, res, next) => {
  try {
    const user = await prisma.user.findUnique({
      where: { id: req.userId },
      select: {
        showEmail: true, showPhone: true, showLocation: true,
        showOnline: true, showRating: true,
        notifNewOffer: true, notifMessages: true, notifItemSold: true,
        notifFavorites: true, notifEmail: true, marketingEmail: true,
        twoFactorEnabled: true,
      },
    });
    if (!user) throw new AppError(404, 'User not found');
    res.json(user);
  } catch (error) {
    next(error);
  }
});

router.put('/settings', authenticate, validate(updateSettingsSchema), async (req, res, next) => {
  try {
    const user = await prisma.user.update({
      where: { id: req.userId },
      data: req.body,
      select: {
        showEmail: true, showPhone: true, showLocation: true,
        showOnline: true, showRating: true,
        notifNewOffer: true, notifMessages: true, notifItemSold: true,
        notifFavorites: true, notifEmail: true, marketingEmail: true,
        twoFactorEnabled: true,
      },
    });
    res.json(user);
  } catch (error) {
    next(error);
  }
});

// --- Sessions ---
router.get('/sessions', authenticate, async (req, res, next) => {
  try {
    const sessions = await prisma.session.findMany({
      where: { userId: req.userId },
      select: { id: true, userAgent: true, ipAddress: true, createdAt: true, expiresAt: true },
      orderBy: { createdAt: 'desc' },
    });
    res.json(sessions);
  } catch (error) {
    next(error);
  }
});

// --- Account deletion ---
router.delete('/account', authenticate, validate(deleteAccountSchema), async (req, res, next) => {
  try {
    const { password } = req.body;
    const user = await prisma.user.findUnique({ where: { id: req.userId } });
    if (!user) throw new AppError(404, 'User not found');

    const valid = await comparePassword(password, user.passwordHash);
    if (!valid) throw new AppError(400, 'Password is incorrect');

    await prisma.session.deleteMany({ where: { userId: req.userId } });
    await prisma.user.update({
      where: { id: req.userId },
      data: { isActive: false },
    });

    res.clearCookie('refreshToken');
    res.json({ message: 'Account deactivated' });
  } catch (error) {
    next(error);
  }
});

// --- Profile ---
router.get('/profile', authenticate, async (req, res, next) => {
  try {
    const user = await prisma.user.findUnique({ where: { id: req.userId }, select: userSelect });
    if (!user) throw new AppError(404, 'User not found');
    res.json(user);
  } catch (error) {
    next(error);
  }
});

router.put('/profile', authenticate, validate(updateProfileSchema), async (req, res, next) => {
  try {
    const user = await prisma.user.update({
      where: { id: req.userId },
      data: req.body,
      select: userSelect,
    });
    res.json(user);
  } catch (error) {
    next(error);
  }
});

// --- Password ---
router.put('/password', authenticate, async (req, res, next) => {
  try {
    const { currentPassword, newPassword } = req.body;
    if (!currentPassword || !newPassword) throw new AppError(400, 'Both current and new passwords are required');
    if (newPassword.length < 8) throw new AppError(400, 'New password must be at least 8 characters');

    const user = await prisma.user.findUnique({ where: { id: req.userId } });
    if (!user) throw new AppError(404, 'User not found');

    const valid = await comparePassword(currentPassword, user.passwordHash);
    if (!valid) throw new AppError(400, 'Current password is incorrect');

    const passwordHash = await hashPassword(newPassword);
    await prisma.user.update({ where: { id: req.userId }, data: { passwordHash } });

    res.json({ message: 'Password updated' });
  } catch (error) {
    next(error);
  }
});

// --- Block/Unblock ---
router.post('/:id/block', authenticate, async (req, res, next) => {
  try {
    if (req.params.id === req.userId) throw new AppError(400, 'Cannot block yourself');

    const target = await prisma.user.findUnique({ where: { id: req.params.id } });
    if (!target) throw new AppError(404, 'User not found');

    const existing = await prisma.blockedUser.findUnique({
      where: { blockerId_blockedId: { blockerId: req.userId!, blockedId: req.params.id } },
    });
    if (existing) throw new AppError(409, 'User already blocked');

    await prisma.blockedUser.create({
      data: { blockerId: req.userId!, blockedId: req.params.id },
    });
    res.json({ message: 'User blocked' });
  } catch (error) {
    next(error);
  }
});

router.delete('/:id/block', authenticate, async (req, res, next) => {
  try {
    const existing = await prisma.blockedUser.findUnique({
      where: { blockerId_blockedId: { blockerId: req.userId!, blockedId: req.params.id } },
    });
    if (!existing) throw new AppError(404, 'Block not found');

    await prisma.blockedUser.delete({ where: { id: existing.id } });
    res.json({ message: 'User unblocked' });
  } catch (error) {
    next(error);
  }
});

// --- Public profile (must be LAST due to /:id param) ---
router.get('/:id', async (req, res, next) => {
  try {
    const user = await prisma.user.findUnique({
      where: { id: req.params.id },
      select: {
        ...userSelect,
        _count: { select: { listings: { where: { status: 'ACTIVE' } } } },
      },
    });
    if (!user || !(await prisma.user.findUnique({ where: { id: req.params.id, isActive: true } }))) {
      throw new AppError(404, 'User not found');
    }

    // Enforce privacy flags
    const publicUser: Record<string, unknown> = { ...user };
    if (!user.showEmail) delete publicUser.email;
    if (!user.showPhone) delete publicUser.phone;
    if (!user.showLocation) delete publicUser.location;
    if (!user.showRating) {
      delete publicUser.rating;
      delete publicUser.ratingCount;
    }

    res.json(publicUser);
  } catch (error) {
    next(error);
  }
});

export default router;
