import { PrismaClient } from '@prisma/client';
import bcrypt from 'bcryptjs';
import jwt from 'jsonwebtoken';
import { User, UserPermissions } from '../types/auth';
import { logger } from '../config/logger';
import { JsonValue } from "@prisma/client/runtime/library";

const prisma = new PrismaClient();

export const authService = {
  login: async (email: string, password: string) => {
    try {
      logger.info(`Попытка входа пользователя: ${email}`);
      
      const user : {
        email: string;
        password: string;
        id: string;
        displayName: string;
        avatarUrl: string;
        permissions: JsonValue;
      } | null = await prisma.user.findUnique({
        where: { email },
        select: {
          id: true,
          email: true,
          displayName: true,
          avatarUrl: true,
          password: true,
          permissions: true
        }
      });

      if (!user) {
        logger.warn(`Сбой входа: Пользователь не найден - ${email}`);
        throw new Error('Недопустивые данные пользователя');
      }

      const isValidPassword = await bcrypt.compare(password, user.password);
      if (!isValidPassword) {
        logger.warn(`Сбой входа: Неправильный пароль пользователя - ${email}`);
        throw new Error('Недопустивые данные пользователя');
      }

      const token = await authService.generateToken(user.id);
      const { password: _, ...userWithoutPassword } = user;

      const permissions = user.permissions as unknown;

      logger.info(`Пользователь успешно зашел: ${email}`);
      return {
        user: {...userWithoutPassword,
               permissions: permissions as UserPermissions } as User,
        token
      };
    } catch (error) {
      logger.error('Ошибка входа:', error);
      throw error;
    }
  },

  generateToken: async (userId: string) => {
    try {
      const token = jwt.sign(
        { id: userId },
        process.env.JWT_SECRET || '',
        { expiresIn: '24h' }
      );
      logger.debug(`Создан токен для пользователя: ${userId}`);
      return token;
    } catch (error) {
      logger.error('Ошибка создания токена:', error);
      throw error;
    }
  },

  createUser: async (userData: {
    email: string;
    password: string;
    displayName: string;
    avatarUrl: string;
    permissions: any;
  }) => {
    try {
      logger.info(`Создание нового пользователя: ${userData.email}`);
      
      const hashedPassword = await bcrypt.hash(userData.password, 10);
      const user : {
        email: string;
        id: string;
        displayName: string;
        avatarUrl: string;
        permissions: JsonValue;
      } = await prisma.user.create({
        data: {
          ...userData,
          password: hashedPassword
        },
        select: {
          id: true,
          email: true,
          displayName: true,
          avatarUrl: true,
          permissions: true
        }
      });

      logger.info(`Пользователь успешно создан: ${userData.email}`);

      const permissions = user.permissions as unknown;

      return {...user,
              permissions: permissions as UserPermissions } as User
    } catch (error) {
      logger.error('Ошибка создания пользователя:', error);
      throw error;
    }
  }
};