import {
  BadRequestException,
  HttpStatus,
  Injectable,
  NotFoundException,
} from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { plainToClass } from 'class-transformer';
import AppResponse from 'src/response/app-response';
import { Repository } from 'typeorm';
import { BidHistory } from '../entities/bid-history.entity';
import { Bid } from '../entities/bid.entity';
import { CreateBidHistoryDto } from '../dto/bid-history/create-bid-history.dto';
import { BotTelegramApi } from '../apis/bot-telegram.api';
import { SendMessageHistoriesService } from './send-message-histories.service';
import { NotificationService } from '@/modules/notification/notification.service';
import { isTimeReached } from '@/ultils';
import { BidsService } from './bids.service';
import { EventEmitter2 } from '@nestjs/event-emitter';
import { Event } from '../utils/events';

@Injectable()
export class BidHistoriesService {
  constructor(
    @InjectRepository(BidHistory)
    readonly bidHistoriesRepo: Repository<BidHistory>,
    // @InjectRepository(Bid)
    // readonly bidsRepo: Repository<Bid>,
    private readonly botTelegramApi: BotTelegramApi,
    readonly sendMessageHistoriesService: SendMessageHistoriesService,
    private readonly notificationService: NotificationService,
    private readonly bidsService: BidsService,
    private eventEmitter: EventEmitter2,
  ) {}

  async index() {
    return this.bidHistoriesRepo.find();
  }

  async create({ price, bid_id }: CreateBidHistoryDto) {
    // Tìm thông tin bid từ database
    const bid = await this.bidsService.bidsRepo.findOne({
      where: { id: bid_id },
      relations: { web_bid: true },
    });

    // Nếu không tìm thấy bid, trả về lỗi 404
    if (!bid)
      throw new NotFoundException(
        AppResponse.toResponse(null, {
          message: 'Not found bid',
          status_code: HttpStatus.NOT_FOUND,
        }),
      );

    // Lấy lịch sử đặt giá cao nhất trước đó của bid hiện tại
    const lastHistory = await this.bidHistoriesRepo.findOne({
      where: { bid: { id: bid_id } },
      order: { price: 'desc' },
    });

    // Nếu đã có lịch sử và giá mới giống với giá cao nhất hiện tại
    if (lastHistory && lastHistory.price === price) {
      // Nếu đã hết thời gian đấu giá, cập nhật trạng thái là 'win-bid'
      if (isTimeReached(bid.close_time)) {
        this.bidsService.bidsRepo.update(bid_id, { status: 'win-bid' });
      }

      // Ném lỗi không cho đặt giá trùng lặp
      throw new BadRequestException(
        AppResponse.toResponse(null, { message: 'Duplicate place bid' }),
      );
    }

    // Nếu tổng giá vượt quá mức tối đa cho phép
    if (price + bid.plus_price > bid.max_price) {
      // Cập nhật trạng thái bid là 'out-bid'
      this.bidsService.bidsRepo.update(bid_id, { status: 'out-bid' });

      // Gửi thông báo trạng thái mới qua service thông báo
      this.notificationService.emitBidStatus({ ...bid, status: 'out-bid' });

      // Ném lỗi không cho đặt giá vượt mức
      throw new BadRequestException(
        AppResponse.toResponse(null, {
          message: 'Price is more than Max price ' + bid.max_price,
        }),
      );
    }

    // Lưu lịch sử đặt giá mới
    await this.bidHistoriesRepo.save({ bid, price });

    // Lấy danh sách tất cả lịch sử đặt giá theo thứ tự mới nhất
    const response = await this.bidHistoriesRepo.find({
      where: { bid: { id: bid_id } },
      order: {
        created_at: 'DESC',
      },
    });

    // Nếu đây là lần đặt giá đầu tiên, cập nhật cờ `first_bid` thành false
    if (response.length === 1) {
      this.bidsService.bidsRepo.update(bid_id, { first_bid: false });
    }

    // Gửi thông tin bid đến bot telegram
    const botData = { ...bid, histories: response };
    // this.botTelegramApi.sendBidInfo(botData);

    // Send event thống place bid
    this.eventEmitter.emit(Event.BID_SUBMITED, botData);

    // Lưu message đã gửi để theo dõi
    this.sendMessageHistoriesService.sendMessageRepo.save({
      message: this.botTelegramApi.formatBidMessage(botData),
      bid,
    });

    // Kiểm tra nếu trạng thái bid thay đổi sau khi lưu, phát sự kiện cập nhật tất cả bid
    const bidUpdated = await this.bidsService.bidsRepo.findOne({
      where: { id: bid_id },
    });

    this.bidsService.emitAllBidEvent();

    // Trả về danh sách lịch sử đặt giá đã cập nhật
    return AppResponse.toResponse(plainToClass(BidHistory, response));
  }
}
