import { Injectable, UnauthorizedException } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { User } from '../entities/user.entity';
import * as bcrypt from 'bcrypt';
import { JwtService } from '@nestjs/jwt';
import { ConfigService } from '@nestjs/config';
import { Role } from '../enums/role.enum';

@Injectable()
export class AuthService {
  constructor(
    @InjectRepository(User)
    private usersRepository: Repository<User>,
    private jwtService: JwtService,
    private configService: ConfigService,
  ) {}

  async getProfile(userId: string) {
    const user = await this.usersRepository.findOne({
      where: { id: userId },
      relations: ['role'],
    });

    if (!user) {
      throw new UnauthorizedException('User not found');
    }

    return {
      id: user.id,
      email: user.email,
      firstName: user.firstName,
      lastName: user.lastName,
      role: user.role?.name || user.role,
    };
  }

  async validateUser(email: string, password: string): Promise<User | null> {
    const user = await this.usersRepository.findOne({
      where: { email },
      select: ['id', 'email', 'passwordHash', 'roleId', 'isActive'],
      relations: ['role'],
    });

    if (!user || !user.isActive) {
      return null;
    }

    const isValidPassword = await bcrypt.compare(password, user.passwordHash);
    if (!isValidPassword) {
      return null;
    }

    return user;
  }

  async login(user: User) {
    const payload = {
      sub: user.id,
      email: user.email,
      role: user.role?.name || user.role,
    };

    return {
      access_token: this.jwtService.sign(payload),
      user: {
        id: user.id,
        email: user.email,
        role: user.role?.name || user.role,
      },
    };
  }

  async register(userData: any) {
    const hashedPassword = await bcrypt.hash(userData.password, 10);
    const user = this.usersRepository.create({
      ...userData,
      password: hashedPassword,
      role: Role.CUSTOMER,
      isActive: true,
    });

    return this.usersRepository.save(user);
  }

  async forgotPassword(email: string) {
    const user = await this.usersRepository.findOne({
      where: { email },
      select: ['id', 'email'],
    });

    if (!user) {
      throw new UnauthorizedException('User not found');
    }

    // Generate reset token
    const resetToken = this.jwtService.sign(
      { userId: user.id },
      {
        secret: this.configService.get('JWT_RESET_SECRET'),
        expiresIn: '1h',
      }
    );

    // Save reset token to user
    await this.usersRepository.update(user.id, {
      resetToken,
      resetTokenExpiration: new Date(Date.now() + 3600000), // 1 hour from now
    });

    // Send reset email
    // TODO: Implement email service

    return { message: 'Password reset email sent' };
  }

  async resetPassword(token: string, newPassword: string) {
    const decoded = this.jwtService.verify(token, {
      secret: this.configService.get('JWT_RESET_SECRET'),
    });

    const user = await this.usersRepository.findOne({
      where: { id: decoded.userId },
      select: ['id', 'resetToken', 'resetTokenExpiration'],
    });

    if (!user || !user.resetToken) {
      throw new UnauthorizedException('Invalid reset token');
    }

    if (new Date() > user.resetTokenExpiration) {
      throw new UnauthorizedException('Reset token expired');
    }

    const hashedPassword = await bcrypt.hash(newPassword, 10);
    await this.usersRepository.update(user.id, {
      passwordHash: hashedPassword,
      resetToken: null,
      resetTokenExpiration: null,
    });

    return { message: 'Password reset successfully' };
  }
}
