import {
  pushPrice,
  updateBid,
  updateStatusByPrice,
} from "../../system/apis/bid.js";
import axios from "../../system/axios.js";
import {
  delay,
  extractNumber,
  isTimeReached,
  removeFalsyValues,
} from "../../system/utils.js";
import { ProductBid } from "../product-bid.js";

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

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

      await this.page_context.waitForSelector("#lot-closing-datetime", {
        timeout: 3000,
      });

      return await this.page_context.$eval(
        "#lot-closing-datetime",
        (el) => el.value
      );
    } catch (error) {
      return null;
    }
  };

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

      await this.page_context.waitForSelector(
        "#biddableLot form div div:nth-child(1) span span",
        { timeout: 3000 }
      );

      const element = await this.page_context.$(
        "#biddableLot form div div:nth-child(1) span span"
      );

      const textPrice = await this.page_context.evaluate(
        (el) => el.textContent,
        element
      );

      return extractNumber(textPrice) || null;
    } catch (error) {
      return null;
    }
  };

  async isCloseProduct() {
    const close_time = await this.getCloseTime();

    const currentUrl = await this.page_context.url();

    if (currentUrl !== this.url) {
      return { result: false, close_time };
    }

    if (!close_time) {
      const priceWasBid = await this.getPriceWasBid();

      await updateStatusByPrice(this.id, priceWasBid);
      return { result: true, close_time: null };
    }

    await delay(500);

    if (!close_time || new Date(close_time).getTime() <= new Date().getTime()) {
      console.log(`❌ [${this.id}] Product is close ${close_time}`);
      return { result: true, close_time };
    }

    return { result: false, close_time };
  }

  async placeBid() {
    try {
      await this.page_context.evaluate(() => {
        document.querySelector("#price").value = "";
      });
      console.log("✅ Cleared price");

      await this.page_context.type("#price", String(this.max_price));
      console.log("✅ Typed max price");
      await delay(5000);

      const currentValue = await this.page_context.$eval(
        "#price",
        (el) => el.value
      );

      console.log("✅ Checked currentValue:", currentValue);

      if (currentValue !== String(this.max_price)) {
        console.warn(
          `[${this.id}] Value not match #price: ${currentValue} !== ${this.max_price}`
        );
        return;
      }

      await this.page_context.click("#btnSubmit");
      console.log("✅ Clicked submit");
      await delay(1000);

      await this.page_context.waitForSelector("button", { timeout: 5000 });

      await delay(5000);

      // await this.page_context.click("button");

      // await this.page_context.waitForNavigation({ timeout: 5000 });

      // await this.page_context.waitForFunction(
      //   () => document.body.innerText.includes("Successfully"),
      //   { timeout: 5000 } // hoặc lâu hơn nếu cần
      // );
      // console.log("✅ Found 'Successfully'");

      // await pushPrice({
      //   bid_id: this.id,
      //   price: this.max_price,
      // });

      // await this.handleReturnProductPage();

      if (this.isSandbox()) {
        await this.handlePlaceBidSandbox();
      } else {
        await this.handlePlaceBidLive();
      }

      return true;
    } catch (error) {
      await this.page_context.goto(this.url);
      console.log(error);
      console.log(`❌ [${this.id}] Error in placeBid: ${error.message}`);
      return false;
    } finally {
      global.IS_CLEANING = true;
    }
  }

  async handlePlaceBidLive() {
    try {
      global.IS_CLEANING = false;

      await this.page_context.click("button");

      await this.page_context.waitForNavigation({ timeout: 5000 });

      // await this.page_context.waitForFunction(
      //   () => document.body.innerText.includes("Successfully"),
      //   { timeout: 5000 } // hoặc lâu hơn nếu cần
      // );

      console.log("✅ Found 'Successfully'");

      await pushPrice({
        bid_id: this.id,
        price: this.max_price,
      });

      await this.handleReturnProductPage();
    } finally {
      global.IS_CLEANING = true;
    }
  }

  async handlePlaceBidSandbox() {
    // call to trickger server send mail
    await axios({
      url: this.ACTION_URL(),
      method: "POST",
      data: {
        id: this.id,
        record_url: `${process.env.BASE_URL}admin/bids/record/${this.name_record}`,
      },
    });

    await this.close();
  }

  async handleReturnProductPage() {
    await this.page_context.goto(this.url);
    await delay(1000);
  }

  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;
    }
  }

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

    const page = this.page_context;

    try {
      const close_time = await this.getCloseTime();

      // Chờ phần tử xuất hiện trước khi lấy giá trị
      await page
        .waitForSelector("#priceValue", { timeout: 5000 })
        .catch(() => null);
      const price_value = await page
        .$eval("#priceValue", (el) => el.value)
        .catch(() => null);

      await page.waitForSelector("#lotId", { timeout: 5000 }).catch(() => null);
      const lot_id = await page
        .$eval("#lotId", (el) => el.value)
        .catch(() => null);

      await page
        .waitForSelector("#placebid-sticky > div:nth-child(2) > div > h3", {
          timeout: 5000,
        })
        .catch(() => null);
      const name = await page
        .$eval(".dls-heading-3.lotPageTitle", (el) => el.innerText)
        .catch(() => null);

      await page
        .waitForSelector(
          "#biddableLot > form > div > div:nth-child(1) > div:nth-child(1) > div:nth-child(2) > div > span > span",
          { timeout: 5000 }
        )
        .catch(() => null);
      const current_price = await page
        .$eval(
          "#biddableLot > form > div > div:nth-child(1) > div:nth-child(1) > div:nth-child(2) > div > span > span",
          (el) => el.innerText
        )
        .catch(() => null);

      console.log(
        `📌 [${this.id}] Product Info: Lot ID: ${lot_id}, Name: ${name}, Current Price: ${current_price}, Reserve price: ${price_value}`
      );

      const data = removeFalsyValues(
        {
          lot_id,
          reserve_price: price_value,
          close_time: close_time ? String(close_time) : null,
          name,
          current_price: current_price ? extractNumber(current_price) : null,
        },
        ["close_time"]
      );

      this.handleUpdateBid(data);

      return { price_value, lot_id, name, current_price };
    } catch (error) {
      console.error(`🚨 Error updating product info: ${error.message}`);
      return null;
    }
  };

  getCurrentData = async () => {
    if (!this.page_context) return null;

    try {
      // Lấy thời gian đóng
      const close_time = await this.getCloseTime();

      // Giá trị reserve price
      await this.page_context
        .waitForSelector("#priceValue", { timeout: 5000 })
        .catch(() => null);
      const price_value = await this.page_context
        .$eval("#priceValue", (el) => el.value)
        .catch(() => null);

      // Lot ID
      await this.page_context
        .waitForSelector("#lotId", { timeout: 5000 })
        .catch(() => null);
      const lot_id = await this.page_context
        .$eval("#lotId", (el) => el.value)
        .catch(() => null);

      // Tên sản phẩm
      await this.page_context
        .waitForSelector(".dls-heading-3.lotPageTitle", { timeout: 5000 })
        .catch(() => null);
      const name = await this.page_context
        .$eval(".dls-heading-3.lotPageTitle", (el) => el.innerText)
        .catch(() => null);

      // Giá hiện tại
      await this.page_context
        .waitForSelector(
          "#biddableLot > form > div > div:nth-child(1) > div:nth-child(1) > div:nth-child(2) > div > span > span",
          { timeout: 5000 }
        )
        .catch(() => null);
      const current_price_raw = await this.page_context
        .$eval(
          "#biddableLot > form > div > div:nth-child(1) > div:nth-child(1) > div:nth-child(2) > div > span > span",
          (el) => el.innerText
        )
        .catch(() => null);

      const current_price = current_price_raw
        ? extractNumber(current_price_raw)
        : null;

      return removeFalsyValues(
        {
          lot_id,
          reserve_price: Number(price_value) || 0,
          close_time: close_time ? String(close_time) : null,
          name,
          current_price,
        },
        ["close_time"]
      );
    } catch (error) {
      console.error(`🚨 Error fetching current product data: ${error.message}`);
      return null;
    }
  };

  async handlePlaceBid() {
    if (!this.page_context) {
      console.log(
        `⚠️ [${this.id}] No page context found, aborting bid process.`
      );
      return;
    }

    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...`);
      global[`IS_PLACE_BID-${this.id}`] = true;

      // Tắt clearLazyTab vì web này phải navigate để bid
      global.IS_CLEANING = false;

      const isCloseProduct = await this.isCloseProduct();

      if (isCloseProduct.result) {
        console.log(
          `⚠️ [${this.id}] Outbid detected, calling outBid function.`
        );

        await outBid(this.id);

        return;
      }

      const biddedData = this.getBidedData();

      const isBided = (biddedData || []).find(
        (item) => item.model === this.model && item.max_price === this.max_price
      );

      if (isBided) {
        if (this.histories.length <= 0 && isTimeReached(this.start_bid_time)) {
          pushPrice({
            bid_id: this.id,
            price: this.max_price,
          });
        }

        console.log(`[${this.id}] This item bided. Skipping...`);
        global[`IS_PLACE_BID-${this.id}`] = false;
        global.IS_CLEANING = true;
        return;
      }

      if (!this.start_bid_time || !this.close_time) {
        console.log(
          `[${this.id}] Skipping processing: auction has started but not yet closed.`
        );

        global.IS_CLEANING = true;

        return;
      }

      // Kiểm tra nếu giá hiện tại lớn hơn giá tối đa cộng thêm giá cộng thêm
      if (this.current_price > this.max_price + this.plus_price) {
        console.log(`⚠️ [${this.id}] Outbid bid`); // Ghi log cảnh báo nếu giá hiện tại vượt quá mức tối đa cho phép

        global.IS_CLEANING = true;

        return; // Dừng hàm nếu giá đã vượt qua giới hạn
      }

      // Kiểm tra thời gian bid
      if (this.start_bid_time && !isTimeReached(this.start_bid_time)) {
        console.log(
          `⏳ [${this.id}] Not yet time to bid. Skipping Product: ${
            this.name || "None"
          }`
        );
        global.IS_CLEANING = true;

        return;
      }

      if (this.histories.length > 0) {
        console.log(
          `[${this.id}] Already biding with price ${this.histories[0].price}`
        );
        return;
      }

      console.log(
        "-------------------------------------BIDING---------------------------------------"
      );

      await this.startRecordSandbox();
      const result = await this.placeBid();

      global.IS_CLEANING = true;
      global[`IS_PLACE_BID-${this.id}`] = false;
    } catch (error) {
      console.log(`🚨 [${this.id}] Error placing bid: ${error.message}`);
    } finally {
      await this.stopRecordSandbox();
      console.log(`🔚 [${this.id}] Resetting bid flag.`);
    }
  }

  getBidedData() {
    return global[`BIDED_DATA_${this.web_bid?.origin_url}`];
  }

  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.message}`
      );
    }
  };
}
