import { join } from 'path'
import { Inject, Injectable, forwardRef } from '@nestjs/common'
import { InjectRepository } from '@nestjs/typeorm'
import { CommissionConfig } from './entities/commission-config.entity'
import { Repository } from 'typeorm'
import { CommissionRecord } from './entities/commission-record.entity'
import { Users } from '../users/entities/users.entity'
import { UserBalanceService } from '../user-balance/user-balance.service'
import { BalanceType as BalanceType } from '../user-balance/entities/balance-record.entity'
import { BigNumber } from 'bignumber.js'
import { CommissionRecordDto } from './dto/commission-record.dto'
import { hideSensitiveData } from '../utils/common'
import { MembershipService } from '../membership/membership.service'

@Injectable()
export class CommissionService {
    constructor(
        @InjectRepository(CommissionConfig)
        private readonly commissionConfigRepository: Repository<CommissionConfig>,
        @InjectRepository(CommissionRecord)
        private readonly commissionRecordRepository: Repository<CommissionRecord>,
        @InjectRepository(Users)
        private readonly usersRepository: Repository<Users>,
        private readonly userBalanceService: UserBalanceService,
        @Inject(forwardRef(() => MembershipService))
        private readonly membershipService: MembershipService
    ) {}

    async saveConfig(config: Partial<CommissionConfig>) {
        return await this.commissionConfigRepository.save(config)
    }

    async doCommission(userId: number, amount: BigNumber) {
        amount = new BigNumber(amount)
        const user = await this.usersRepository.findOneBy({
            id: userId
        })
        if (!user || !user.invitor) return

        const plans = await this.membershipService.getPlans()
        const configs = await this.commissionConfigRepository.find()
        const maxLevel = configs.map((config) => config.level).sort((a, b) => b - a)[0] || 0

        let invitorId = user.invitor
        for (let i = 0; i < maxLevel; i++) {
            const invitor = await this.usersRepository.findOneBy({
                id: invitorId
            })
            if (!invitor) return
            const membership = await this.membershipService.getMembership(invitorId)
            const plan = plans.find((plan) => plan.id === membership.planId)
            if (plan?.commissionable) {
                const config = configs.find((config) => config.level === i + 1)
                if (config) {
                    const commission = amount.times(config.ratio)
                    await this.userBalanceService.modifyBalance(invitorId, commission, BalanceType.COMMISSION)
                    await this.commissionRecordRepository.save(
                        new CommissionRecord({
                            userId: invitorId,
                            fromUserId: userId,
                            amount: commission,
                            level: configs[i].level,
                            ratio: configs[i].ratio
                        })
                    )
                }
            }

            if (!invitor.invitor) return
            invitorId = invitor.invitor
        }
    }

    async getRecords(userId: number) {
        return (
            await this.commissionRecordRepository
                .createQueryBuilder()
                .leftJoinAndMapOne(
                    'CommissionRecord.fromUser',
                    Users,
                    'fromUser',
                    'CommissionRecord.fromUserId = fromUser.id'
                )
                .where('CommissionRecord.userId = :userId', { userId })
                .orderBy('CommissionRecord.createdAt', 'DESC')
                .getMany()
        ).map((record) => {
            return new CommissionRecordDto({
                id: record.id,
                userId: record.userId,
                fromUserId: record.fromUserId,
                name: hideSensitiveData(record.fromUser?.name),
                level: record.level,
                ratio: record.ratio,
                amount: record.amount
            })
        })

        // return await this.commissionRecordRepository.find({
        //     relations: {
        //         fromUser: true
        //     },
        //     where: {
        //         userId
        //     },
        //     order: {
        //         createdAt: 'DESC'
        //     }
        // })
    }
}
