"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.SearchService = void 0;
const common_1 = require("@nestjs/common");
const typeorm_1 = require("@nestjs/typeorm");
const typeorm_2 = require("typeorm");
const expense_entity_1 = require("../../database/entities/expense.entity");
const group_member_entity_1 = require("../../database/entities/group-member.entity");
const user_entity_1 = require("../../database/entities/user.entity");
const MAX_PER_TYPE = 10;
let SearchService = class SearchService {
    constructor(expenseRepo, groupMemberRepo, userRepo) {
        this.expenseRepo = expenseRepo;
        this.groupMemberRepo = groupMemberRepo;
        this.userRepo = userRepo;
    }
    async search(userId, query) {
        const q = query.q.trim();
        const type = query.type ?? 'all';
        const [expenses, groups, users] = await Promise.all([
            type === 'all' || type === 'expense' ? this.searchExpenses(userId, q) : [],
            type === 'all' || type === 'group' ? this.searchGroups(userId, q) : [],
            type === 'all' || type === 'user' ? this.searchUsers(userId, q) : [],
        ]);
        const results = [...expenses, ...groups, ...users];
        return { results, totalCount: results.length };
    }
    async searchExpenses(userId, q) {
        const expenses = await this.expenseRepo
            .createQueryBuilder('expense')
            .innerJoin('expense.splits', 'split', 'split.userId = :userId', { userId })
            .leftJoinAndSelect('expense.group', 'group')
            .where('expense.isDeleted = false')
            .andWhere('expense.description LIKE :q', { q: `%${q}%` })
            .orderBy('expense.date', 'DESC')
            .take(MAX_PER_TYPE)
            .getMany();
        return expenses.map((e) => ({
            id: e.id,
            type: 'expense',
            description: e.description,
            amount: Number(e.amount),
            currency: e.currency,
            category: e.category,
            groupName: e.group?.name ?? null,
            date: e.date,
        }));
    }
    async searchGroups(userId, q) {
        const memberships = await this.groupMemberRepo.find({
            where: {
                userId,
                leftAt: (0, typeorm_2.IsNull)(),
                group: { isActive: true, name: (0, typeorm_2.Like)(`%${q}%`) },
            },
            relations: { group: true },
            take: MAX_PER_TYPE,
        });
        const results = [];
        for (const { group } of memberships) {
            if (!group)
                continue;
            const memberCount = await this.groupMemberRepo.count({
                where: { groupId: group.id, leftAt: (0, typeorm_2.IsNull)() },
            });
            results.push({
                id: group.id,
                type: 'group',
                name: group.name,
                description: group.description,
                imageUrl: group.imageUrl,
                memberCount,
                currency: group.currency,
            });
        }
        return results;
    }
    async searchUsers(userId, q) {
        const users = await this.userRepo.find({
            where: [
                { id: (0, typeorm_2.Not)(userId), name: (0, typeorm_2.Like)(`%${q}%`) },
                { id: (0, typeorm_2.Not)(userId), email: (0, typeorm_2.Like)(`%${q}%`) },
            ],
            select: { id: true, name: true, email: true, avatarUrl: true },
            take: MAX_PER_TYPE,
        });
        return users.map((u) => ({
            id: u.id,
            type: 'user',
            name: u.name,
            email: u.email,
            avatarUrl: u.avatarUrl,
        }));
    }
};
exports.SearchService = SearchService;
exports.SearchService = SearchService = __decorate([
    (0, common_1.Injectable)(),
    __param(0, (0, typeorm_1.InjectRepository)(expense_entity_1.Expense)),
    __param(1, (0, typeorm_1.InjectRepository)(group_member_entity_1.GroupMember)),
    __param(2, (0, typeorm_1.InjectRepository)(user_entity_1.User)),
    __metadata("design:paramtypes", [typeorm_2.Repository,
        typeorm_2.Repository,
        typeorm_2.Repository])
], SearchService);
//# sourceMappingURL=search.service.js.map