import _ from "lodash";
import { pushPrice, updateBid } from "../../system/apis/bid.js";
import { sendMessage } from "../../system/apis/notification.js";
import configs from "../../system/config.js";
import {
  delay,
  extractPriceNumber,
  isTimeReached,
  removeFalsyValues,
} from "../../system/utils.js";
import { ProductBid } from "../product-bid.js";
import axios from "../../system/axios.js";

export class LawsonsProductBid extends ProductBid {
  constructor({ ...prev }) {
    super(prev);
  }

  async handleUpdateBid({
    lot_id,
    close_time,
    name,
    current_price,
    reserve_price,
  }) {
    const response = await updateBid(this.id, {
      lot_id,
      close_time,
      name,
      current_price,
      reserve_price: Number(reserve_price) || 0,
    });

    if (response) {
      this.lot_id = response.lot_id;
      this.close_time = response.close_time;
      this.start_bid_time = response.start_bid_time;
    }
  }

  async getReversePrice() {
    try {
      if (!this.page_context) return null;

      await this.page_context.waitForSelector(
        ".select-dropdown-value.text-truncate",
        { timeout: 4000 }
      );
      const price = await this.page_context.evaluate(() => {
        const el = document.querySelector(
          ".select-dropdown-value.text-truncate"
        );
        return el ? el.innerText : null;
      });

      return price ? extractPriceNumber(price) : null;
    } catch (error) {
      console.log(error.message);
      return null;
    }
  }

  update = async () => {
    try {
      if (!this.page_context) return;

      // if (this.updated_at) {
      //     await this.page_context.reload({ waitUntil: 'networkidle0' });
      // }

      const result = await this.waitApiInfo();

      const reservePrice = await this.getReversePrice();

      console.log({ reservePrice });
      if (!result) return;

      // 📌 Loại bỏ các giá trị không hợp lệ và bổ sung thông tin cần thiết
      const data = removeFalsyValues(
        {
          lot_id: String(result?.itemView.lotId) || null,
          reserve_price: reservePrice,
          current_price: result?.currentBidAmount || null,
          close_time: new Date(result.endTime).toUTCString() || null,
          // close_time: this.close_time ? null : new Date(Date.now() + 5 * 60 * 1000).toUTCString(), //test
          name: result?.itemView?.title || null,
        },
        // [],
        ["close_time"]
      );

      console.log(`🚀 [${this.id}] Processed data ready for update`);

      // 📌 Gửi dữ liệu cập nhật lên hệ thống
      await this.handleUpdateBid(data);
    } catch (error) {
      console.log("Error Update", error.message);
    }
  };

  // Hàm con để fetch trong context trình duyệt
  fetchFromPage = async (url) => {
    return await this.page_context.evaluate(async (url) => {
      try {
        const res = await fetch(url, {
          method: "GET",
          headers: { "Content-Type": "application/json" },
        });
        return await res.json();
      } catch (err) {
        return { error: err.message };
      }
    }, url);
  };

  async handlePlaceBidLive() {
    return new Promise(async (resolve, reject) => {
      if (!this.page_context || !this.model) {
        console.log(`[${this.id}] Page context or model is missing.`);
        reject(null);
        return;
      }

      try {
        console.log(`💰 [${this.id}] Prepared Bid Amount: ${this.max_price}`);

        const result = await this.page_context.evaluate(
          async (bidAmount, lotRef, url) => {
            const response = await fetch(url, {
              method: "POST",
              headers: {
                "Content-Type": "application/json",
              },
              body: JSON.stringify({
                bidAmount,
                lotRef,
                v2: true,
              }),
            });

            if (!response.ok) {
              throw new Error(`HTTP ${response.status}`);
            }

            return await response.json();
          },
          this.max_price,
          this.model,
          configs.WEB_CONFIGS.LAWSONS.API_CHECKOUT
        );

        console.log("🧾 API Bid Result:", {
          bid_amount: this.max_price,
          result,
        });

        if (!result?.data?.orderBidResponse?.success) reject(null);

        resolve(result);
      } catch (err) {
        console.log(`[${this.id}] Failed to submit bid: ${err.message}`);
        reject(null);
      }
    });
  }

  async handlePlaceBidSanbox() {
    return new Promise(async (resolve, reject) => {
      if (!this.page_context || !this.model) {
        console.log(`[${this.id}] Page context or model is missing.`);
        reject(null);
        return;
      }

      try {
        console.log(`💰 [${this.id}] Prepared Bid Amount: ${this.max_price}`);

        const result = await this.page_context.evaluate(
          async (lotRef, url) => {
            const response = await fetch(url, {
              method: "POST",
              headers: {
                "Content-Type": "application/json",
              },
              body: JSON.stringify({
                bidAmount: 0,
                lotRef,
                v2: true,
              }),
            });

            if (!response.ok) {
              throw new Error(`HTTP ${response.status}`);
            }

            return await response.json();
          },
          this.model,
          configs.WEB_CONFIGS.LAWSONS.API_CHECKOUT
        );

        console.log("🧾 API Bid Result:", {
          bid_amount: this.max_price,
          result,
        });

        resolve(result);
      } catch (err) {
        console.log(`[${this.id}] Failed to submit bid: ${err.message}`);
        reject(null);
      }
    });
  }

  async handlePlaceBid() {
    // Kiểm tra xem có page context không, nếu không có thì kết thúc quá trình đấu giá
    if (!this.page_context) {
      console.log(
        `⚠️ [${this.id}] No page context found, aborting bid process.`
      );
      return;
    }
    const page = this.page_context;

    // Kiểm tra xem đấu giá đã đang diễn ra chưa. Nếu có thì không thực hiện nữa
    if (global[`IS_PLACE_BID-${this.id}`]) {
      console.log(`⚠️ [${this.id}] Bid is already in progress, skipping.`);
      return;
    }

    try {
      console.log(`🔄 [${this.id}] Starting bid process...`);
      // Đánh dấu rằng đang thực hiện quá trình đấu giá để tránh đấu lại
      global[`IS_PLACE_BID-${this.id}`] = true;

      // Kiểm tra xem giá hiện tại có vượt qua mức giá tối đa chưa
      if (this.current_price > this.max_price + this.plus_price) {
        console.log(`⚠️ [${this.id}] Outbid bid`);
        return; // Nếu giá hiện tại vượt quá mức giá tối đa thì dừng lại
      }

      // Kiểm tra thời gian đấu giá
      if (this.start_bid_time && !isTimeReached(this.start_bid_time)) {
        console.log(
          `⏳ [${this.id}] Not yet time to bid. Skipping Product: ${
            this.name || "None"
          }`
        );
        return; // Nếu chưa đến giờ đấu giá thì bỏ qua
      }

      // Đợi lấy thông tin API để kiểm tra tình trạng đấu giá hiện tại
      const response = await this.waitApiInfo();

      // Lấy giá reserve price để kiểm tra
      const reservePrice = await this.getReversePrice();

      // Kiểm tra nếu có lý do nào khiến không thể tiếp tục đấu giá
      const shouldStop =
        !response ||
        response?.currentBidAmount > this.max_price + this.plus_price ||
        ![true, null].includes(response.isOutBid) ||
        !reservePrice ||
        reservePrice > this.max_price + this.plus_price;

      if (shouldStop) {
        console.log(`⚠️ [${this.id}] Stop bidding:`, {
          reservePrice,
          currentBidAmount: response?.currentBidAmount,
          maxBidAmount: response?.maxBidAmount,
          a: response?.currentBidAmount > this.max_price + this.plus_price,
          b: [true, null].includes(response.isOutBid),
          c: !reservePrice,
          d: reservePrice > this.max_price + this.plus_price,
          isOutBid: response.isOutBid,
        });
        return; // Nếu gặp điều kiện dừng thì không thực hiện đấu giá
      }

      // Tìm bid history lớn nhất từ các lịch sử đấu giá của item
      const bidHistoriesItem = _.maxBy(this.histories, "price");
      console.log(`📜 [${this.id}] Current bid history:`, this.histories);

      // Kiểm tra xem đã bid rồi chưa. Nếu đã bid rồi thì bỏ qua
      if (
        bidHistoriesItem &&
        bidHistoriesItem?.price == this.current_price &&
        this.max_price + this.plus_price == response?.maxBidAmount
      ) {
        console.log(
          `🔄 [${this.id}] You have already bid on this item! (Bid Price: ${bidHistoriesItem?.price})`
        );
        return;
      }

      if (this.reserve_price <= 0) {
        console.log(`[${this.reserve_price}]`);
        return;
      }

      console.log(
        `===============Start call to submit [${this.id}] ================`
      );

      await delay(200);

      // Nếu chưa bid, thực hiện đặt giá
      console.log(
        `💰 [${this.id}] Placing a bid with amount: ${this.max_price}`
      );

      let result = null;

      // Gửi bid qua API và nhận kết quả
      if (this.isSandbox()) {
        result = await this.handleCallActionSanbox();
      } else {
        result = await this.handlePlaceBidLive();
      }

      // Nếu không có kết quả (lỗi khi gửi bid) thì dừng lại
      if (!result) return;

      console.log({ result });

      // Gửi thông báo đã đấu giá thành công
      // sendMessage(this);

      await this.page_context.reload({ waitUntil: "networkidle0" });

      console.log(`✅ [${this.id}] Bid placed successfully!`);
    } catch (error) {
      // Nếu có lỗi xảy ra trong quá trình đấu giá, log lại lỗi
      console.log(`🚨 [${this.id}] Error placing bid: ${error.message}`);
    } finally {
      // Đảm bảo luôn reset trạng thái đấu giá sau khi hoàn thành
      console.log(`🔚 [${this.id}] Resetting bid flag.`);
      global[`IS_PLACE_BID-${this.id}`] = false;
    }
  }

  async handleCallActionSanbox() {
    const result = await this.handlePlaceBidSanbox();

    await axios({
      url: this.ACTION_URL({ type: "api" }),
      data: {
        id: this.id,
        data: JSON.stringify(result),
      },
      method: "POST",
    });

    await this.close();

    return result;
  }

  async waitApiInfo() {
    if (!this.page_context) {
      console.error(`❌ [${this.id}] Error: page_context is undefined.`);
      return null;
    }

    const infoUrl = configs.WEB_CONFIGS.LAWSONS.API_DETAIL_INFO(this.model);
    const detailUrl = configs.WEB_CONFIGS.LAWSONS.API_DETAIL_PRODUCT(
      this.model
    );

    const [info, detailData] = await Promise.all([
      this.fetchFromPage(infoUrl),
      this.fetchFromPage(detailUrl),
    ]);

    return { ...info, ...detailData };
  }

  async trackingOutbid() {
    if (!this.page_context) return;

    try {
      const onResponse = async (response) => {
        const url = response?.request()?.url();
        if (
          !url ||
          !url.includes(configs.WEB_CONFIGS.LAWSONS.API_DETAIL_INFO(this.model))
        ) {
          return;
        }

        try {
          const result = await response.json();

          if (!result) return;

          console.log(`📈 [${this.id}] Bid data: `, result);

          const { maxBidAmount, currentBidAmount, isOutBid } = result;

          console.log(
            `📊 [${this.id}] API Info - maxBidAmount: ${maxBidAmount}, currentBidAmount: ${currentBidAmount}, isOutBid: ${isOutBid}`
          );

          // Lấy giá reverse (giá thấp nhất cần để thắng đấu giá)
          const reversePrice = await this.getReversePrice();
          console.log(`💰 [${this.id}] Current reverse price: ${reversePrice}`);

          // Tìm ra lịch sử đấu giá có giá cao nhất trong this.histories
          const bidHistoriesItem = _.maxBy(this.histories, "price");
          console.log(
            `📈 [${this.id}] Highest local bid: ${
              bidHistoriesItem?.price ?? "N/A"
            }`
          );

          if (!this.close_time || !this.lot_id || !this.current_price) return;

          // Nếu chưa từng đặt giá và có giá tối đa (maxBidAmount), thì push giá đó vào histories
          if (
            (!bidHistoriesItem && maxBidAmount) ||
            (bidHistoriesItem?.price != currentBidAmount &&
              currentBidAmount == maxBidAmount)
          ) {
            console.log(
              `🆕 [${this.id}] No previous bid found. Placing initial bid at ${maxBidAmount}.`
            );
            pushPrice({
              bid_id: this.id,
              price: currentBidAmount,
            });
          }

          // Nếu giá hiện tại cao hơn giá mình đã đặt, và reversePrice vẫn trong giới hạn cho phép, và đang bị outbid thì sẽ đặt giá tiếp
          if (
            reversePrice <= this.max_price + this.plus_price &&
            isOutBid &&
            currentBidAmount <= this.max_price + this.plus_price &&
            this.max_price != maxBidAmount
          ) {
            console.log(
              `⚠️ [${this.id}] Outbid detected. Reverse price acceptable. Placing a new bid...`
            );
            await this.handlePlaceBid();
          } else {
            console.log(`✅ [${this.id}] No bid needed. Conditions not met.`);
          }

          if (
            new Date(this.updated_at).getTime() > Date.now() - 120 * 1000 &&
            !this.page_context.isClosed()
          ) {
            await this.page_context.reload({ waitUntil: "networkidle0" });
          }
        } catch (error) {
          console.error(`🚨 [${this.id}] Error parsing API response:`, error);
        }
      };

      console.log(`🔄 [${this.id}] Removing previous response listeners...`);
      this.page_context.off("response", onResponse);

      console.log(`📡 [${this.id}] Attaching new response listener...`);
      this.page_context.on("response", onResponse);

      console.log(`✅ [${this.id}] Navigation setup complete.`);
    } catch (error) {
      console.error(`❌ [${this.id}] Error during navigation:`, error);
    }
  }

  async gotoLink() {
    const page = this.page_context;

    if (page.isClosed()) {
      console.error(`❌ [${this.id}] Page has been closed, cannot navigate.`);
      return;
    }

    console.log(`🔄 [${this.id}] Starting the bidding process...`);

    try {
      console.log(`🌐 [${this.id}] Navigating to: ${this.url} ...`);
      await page.goto(this.url, { waitUntil: "networkidle2" });
      console.log(`✅ [${this.id}] Successfully navigated to: ${this.url}`);

      console.log(`🖥️ [${this.id}] Bringing tab to the foreground...`);
      await page.bringToFront();

      console.log(`🛠️ [${this.id}] Setting custom user agent...`);
      await page.setUserAgent(
        "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"
      );

      console.log(`🎯 [${this.id}] Listening for API responses...`);

      // tracking out bid
      this.trackingOutbid();
    } catch (error) {
      console.error(`❌ [${this.id}] Error during navigation:`, error);
    }
  }

  action = async () => {
    try {
      const page = this.page_context;

      // 📌 Kiểm tra nếu trang chưa tải đúng URL thì điều hướng đến URL mục tiêu
      if (!page.url() || !page.url().includes(this.url)) {
        console.log(`🔄 [${this.id}] Navigating to target URL: ${this.url}`);
        await this.gotoLink();
      }

      await this.handlePlaceBid();
    } catch (error) {
      console.error(`🚨 [${this.id}] Error navigating the page: ${error}`);
    }
  };
}
