"use strict";
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
    return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
    if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
var __param = (this && this.__param) || function (paramIndex, decorator) {
    return function (target, key) { decorator(target, key, paramIndex); }
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.UserService = void 0;
const common_1 = require("@nestjs/common");
const typeorm_1 = require("typeorm");
const typeorm_2 = require("@nestjs/typeorm");
const user_entity_1 = require("../user/user.entity");
const bcrypt = require("bcrypt");
const kyc_status_enum_1 = require("../../common/kyc/kyc-status.enum");
let UserService = class UserService {
    constructor(userRepository) {
        this.userRepository = userRepository;
    }
    findAll() {
        return this.userRepository.find();
    }
    async registerUser(createUserDto) {
        const userId = this.generateUserId(createUserDto.name, createUserDto.email);
        const hashedPassword = await this.hashPassword(createUserDto.password);
        const { hash, ...userData } = createUserDto;
        const newUser = this.userRepository.create({
            ...userData,
            userId,
            password: hashedPassword,
        });
        return await this.userRepository.save(newUser);
    }
    async findAdmin() {
        return await this.userRepository
            .createQueryBuilder('user')
            .where("FIND_IN_SET(:role, user.roles)", { role: user_entity_1.UserRole.ADMIN })
            .getMany();
    }
    generateUserId(name, email) {
        const timestamp = Date.now();
        const emailInitials = email.slice(0, 2).toUpperCase();
        const year = new Date().getFullYear();
        const userId = `${name.replace(/\s+/g, '').toLowerCase()}${emailInitials}${year}${timestamp}`;
        return userId;
    }
    async hashPassword(password) {
        const salt = await bcrypt.genSalt();
        return await bcrypt.hash(password, salt);
    }
    async updateUser(userId, updateUserDto) {
        const user = await this.userRepository.findOne({
            where: { userId: userId },
        });
        if (!user) {
            throw new common_1.NotFoundException(`User with ID ${userId} not found`);
        }
        Object.assign(user, updateUserDto);
        user.userVerified = true;
        return await this.userRepository.save(user);
    }
    async updateOtpUser(user) {
        return await this.userRepository.save(user);
    }
    async updateDeviceIdUser(user) {
        return await this.userRepository.save(user);
    }
    async findUserByMobile(identifier) {
        const isEmail = /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(identifier);
        const user = isEmail
            ? await this.userRepository.findOne({ where: { email: identifier } })
            : await this.userRepository.findOne({ where: { mobileNumber: identifier } });
        return user;
    }
    async validateOtp(identifier, otp) {
        const isEmail = /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(identifier);
        const user = isEmail
            ? await this.userRepository.findOne({ where: { email: identifier } })
            : await this.userRepository.findOne({ where: { mobileNumber: identifier } });
        if (!user) {
            throw new common_1.UnauthorizedException('User not found with the provided identifier');
        }
        if (user.otp !== otp) {
            throw new common_1.UnauthorizedException('Invalid OTP');
        }
        const now = new Date();
        if (user.otpExpiresAt && user.otpExpiresAt < now) {
            throw new common_1.UnauthorizedException('OTP has expired');
        }
        return true;
    }
    async findOneProfile(userId) {
        return this.userRepository.findOne({ where: { id: parseInt(userId) } });
    }
    async findById(userId) {
        return this.userRepository.findOne({ where: { id: userId } });
    }
    async findOneMobileEmail(identifier) {
        const isEmail = /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(identifier);
        return this.userRepository.findOne({
            where: isEmail ? { email: identifier } : { mobileNumber: identifier },
        });
    }
    async updateOtpUserStatus(user) {
        user.otpStatus = true;
        return await this.userRepository.save(user);
    }
    async addRole(id, role) {
        const user = await this.userRepository.findOne({ where: { id } });
        if (!user)
            throw new Error('User not found');
        if (role === user_entity_1.UserRole.VENDOR && user.roles.includes(user_entity_1.UserRole.ADMIN)) {
            throw new Error('Admin users cannot be assigned the vendor role');
        }
        if (!user.roles.includes(role)) {
            user.roles.push(role);
            return this.userRepository.save(user);
        }
        return user;
    }
    async removeRole(id, role) {
        const user = await this.userRepository.findOne({ where: { id } });
        if (!user)
            throw new Error('User not found');
        user.roles = user.roles.filter(r => r !== role);
        return this.userRepository.save(user);
    }
    async updateStatus(id, status) {
        const user = await this.userRepository.findOne({ where: { id } });
        if (!user) {
            throw new common_1.NotFoundException(`User with id ${id} not found`);
        }
        user.status = status;
        return await this.userRepository.save(user);
    }
    async changePassword(userId, newPassword) {
        if (!newPassword || newPassword.length < 6) {
            throw new common_1.BadRequestException('Invalid password');
        }
        const user = await this.userRepository.findOne({ where: { id: userId } });
        if (!user)
            throw new common_1.NotFoundException('User not found');
        const hashedPassword = await this.hashPassword(newPassword);
        user.password = hashedPassword;
        await this.userRepository.save(user);
        return { id: user.id, message: 'Password changed successfully' };
    }
    async updateDeviceIdNotification(id, deviceId, deviceType) {
        const user = await this.userRepository.findOne({ where: { id } });
        if (!user) {
            throw new common_1.NotFoundException(`User with id ${id} not found`);
        }
        user.deviceId = deviceId;
        user.deviceType = deviceType;
        return await this.userRepository.save(user);
    }
    async setUserVerifiedById(id, verified) {
        const user = await this.userRepository.findOne({ where: { id } });
        if (!user) {
            throw new common_1.NotFoundException(`User with id ${id} not found`);
        }
        user.userVerified = verified;
        return await this.userRepository.save(user);
    }
    async setUserKycVerifiedById(id, verified) {
        const user = await this.userRepository.findOne({ where: { id } });
        if (!user) {
            throw new common_1.NotFoundException(`User with id ${id} not found`);
        }
        user.userKycVerified = verified;
        user.kycStatus = verified ? kyc_status_enum_1.KycVerificationStatus.VERIFIED : kyc_status_enum_1.KycVerificationStatus.UNVERIFIED;
        user.kycRejectedReason = verified ? null : user.kycRejectedReason;
        user.kycLastVerifiedAt = verified ? new Date() : user.kycLastVerifiedAt;
        return await this.userRepository.save(user);
    }
    async updateUserKycState(id, status, rejectionReason) {
        const user = await this.userRepository.findOne({ where: { id } });
        if (!user) {
            throw new common_1.NotFoundException(`User with id ${id} not found`);
        }
        user.kycStatus = status;
        user.userKycVerified = status === kyc_status_enum_1.KycVerificationStatus.VERIFIED;
        user.kycRejectedReason = rejectionReason ?? null;
        if (status === kyc_status_enum_1.KycVerificationStatus.VERIFIED) {
            user.kycLastVerifiedAt = new Date();
        }
        return await this.userRepository.save(user);
    }
};
exports.UserService = UserService;
exports.UserService = UserService = __decorate([
    (0, common_1.Injectable)(),
    __param(0, (0, typeorm_2.InjectRepository)(user_entity_1.User)),
    __metadata("design:paramtypes", [typeorm_1.Repository])
], UserService);
//# sourceMappingURL=user.services.js.map