import { Injectable } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import axios from 'axios';
import * as dayjs from 'dayjs';
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'fs';
import { join } from 'path';
import { Bid } from '../entities/bid.entity';
import { Constant } from '../utils/constant';

@Injectable()
export class BotTelegramApi {
  private readonly botToken: string;
  private readonly apiUrl: string;

  constructor(private readonly configService: ConfigService) {
    this.botToken = this.configService.get<string>('TELEGRAM_BOT_TOKEN');
    this.apiUrl = `https://api.telegram.org/bot${this.botToken}`;
  }

  formatBidMessage(bid: Bid) {
    return `<b>📢 New Bid Alert!</b>\n
    <b>📌 Product:</b> ${bid.name ? `<b>${bid.name}</b>` : '_No name_'}\n
    <b>💰 Current Price:</b> <code>${bid.current_price.toLocaleString()}${bid.plus_price ? ` (+${bid.plus_price.toLocaleString()})` : ''}</code>\n
    <b>🏆 Max Price:</b> <code>${bid.max_price.toLocaleString()}</code>\n
    <b>🔖 Starting Price:</b> <code>${bid.reserve_price.toLocaleString()}</code>\n\n
    <b>📦 Model:</b> <code>${bid.model || 'None'}</code>\n
    <b>🔢 Quantity:</b> <code>${bid.quantity}</code>\n
    <b>🆔 Lot ID:</b> <code>${bid.lot_id ? bid.lot_id.toString() : 'None'}</code>\n\n
    <b>⏳ Closing Time:</b> ${bid.close_time ? `<code>${dayjs(bid.close_time).format('HH:mm:ss DD/MM/YYYY')}</code>` : '_Not available_'}\n
    <b>🚀 Start Time:</b> ${bid.start_bid_time ? `<code>${dayjs(bid.start_bid_time).format('HH:mm:ss DD/MM/YYYY')}</code>` : '_Not available_'}\n\n
    <b>📈 Bid History:</b>\n${
      bid.histories.length > 0
        ? bid.histories
            .map(
              (h, index) =>
                `  ${index + 1}. 💵 <code>${index === 0 ? '🔴' : ''}${h.price.toLocaleString()}</code> 🕒 <code>${dayjs(h.updated_at).format('HH:mm:ss DD/MM/YYYY')}</code>`,
            )
            .join('\n')
        : '_No bid history yet_'
    }\n\n
    <b>📝 Status:</b> <code>${bid.status.replace('-', ' ')}</code>\n\n
    ⬇️ <b>View Details:</b> <a href="${bid.url}">Click here</a>`;
  }

  async sendMessage(
    text: string,
    bonusBody: Record<string, any> = {},
    chatId: string = this.configService.get<string>('CHAT_ID'),
  ): Promise<void> {
    try {
      const url = `${this.apiUrl}/sendMessage`;
      const response = await axios.post(
        url,
        {
          chat_id: chatId,
          text: text,
          ...bonusBody,
        },
        {
          family: 4,
        },
      );
    } catch (error) {
      console.error('Error sending message:', error || error.message);
    }
  }

  async createFolderPath(): Promise<string> {
    const rootDir = process.cwd();
    const folderPath = join(rootDir, `${Constant.BOT_TELEGRAM_PATH}`);

    if (!existsSync(folderPath)) {
      mkdirSync(folderPath, { recursive: true, mode: 0o777 });

      // ✅ Lưu metadata lần đầu
      const metadataPath = join(folderPath, 'metadata.json');
      writeFileSync(
        metadataPath,
        JSON.stringify({ createdAt: Date.now() }),
        'utf-8',
      );
    }

    return folderPath;
  }

  async getGroupInfo(
    chatId: string = this.configService.get<string>('CHAT_ID'),
  ): Promise<any> {
    try {
      const folderPath = await this.createFolderPath();
      const metadataPath = join(folderPath, 'metadata.json');
      const dataFilePath = join(folderPath, `group_${chatId}.json`);

      // 10 minute
      const TIME_TO_REFRESH_DATA = 10;

      if (existsSync(metadataPath)) {
        const metadata = JSON.parse(readFileSync(metadataPath, 'utf-8'));
        const createdAt = metadata?.createdAt || 0;
        const now = Date.now();
        const diffMinutes = (now - createdAt) / 60000;

        if (diffMinutes < TIME_TO_REFRESH_DATA && existsSync(dataFilePath)) {
          return JSON.parse(readFileSync(dataFilePath, 'utf-8'));
        }
      }

      const url = `${this.apiUrl}/getChat`;
      const { data } = await axios({
        url,
        params: { chat_id: chatId },
        family: 4,
      });

      if (data?.ok) {
        writeFileSync(
          dataFilePath,
          JSON.stringify(data.result, null, 2),
          'utf-8',
        );
        writeFileSync(
          metadataPath,
          JSON.stringify({ createdAt: Date.now() }),
          'utf-8',
        );

        return data.result;
      }
    } catch (error) {
      console.error(error || error.message);
    }
  }

  async sendBidInfo(bid: Bid): Promise<boolean> {
    try {
      const text = this.formatBidMessage(bid);

      await this.sendMessage(text, {
        parse_mode: 'HTML',
      });

      return true;
    } catch (error) {
      console.log('SEND MESSAGE FAILURE');
      return false;
    }
  }
}
