"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); }
};
var AdminVendorService_1;
Object.defineProperty(exports, "__esModule", { value: true });
exports.AdminVendorService = void 0;
const common_1 = require("@nestjs/common");
const typeorm_1 = require("typeorm");
const typeorm_2 = require("@nestjs/typeorm");
const user_entity_1 = require("../../common/vendor/user.entity");
const user_entity_2 = require("../../appapi/user/user.entity");
const vendor_entity_1 = require("../../common/vendor/vendor.entity");
const bcrypt = require("bcrypt");
const vendor_plan_entity_1 = require("../../common/vendor/vendor_plan.entity");
const status_enum_1 = require("../../common/columntype/status.enum");
const shop_entity_1 = require("../../common/shop/shop.entity");
const review_entity_1 = require("../../common/review/review.entity");
const document_entity_1 = require("../../common/document/document.entity");
const offer_entity_1 = require("../../common/offer/offer.entity");
const productrequest_entity_1 = require("../../common/productrequest/productrequest.entity");
const plan_entity_1 = require("../../common/plan/plan.entity");
let AdminVendorService = AdminVendorService_1 = class AdminVendorService {
    constructor(userRepository, vendorRepository, vendorPlanRepository, offerRepository, shopReviewRepository, productrequestRepository, shopRepository) {
        this.userRepository = userRepository;
        this.vendorRepository = vendorRepository;
        this.vendorPlanRepository = vendorPlanRepository;
        this.offerRepository = offerRepository;
        this.shopReviewRepository = shopReviewRepository;
        this.productrequestRepository = productrequestRepository;
        this.shopRepository = shopRepository;
        this.logger = new common_1.Logger(AdminVendorService_1.name);
    }
    async create(CreateVendorDto) {
        const userId = this.generateUserId(CreateVendorDto.name, CreateVendorDto.email);
        const hashedPassword = await this.hashPassword(CreateVendorDto.password);
        const user = this.userRepository.create({
            ...CreateVendorDto,
            userId,
            password: hashedPassword,
        });
        const savedUser = await this.userRepository.save(user);
        const vendor = this.vendorRepository.create({
            planId: CreateVendorDto.planId,
            twitter_link: CreateVendorDto.twitter_link,
            instagram_link: CreateVendorDto.instagram_link,
            fb_link: CreateVendorDto.fb_link,
            linkedin_link: CreateVendorDto.linkedin_link,
            user: savedUser,
        });
        await this.vendorRepository.save(vendor);
        const vendorplans = this.vendorPlanRepository.create({
            vendorId: user.id,
            planId: CreateVendorDto.planId,
            status: status_enum_1.Status.INACTIVE
        });
        await this.vendorPlanRepository.save(vendorplans);
        return savedUser;
    }
    async findAll() {
        return this.userRepository
            .createQueryBuilder('user')
            .leftJoinAndMapOne('user.vendorPlan', vendor_plan_entity_1.VendorPlan, 'vendorPlan', 'vendorPlan.vendorId = user.id')
            .leftJoinAndMapOne('vendorPlan.plan', plan_entity_1.Plan, 'plan', 'plan.id = vendorPlan.planId')
            .leftJoinAndSelect('user.vendor', 'vendor')
            .where('user.roles LIKE :role', { role: `%${user_entity_2.UserRole.VENDOR}%` })
            .orderBy(`GREATEST(vendorPlan.updatedAt, vendorPlan.createdAt)`, 'DESC')
            .addOrderBy('vendorPlan.updatedAt', 'DESC')
            .addOrderBy('user.createdAt', 'DESC')
            .getMany();
    }
    async findOne(id) {
        const vendor = await this.userRepository
            .createQueryBuilder('user')
            .leftJoinAndSelect('user.vendor', 'vendor')
            .leftJoinAndSelect('vendor.plan', 'plan')
            .leftJoinAndMapMany('vendor.documents', document_entity_1.Document, 'document', 'document.vendorId = user.id')
            .leftJoinAndMapMany('vendor.shops', shop_entity_1.Shop, 'shops', 'shops.userId = vendor.userId')
            .leftJoinAndMapMany('shops.reviews', review_entity_1.Review, 'reviews', 'reviews.shopId = shops.id')
            .where('user.id = :id', { id })
            .getOne();
        if (!vendor) {
            throw new common_1.NotFoundException(`Vendor with ID ${id} not found`);
        }
        return vendor;
    }
    async update(id, UpdateVendorDto) {
        const user = await this.userRepository.findOne({
            where: { id: id },
            relations: ['vendor'],
        });
        if (!user) {
            throw new common_1.NotFoundException('User not found');
        }
        const updateUser = this.userRepository.create({
            name: UpdateVendorDto.name,
            lastName: UpdateVendorDto.lastName,
            email: UpdateVendorDto.email,
            dateOfBirth: UpdateVendorDto.dateOfBirth,
            nationality: UpdateVendorDto.nationality,
            preferredLanguage: UpdateVendorDto.preferredLanguage,
            gender: UpdateVendorDto.gender,
            mobileNumber: UpdateVendorDto.mobileNumber,
            userAddress: UpdateVendorDto.userAddress,
            status: UpdateVendorDto.status
        });
        await this.userRepository.update(id, updateUser);
        if (user.vendor) {
            if (UpdateVendorDto.planId)
                user.vendor.planId = UpdateVendorDto.planId;
            if (UpdateVendorDto.twitter_link)
                user.vendor.twitter_link = UpdateVendorDto.twitter_link;
            if (UpdateVendorDto.instagram_link)
                user.vendor.instagram_link = UpdateVendorDto.instagram_link;
            if (UpdateVendorDto.fb_link)
                user.vendor.fb_link = UpdateVendorDto.fb_link;
            if (UpdateVendorDto.linkedin_link)
                user.vendor.linkedin_link = UpdateVendorDto.linkedin_link;
        }
        else {
            const vendor = this.vendorRepository.create({
                planId: UpdateVendorDto?.planId,
                twitter_link: UpdateVendorDto?.twitter_link,
                instagram_link: UpdateVendorDto?.instagram_link,
                fb_link: UpdateVendorDto?.fb_link,
                linkedin_link: UpdateVendorDto?.linkedin_link,
                user: user,
            });
            await this.vendorRepository.save(vendor);
        }
        await this.vendorRepository.save(user.vendor);
        return this.findOne(id);
    }
    async updateUserStatus(userId, status) {
        const user = await this.userRepository.findOne({ where: { id: userId } });
        if (!user) {
            throw new common_1.NotFoundException('User not found');
        }
        const vendorPlan = await this.vendorPlanRepository.findOne({ where: { vendorId: userId } });
        if (!vendorPlan) {
            throw new common_1.NotFoundException('Vendor plan not found');
        }
        user.status = status;
        user.userVerified = (status === "active") ? 1 : 0;
        const res = this.userRepository.save(user);
        if (Array.isArray(user.roles) && user.roles.includes(user_entity_2.UserRole.VENDOR)) {
            const latestInactivePlan = await this.vendorPlanRepository
                .createQueryBuilder('vendorPlan')
                .leftJoinAndMapOne('vendorPlan.plan', 'plans', 'plan', 'vendorPlan.planId = plan.id')
                .where('vendorPlan.vendorId = :vendorId', { vendorId: user.id })
                .orderBy('vendorPlan.createdAt', 'DESC')
                .getOne();
            if (latestInactivePlan) {
                latestInactivePlan.status = status;
                latestInactivePlan.start_date = new Date();
                const endDate = new Date(latestInactivePlan.start_date);
                if (latestInactivePlan['plan']?.plan_type == 1) {
                    endDate.setMonth(endDate.getMonth() + 1);
                }
                else if (latestInactivePlan['plan']?.plan_type == 2) {
                    endDate.setMonth(endDate.getMonth() + 3);
                }
                else if (latestInactivePlan['plan']?.plan_type == 3) {
                    endDate.setFullYear(endDate.getFullYear() + 1);
                }
                latestInactivePlan.end_date = endDate;
                await this.vendorPlanRepository.save(latestInactivePlan);
            }
        }
        return res;
    }
    async remove(id) {
        const result = await this.userRepository.delete(id);
        if (result.affected === 0) {
            throw new common_1.NotFoundException(`Vendor with ID ${id} not found`);
        }
    }
    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 getVendorDashboard(vendorId) {
        const dashboard = {};
        const activeOffers = await this.offerRepository
            .createQueryBuilder('offer')
            .where('offer.createdBy = :vendorId', { vendorId })
            .andWhere('offer.status = :status', { status: 'active' })
            .getCount();
        dashboard.activeOffers = activeOffers;
        const avgRaw = await this.shopReviewRepository
            .createQueryBuilder('review')
            .innerJoin(shop_entity_1.Shop, 'shop', 'shop.id = review.shopId')
            .where('shop.userId = :vendorId', { vendorId })
            .select('AVG(review.rating)', 'avgRating')
            .getRawOne();
        const avgRatingNumber = avgRaw && avgRaw.avgRating !== null
            ? Number(Number(avgRaw.avgRating).toFixed(1))
            : 0.0;
        dashboard.avgRating = Number(avgRatingNumber || 0).toFixed(1);
        const reviewsRaw = await this.shopReviewRepository
            .createQueryBuilder('review')
            .innerJoin(user_entity_1.User, 'user', 'user.id = review.userId')
            .innerJoin(shop_entity_1.Shop, 'shop', 'shop.id = review.shopId')
            .where('shop.userId = :vendorId', { vendorId })
            .select([
            'review.id AS review_id',
            'review.rating AS rating',
            'review.comment AS comment',
            'review.createdAt AS createdAt',
            'user.id AS user_id',
            'user.name AS user_name',
            'shop.name AS shop_name',
            'shop.id AS shop_id',
        ])
            .orderBy('review.createdAt', 'DESC')
            .getRawMany();
        const reviews = reviewsRaw.map(r => ({
            id: r.review_id,
            rating: Number(r.rating),
            comment: r.comment,
            createdAt: r.createdAt,
            user: {
                id: r.user_id,
                name: r.user_name,
            },
            shop: {
                id: r.shop_id,
                name: r.shop_name,
            },
        }));
        dashboard.ratingDetail = {
            avgRating: Number(avgRatingNumber.toFixed(1)),
            reviews,
        };
        const shopCount = await this.shopRepository.count({
            where: { userId: vendorId }
        });
        dashboard.totalShopListings = shopCount;
        const vendor = await this.vendorRepository.findOne({
            where: { user: { id: vendorId } },
        });
        if (!vendor)
            throw new common_1.NotFoundException('Vendor not found');
        let categories = [];
        if (vendor.categories) {
            const rawValue = vendor.categories;
            if (typeof rawValue === 'string') {
                const s = String(rawValue).trim();
                if (s.startsWith('[')) {
                    try {
                        categories = JSON.parse(s)
                            .map((c) => Number(c))
                            .filter((n) => !Number.isNaN(n));
                    }
                    catch {
                        categories = s.split(',').map(x => Number(x.trim())).filter(n => !Number.isNaN(n));
                    }
                }
                else {
                    categories = s.split(',').map(x => Number(x.trim())).filter(n => !Number.isNaN(n));
                }
            }
            else if (Array.isArray(rawValue)) {
                categories = rawValue.map((c) => Number(c)).filter(n => !Number.isNaN(n));
            }
            else if (typeof rawValue === 'number') {
                categories = [rawValue];
            }
            else {
                const s = String(rawValue).trim();
                if (s) {
                    categories = s.split(',').map(x => Number(x.trim())).filter(n => !Number.isNaN(n));
                }
            }
        }
        let prRows = [];
        if (categories.length > 0) {
            prRows = await this.productrequestRepository
                .createQueryBuilder('pr')
                .select([
                'pr.id AS pr_id',
                'pr.shopId AS pr_categoryId',
                'pr.title AS pr_title',
                'pr.description AS pr_description',
                'pr.customerName AS pr_customerName',
                'pr.email AS pr_email',
                'pr.mobile AS pr_mobile',
                'pr.status AS pr_status',
                'pr.galleries AS pr_galleries',
                'pr.createdAt AS pr_createdAt',
            ])
                .where('pr.shopId IN (:...categories)', { categories })
                .orderBy('pr.createdAt', 'DESC')
                .getRawMany();
        }
        function safeParse(json) {
            if (typeof json === 'string') {
                try {
                    return JSON.parse(json);
                }
                catch {
                    return [];
                }
            }
            return Array.isArray(json) ? json : [];
        }
        const productRequests = prRows.map(r => ({
            id: Number(r.pr_id),
            categoryId: Number(r.pr_categoryId),
            title: r.pr_title,
            description: r.pr_description,
            customerName: r.pr_customerName,
            email: r.pr_email,
            mobile: r.pr_mobile,
            status: r.pr_status,
            galleries: safeParse(r.pr_galleries),
            createdAt: r.pr_createdAt,
            user: null
        }));
        dashboard.productRequests = productRequests;
        dashboard.categories = categories;
        return dashboard;
    }
};
exports.AdminVendorService = AdminVendorService;
exports.AdminVendorService = AdminVendorService = AdminVendorService_1 = __decorate([
    (0, common_1.Injectable)(),
    __param(0, (0, typeorm_2.InjectRepository)(user_entity_1.User)),
    __param(1, (0, typeorm_2.InjectRepository)(vendor_entity_1.Vendor)),
    __param(2, (0, typeorm_2.InjectRepository)(vendor_plan_entity_1.VendorPlan)),
    __param(3, (0, typeorm_2.InjectRepository)(offer_entity_1.Offer)),
    __param(4, (0, typeorm_2.InjectRepository)(review_entity_1.Review)),
    __param(5, (0, typeorm_2.InjectRepository)(productrequest_entity_1.ProductRequest)),
    __param(6, (0, typeorm_2.InjectRepository)(shop_entity_1.Shop)),
    __metadata("design:paramtypes", [typeorm_1.Repository,
        typeorm_1.Repository,
        typeorm_1.Repository,
        typeorm_1.Repository,
        typeorm_1.Repository,
        typeorm_1.Repository,
        typeorm_1.Repository])
], AdminVendorService);
//# sourceMappingURL=vendor.service.js.map