import { Inject, Injectable, InternalServerErrorException, Logger, forwardRef, } from '@nestjs/common' import { DatabaseService } from '../database/database.service' import { createDefaultUserState } from '../shared/catalog/default-user-state' import type { MeResponse, UserState } from '../shared/types/user.types' import { GoldLandProgressionService } from '../gold-land/services/progression.service' @Injectable() export class UsersService { private readonly logger = new Logger(UsersService.name) constructor( @Inject(DatabaseService) private readonly database: DatabaseService, @Inject(forwardRef(() => GoldLandProgressionService)) private readonly goldLandProgression: GoldLandProgressionService, ) {} ensureUser(userId: string): UserState { return this.getUserState(userId) } getUserState(userId: string): UserState { const row = this.database .getDb() .prepare('SELECT state_json FROM users WHERE id = ?') .get(userId) as { state_json: string } | undefined if (row) { return this.parseStateJson(row.state_json, userId) } const state = createDefaultUserState(userId) this.database .getDb() .prepare('INSERT INTO users (id, state_json, updated_at) VALUES (?, ?, ?)') .run(userId, JSON.stringify(state), new Date().toISOString()) return state } saveUserState(state: UserState): UserState { this.database .getDb() .prepare('UPDATE users SET state_json = ?, updated_at = ? WHERE id = ?') .run(JSON.stringify(state), new Date().toISOString(), state.id) return state } toMeResponse(state: UserState): MeResponse { return { user: { id: state.id, name: state.name, level: state.level, xp: state.xp, maxXp: state.maxXp, coins: state.coins, missionProgress: state.missionProgress, missionTarget: state.missionTarget, }, wallet: { cash: state.cash, goldGrams: state.goldGrams, }, progress: { completedChallenges: state.completedChallenges, completedLessons: state.completedLessons, completedGames: state.completedGames, claimedRewards: state.claimedRewards, ownedItems: state.ownedItems, mapLevels: state.mapLevels, totalStars: state.totalStars, maxStars: state.maxStars, }, achievements: state.achievements, transactions: state.transactions, market: { selectedRange: state.marketSelectedRange, }, } } getMe(userId: string): MeResponse { const state = this.goldLandProgression.syncUserProgressionState(userId) return this.toMeResponse(state) } updateProfile(userId: string, name: string): MeResponse { return this.database.transaction(() => { const state = this.getUserState(userId) state.name = name.trim() this.saveUserState(state) return this.toMeResponse(state) }) } private parseStateJson(raw: string, userId: string): UserState { try { return JSON.parse(raw) as UserState } catch (error) { this.logger.error(`Invalid state_json for user ${userId}`, error) throw new InternalServerErrorException('داده کاربر نامعتبر است') } } }