import {
    Injectable
} from '@nestjs/common'
import { FindManyOptions, In, Repository, UpdateResult } from 'typeorm'
import { InjectRepository } from '@nestjs/typeorm'
import { Moments } from './entities/moments.entity'
import { paginate, Pagination } from 'nestjs-typeorm-paginate'
import { PageRequest } from '../common/dto/page-request'
import { ChatRoleService } from '../chat-role/chat-role.service'
import { LikesService } from 'src/likes/likes.service'
import { ChatRole } from 'src/chat-role/entities/chat-role.entity'
import { Likes } from 'src/likes/entities/likes.entity'
import { setInterval } from 'timers';
import { ChatService } from 'src/chat/chat.service'
import { Mask } from 'src/mask/entities/mask.entity'
import { MomentsDto } from './dto/moments.dto'
import { text } from 'stream/consumers'

@Injectable()
export class MomentsService {
    constructor(
        @InjectRepository(Moments)
        private readonly momentsRepository: Repository<Moments>,
        @InjectRepository(ChatRole)
        private readonly chatRoleRepository: Repository<ChatRole>,
        @InjectRepository(Likes)
        private readonly likesRepository: Repository<Likes>,
        @InjectRepository(Mask)
        private readonly maskRepository: Repository<Mask>,
        private readonly chatRoleService: ChatRoleService,
        private readonly chatService: ChatService,
        private readonly likesService: LikesService
    ) {
        this.delay()
        const now = new Date();
        const nextDay = new Date(now.getFullYear(), now.getMonth(), now.getDate() + 1)
        const delayTime = nextDay.getTime() - now.getTime()
        setTimeout(() => {
            this.automaticallySendMoments()
            setTimeout(() => {
                this.delay()
            }, 3 * 60 * 1000)
            setInterval(() => {
                this.automaticallySendMoments()
                setTimeout(() => {
                    this.delay()
                }, 3 * 60 * 1000)
            }, 24 * 60 * 60 * 1000)
        }, delayTime)
    }

    async findAll(req: PageRequest<Moments>, userId: number): Promise<Pagination<Moments>> {

        const query = await this.momentsRepository.createQueryBuilder('moments')
            .where('moments.isDel = false')
            .andWhere('moments.isPush = true')

        if (req.search) {
            const searchOptions = req.search as FindManyOptions<Moments>;
            if ('where' in req.search) {
                if ('where' in searchOptions && searchOptions.where) {
                    for (const [key, value] of Object.entries(searchOptions.where)) {
                        query.andWhere(`moments.${key} = ${value}`);
                    }
                }
            }

            if ('order' in req.search) {
                if ('order' in searchOptions && searchOptions.order) {
                    for (const [key, value] of Object.entries(searchOptions.order)) {
                        query.addOrderBy(`moments.${key}`, value as 'ASC' | 'DESC');
                    }
                }
            }
        }

        const options = { ...req.page }
        const page = await paginate<Moments>(query, options)

        //const page = await paginate<Moments>(this.momentsRepository, req.page, req.search)
        const ids = page.items.reduce((ids: number[], val: Moments) => {
            if (!ids.includes(val.userId)) {
                ids.push(val.userId);
            }
            return ids;
        }, []);

        const momnetsIds: number[] = page.items.map((moments) => moments.id)
        const likes = await this.likesRepository.createQueryBuilder('likes')
            .select('likes.targetId')
            .where({
                userId: +userId,
                targetId: In(momnetsIds),
                type: 1,
                isValid: true
            })
            .getMany()
        const targetIds: number[] = likes.map((like) => like.targetId);

        const map = await this.chatRoleService.findMapByIds(ids);
        page.items.forEach(c => {
            c.chatRole = map.get(c.userId)
            c.isLiked = targetIds.includes(c.id) ? true : false
        })

        return page
    }

    async findById(id: number, userId: number): Promise<Moments> {
        const moments = await this.momentsRepository.findOneBy({ id: +id })
        const chatRole = await this.chatRoleService.findById(moments.userId)
        const likes = await this.likesRepository.findOneBy({
            userId: +userId,
            targetId: id,
            type: 1,
            isValid: true
        })
        if (likes) {
            moments.isLiked = true
        }
        moments.chatRole = chatRole
        return moments
    }

    public async like(id: number, userId: number): Promise<void> {
        const moments = await this.momentsRepository.findOneBy({ id: +id })
        if (moments) {
            const likes = await this.likesService.like(id, userId, 1)
            const chatRole = await this.chatRoleRepository.findOneBy({ id: +moments.userId })
            if (likes.isValid) {
                moments.momentsLikeCount += 1
                chatRole.likeNumber += 1
            } else {
                moments.momentsLikeCount -= 1
                chatRole.likeNumber -= 1
            }
            await this.chatRoleRepository.save(chatRole)
            await this.momentsRepository.save(moments)
        }
    }

    public async automaticallySendMoments() {
        //const message = "我需要你以类似于朋友圈的方式发一条此时此刻的动态,尽量符合角色性格."
        const chatRoleList = await this.chatRoleRepository.createQueryBuilder().getMany()

        chatRoleList.forEach(async role => {
            const chatHistory = await this.chatService.sendMessage(null, null, role.condition)

            if (chatHistory.message.trim() !== '') {
                const momentsDto = new MomentsDto
                momentsDto.content = chatHistory.message
                momentsDto.userId = role.id
                momentsDto.messageId = chatHistory.messageId
                momentsDto.isPush = false
                await this.momentsRepository.save(momentsDto)
            }
        })
    }


    public async delay() {
        const momentsList = await this.momentsRepository.createQueryBuilder('moments')
            .where('moments.isPush = false')
            .getMany()

        momentsList.forEach(moments => {

            const targetTime = new Date();
            targetTime.setHours(Math.floor(Math.random() * 12) + 10);
            targetTime.setMinutes(Math.floor(Math.random() * 60));

            const now = new Date();
            const delayTime = targetTime.getTime() - now.getTime();

            console.log(moments.userId + '的动态将在' + delayTime / 1000 / 60 + '分后发布')

            if (delayTime < 0) {
                delayTime == 0
            }
            setTimeout(async () => {
                moments.isPush = true
                moments.createdAt = new Date()
                await this.momentsRepository.save(moments)
                const chatRole = await this.chatRoleRepository.findOneBy({ id: moments.userId })
                chatRole.dynamicNumber += 1
                await this.chatRoleRepository.save(chatRole)
            }, delayTime)

        })
    }


}