import { User, Service, Booking, Review, Message, Notification } from '../models/index.js';
import { Op } from 'sequelize';

const userSockets = new Map();

export const initSocket = (io) => {
  io.on('connection', (socket) => {
    const userId = socket.handshake.auth.userId;
    if (userId) {
      userSockets.set(userId, socket.id);
      socket.join(`user:${userId}`);
    }

    socket.on('join:booking', (bookingId) => {
      socket.join(`booking:${bookingId}`);
    });

    socket.on('send:message', async (data) => {
      try {
        const { bookingId, content, type = 'text' } = data;
        const message = await Message.create({ booking_id: bookingId, sender_id: userId, content, type });
        const populated = await Message.findByPk(message.id, {
          include: [{ model: User, as: 'sender', attributes: ['id', 'name', 'avatar'] }]
        });
        io.to(`booking:${bookingId}`).emit('message:new', populated);
      } catch (e) {
        socket.emit('error', { message: 'Failed to send message' });
      }
    });

    socket.on('typing:start', (bookingId) => {
      socket.to(`booking:${bookingId}`).emit('typing:start', { userId });
    });

    socket.on('typing:stop', (bookingId) => {
      socket.to(`booking:${bookingId}`).emit('typing:stop', { userId });
    });

    socket.on('disconnect', () => {
      if (userId) userSockets.delete(userId);
    });
  });
};

export const sendNotification = async (io, userId, type, title, message, data = {}) => {
  const notification = await Notification.create({ user_id: userId, type, title, message, data });
  const socketId = userSockets.get(userId);
  if (socketId) io.to(socketId).emit('notification:new', notification);
  return notification;
};

export const updateRating = async (model, id, ratingField, countField) => {
  const reviews = await Review.findAll({ where: { [model === User ? 'provider_id' : 'service_id']: id } });
  const avgRating = reviews.length > 0 ? reviews.reduce((sum, r) => sum + r.rating, 0) / reviews.length : 0;
  await model.update({ [ratingField]: Math.round(avgRating * 100) / 100, [countField]: reviews.length }, { where: { id } });
};