/* eslint-disable @typescript-eslint/no-explicit-any */
import { delay, delayRD } from "@/features/app";
import { thiefService } from "./thief.service";
import { productApi } from "@/api/product-api.service";

class FacebookService {
  sellingPath = "https://www.facebook.com/marketplace/you/selling";

  selectors = {
    file__image_input: 'input[type="file"]',
    title_input:
      "/html/body/div[1]/div/div[1]/div/div[3]/div/div/div[1]/div[1]/div[1]/div/div[2]/div[1]/div[2]/div/div/div[5]/div/div/div/label/div/input",
    price_input:
      "/html/body/div[1]/div/div[1]/div/div[3]/div/div/div[1]/div[1]/div[1]/div/div[3]/div[1]/div[2]/div/div/div[6]/div/div/div/label/div/input",
    brand_input:
      "/html/body/div[1]/div/div[1]/div/div[3]/div/div/div[1]/div[1]/div[1]/div/div[3]/div[1]/div[2]/div/div/div[9]/div/div/div[2]/div/div/div/label/div/input",
    brand_input_fallback:
      "/html/body/div[1]/div/div[1]/div/div[3]/div/div/div[1]/div[1]/div[1]/div/div[3]/div[1]/div[2]/div/div/div[10]/div/div/div[2]/div/div/div/label/div/input",
    description_input:
      "/html/body/div[1]/div/div[1]/div/div[3]/div/div/div[1]/div[1]/div[1]/div/div[3]/div[1]/div[2]/div/div/div[9]/div/div/div[3]/div/div/div/label/div/div/textarea",
    description_input_falback:
      "/html/body/div[1]/div/div[1]/div/div[3]/div/div/div[1]/div[1]/div[1]/div/div[3]/div[1]/div[2]/div/div/div[10]/div/div/div[3]/div/div/div/label/div/div/textarea",
    sku_input:
      "/html/body/div[1]/div/div[1]/div/div[3]/div/div/div[1]/div[1]/div[1]/div/div[3]/div[1]/div[2]/div/div/div[9]/div/div/div[6]/div/div/div[1]/label/div/input",
    sku_input_fallback:
      "/html/body/div[1]/div/div[1]/div/div[3]/div/div/div[1]/div[1]/div[1]/div/div[3]/div[1]/div[2]/div/div/div[10]/div/div/div[6]/div/div/div[1]/label/div/input",
    category_select: {
      wraper:
        "/html/body/div[1]/div/div[1]/div/div[3]/div/div/div[1]/div[1]/div[1]/div/div[3]/div[1]/div[2]/div/div/div[7]/div/div/div/div",
      container:
        "/html/body/div[1]/div/div[1]/div/div[3]/div/div/div[2]/div/div/div[1]/div[1]/div/div/div/div/div/span/div",
    },
    condition_select: {
      wraper:
        "/html/body/div[1]/div/div[1]/div/div[3]/div/div/div[1]/div[1]/div[1]/div/div[3]/div[1]/div[2]/div/div/div[8]/div/div/div/div",
      container:
        "/html/body/div[1]/div/div[1]/div/div[3]/div/div/div[2]/div/div/div[1]/div[1]/div/div/div/div/div[1]/div",
    },
    tags_input: {
      input:
        "/html/body/div[1]/div/div[1]/div/div[3]/div/div/div[1]/div[1]/div[1]/div/div[3]/div[1]/div[2]/div/div/div[9]/div/div/div[5]/div/div/div/div[1]/label/div/div/div[2]/div/textarea",
      input_falback:
        "/html/body/div[1]/div/div[1]/div/div[3]/div/div/div[1]/div[1]/div[1]/div/div[3]/div[1]/div[2]/div/div/div[10]/div/div/div[5]/div/div/div/div[1]/label/div/div/div[2]/div/textarea",
      plus_btn:
        "/html/body/div[1]/div/div[1]/div/div[3]/div/div/div[1]/div[1]/div[1]/div/div[3]/div[1]/div[2]/div/div/div[9]/div/div/div[5]/div/div/div/div[1]/label/div/div/div[2]/div[2]",
    },
    tags_edit_input: {
      input:
        "/html/body/div[1]/div/div[1]/div/div[3]/div/div/div[1]/div[1]/div[1]/div/div[3]/div[1]/div[2]/div/div/div[9]/div/div/div[4]/div/div/div/div[1]/label/div/div/div[2]/div[1]/textarea",
      input_falback:
        "/html/body/div[1]/div/div[1]/div/div[3]/div/div/div[1]/div[1]/div[1]/div/div[3]/div[1]/div[2]/div/div/div[10]/div/div/div[5]/div/div/div/div[1]/label/div/div/div[2]/div/textarea",
      plus_btn:
        "/html/body/div[1]/div/div[1]/div/div[3]/div/div/div[1]/div[1]/div[1]/div/div[3]/div[1]/div[2]/div/div/div[9]/div/div/div[5]/div/div/div/div[1]/label/div/div/div[2]/div[2]",
    },

    location_select: {
      input:
        "/html/body/div[1]/div/div[1]/div/div[3]/div/div/div[1]/div[1]/div[1]/div/div[3]/div[1]/div[2]/div/div/div[9]/div/div/div[7]/div/div/div/div/div/div/div/div/label/div[2]/input",
      input_fallback:
        "/html/body/div[1]/div/div[1]/div/div[3]/div/div/div[1]/div[1]/div[1]/div/div[3]/div[1]/div[2]/div/div/div[10]/div/div/div[7]/div/div/div/div/div/div/div/div/label/div[2]/input",
      wraper:
        "/html/body/div[1]/div/div[1]/div/div[3]/div/div/div[1]/div[1]/div[1]/div/div[3]/div[1]/div[2]/div/div/div[9]/div/div/div[7]/div/div/div/div/div/div/div/div",
      container:
        "/html/body/div[1]/div/div[1]/div/div[3]/div/div/div[2]/div/div/div[1]/div[1]/div/ul",
      container_fallback:
        "/html/body/div[1]/div/div[1]/div/div[3]/div/div/div[2]/div/div/div[1]/div[1]/div/ul",
    },
    location_edit_select: {
      input:
        "/html/body/div[1]/div/div[1]/div/div[3]/div/div/div[1]/div[1]/div[1]/div/div[3]/div[1]/div[2]/div/div/div[9]/div/div/div[6]/div/div/div/div/div/div/div/div/label/div[2]/input",
      input_fallback:
        "/html/body/div[1]/div/div[1]/div/div[3]/div/div/div[1]/div[1]/div[1]/div/div[3]/div[1]/div[2]/div/div/div[10]/div/div/div[7]/div/div/div/div/div/div/div/div/label/div[2]/input",
      wraper:
        "/html/body/div[1]/div/div[1]/div/div[3]/div/div/div[1]/div[1]/div[1]/div/div[3]/div[1]/div[2]/div/div/div[9]/div/div/div[7]/div/div/div/div/div/div/div/div",
      container:
        "/html/body/div[1]/div/div[1]/div/div[3]/div/div/div[2]/div/div/div[1]/div[1]/div/ul",
      container_fallback:
        "/html/body/div[1]/div/div[1]/div/div[3]/div/div/div[2]/div/div/div[1]/div[1]/div/ul",
    },
    next_btn:
      "/html/body/div[1]/div/div[1]/div/div[3]/div/div/div[1]/div[1]/div[1]/div/div[5]/div/div/div",
    update_btn:
      "/html/body/div[1]/div/div[1]/div/div[3]/div/div/div[1]/div[1]/div[1]/div/div[4]/div/div/div",
    publish_btn:
      "/html/body/div[1]/div/div[1]/div/div[3]/div/div/div[1]/div[1]/div[1]/div/div[4]/div[2]/div/div",
    products:
      "/html/body/div[1]/div/div[1]/div/div[3]/div/div/div[1]/div[1]/div[2]/div/div/div[2]/div[1]/div/div[2]/div/div/span/div/div",
    products_fallback:
      "/html/body/div[1]/div/div[1]/div/div[3]/div/div/div[1]/div[1]/div[2]/div/div/div[2]/div[1]/div/div[2]/div[2]/div",
    option_btn:
      "/html/body/div[1]/div/div[1]/div/div[4]/div/div/div[1]/div/div[2]/div/div/div/div/div/div/div[3]/div/div/div/div/div[1]/div",
    option_btn_fallback:
      "/html/body/div[1]/div/div[1]/div/div[4]/div/div/div[1]/div/div[2]/div/div/div/div[3]/div[2]/div/div[2]/div[1]",
    close_btn_modal_feedback:
      "/html/body/div[1]/div/div[1]/div/div[4]/div/div/div[1]/div/div[2]/div/div/div/div[2]/div",
    images_container:
      "/html/body/div[1]/div/div[1]/div/div[3]/div/div/div[1]/div[1]/div[1]/div/div[2]/div[1]/div[2]/div/div/div[3]/div[2]/div",
    description_edit_input:
      "/html/body/div[1]/div/div[1]/div/div[3]/div/div/div[1]/div[1]/div[1]/div/div[3]/div[1]/div[2]/div/div/div[9]/div/div/div[2]/div/div/div/label/div/div/textarea",
    sku_edit_input:
      "/html/body/div[1]/div/div[1]/div/div[3]/div/div/div[1]/div[1]/div[1]/div/div[3]/div[1]/div[2]/div/div/div[9]/div/div/div[5]/div/div/div[1]/label/div/input",
  };

  clearImages = async () => {
    const el = await thiefService.getElementByXPath(
      this.selectors.images_container
    );

    if (!el) throw new Error(`Can't not found xpath images_container`);

    const children = Array.from(el.children) as HTMLElement[];
    console.log(children);

    // Ví dụ: clear hết
    children.forEach((child) =>
      (child.querySelector('[aria-label="Remove"]') as any)?.click()
    );
  };

  uploadImages = async (item: IItem) => {
    // Tạo DataTransfer để giả lập FileList
    const dt: DataTransfer = new DataTransfer();

    for (const image of item.images) {
      const base64 = await thiefService.imageUrlToBase64(image);

      console.log("Base64:", image.slice(0, 50) + "...");
      const file = thiefService.base64ToFile(
        base64,
        item.sku,
        thiefService.getImageExtension(image) || "jpg"
      );

      dt.items.add(file);
    }

    // Tìm input file của Facebook
    const input: HTMLInputElement | null = document.querySelector(
      this.selectors.file__image_input
    );

    if (input) {
      // Gán file vào input
      input.files = dt.files;

      // Gửi event change
      input.dispatchEvent(new Event("change", { bubbles: true }));
    } else {
      console.error("Không tìm thấy input[type='file']");
    }
  };

  chooseSelect = async (
    value: string,
    xpaths: { wraper: string; container: string }
  ) => {
    const el = await thiefService.getElementByXPath(xpaths.wraper);
    if (!el) throw new Error("Wrapper xpath not found");

    thiefService.scrollToElement(el);
    thiefService.clickByPoint(el);

    await delayRD(300, 500);

    const container = await thiefService.getElementByXPath(xpaths.container);
    if (!container) throw new Error("Container xpath not found");

    // Tìm phần tử con có nội dung giống value
    const matchingChild = Array.from(container.children).find((child) =>
      child.textContent
        ?.trim()
        .toLocaleLowerCase()
        .replace(/–/g, "-")
        .includes(value.toLocaleLowerCase())
    ) as HTMLElement | undefined;

    if (!matchingChild) throw new Error(`No child found with text "${value}"`);

    thiefService.scrollToElement(matchingChild);

    await delay(200);
    thiefService.clickByPoint(matchingChild);
  };

  chooseLocation = async (
    value: string,
    {
      input,
      ...xpaths
    }: {
      wraper: string;
      container: string;
      container_fallback?: string;
      input: string;
      input_fallback?: string;
    }
  ) => {
    await thiefService.writeToInput(value, input, xpaths.input_fallback);

    await delay(200);

    const container = await thiefService.getElementByXPath(xpaths.container, {
      xpathFallback: xpaths.container_fallback,
    });
    if (!container) throw new Error("Container xpath not found");

    thiefService.scrollToElement(container);

    // Tìm phần tử con có nội dung giống value
    const matchingChild = Array.from(container.children).find((child) =>
      child.textContent
        ?.trim()
        .toLocaleLowerCase()
        .includes(value.toLocaleLowerCase())
    ) as HTMLElement | undefined;

    if (!matchingChild) throw new Error(`No child found with text "${value}"`);

    thiefService.scrollToElement(matchingChild);

    await delay(200);
    thiefService.clickByPoint(matchingChild);
  };

  writeTags = async (
    tags: string[],
    xpaths: { input: string; input_falback?: string; plus_btn: string }
  ) => {
    const input = await thiefService.getElementByXPath(xpaths.input, {
      xpathFallback: xpaths?.input_falback,
    });

    if (!input) throw new Error("Input is not found");

    thiefService.scrollToElement(input);

    await delay(200);
    for (const tag of tags) {
      await thiefService.writeToInput(tag, xpaths.input, xpaths?.input_falback);

      await delay(200);

      thiefService.pressEnter(input);
    }
  };

  clickNext = async () => {
    const btn = await thiefService.getElementByXPath(this.selectors.next_btn);

    if (!btn) throw new Error("Next button is not found");

    thiefService.clickByPoint(btn);
  };

  clickUpdate = async () => {
    const btn = await thiefService.getElementByXPath(this.selectors.update_btn);

    if (!btn) throw new Error("Next button is not found");

    thiefService.clickByPoint(btn);
  };

  clickPublist = async () => {
    const btn = await thiefService.getElementByXPath(
      this.selectors.publish_btn
    );

    if (!btn) throw new Error("Publist button is not found");

    thiefService.clickByPoint(btn);
  };

  /**
   * B1. Upload images
   * B2. Write title
   * B3. Write price
   * B4. Select category
   * B5. Select condition
   * .....
   */
  handlePublist = async (item: IItem) => {
    console.log({ item });

    await delayRD(1000, 2000);
    // B1. Upload images
    await this.uploadImages(item);

    await delayRD(300, 500);
    // B2. Write title
    thiefService.writeToInput(item.title, this.selectors.title_input);

    await delayRD(300, 500);

    // B3. Write price
    thiefService.writeToInput(String(item.price), this.selectors.price_input);

    await delayRD(300, 500);

    // B4. Select category
    await this.chooseSelect(item.category, this.selectors.category_select);

    await delayRD(300, 500);

    // B5. Select condition
    await this.chooseSelect(item.condition, this.selectors.condition_select);

    if (item.brand) {
      await delayRD(300, 500);

      // B6. Write brand
      await thiefService.writeToInput(
        item.brand,
        this.selectors.brand_input,
        this.selectors.brand_input_fallback
      );
    }

    await delayRD(300, 500);

    // B7. Write description
    await thiefService.writeToInput(
      item.description,
      this.selectors.description_input,
      this.selectors.description_input_falback
    );

    await delayRD(300, 500);

    await this.writeTags(item.tags, this.selectors.tags_input);

    await delayRD(300, 500);

    // B8. Write sku
    await thiefService.writeToInput(
      item.sku,
      this.selectors.sku_input,
      this.selectors.sku_input_fallback
    );

    if (item?.location) {
      await delayRD(300, 500);

      await this.chooseLocation(item.location, this.selectors.location_select);
    }

    await delayRD(300, 500);

    await this.clickNext();

    await delayRD(300, 500);

    await this.clickPublist();

    return true;
  };

  /**
   * B1. Upload images
   * B2. Write title
   * B3. Write price
   * B4. Select category
   * B5. Select condition
   * .....
   */
  handleUpdate = async (item: IItem) => {
    console.log({ item });

    await delayRD(1000, 2000);

    await this.clearImages();

    await delayRD(1000, 2000);

    await this.uploadImages(item);

    await delayRD(1000, 2000);

    thiefService.writeToInput(item.title, this.selectors.title_input);

    await delayRD(300, 500);

    thiefService.writeToInput(String(item.price), this.selectors.price_input);

    await delayRD(300, 500);

    await this.chooseSelect(item.category, this.selectors.category_select);

    await delayRD(300, 500);

    await this.chooseSelect(item.condition, this.selectors.condition_select);

    await delayRD(300, 500);

    await thiefService.writeToInput(
      item.description,
      this.selectors.description_edit_input
    );

    await delayRD(300, 500);

    await this.writeTags(item.tags, this.selectors.tags_edit_input);

    await delayRD(300, 500);

    await thiefService.writeToInput(item.sku, this.selectors.sku_edit_input);

    if (item?.location) {
      await delayRD(300, 500);

      await this.chooseLocation(
        item.location,
        this.selectors.location_edit_select
      );
    }

    await delayRD(300, 500);

    await this.clickUpdate();

    return true;
  };

  getProducts = async () => {
    const products1 = await thiefService.getElementByXPath(
      this.selectors.products
    );
    const products2 = await thiefService.getElementByXPath(
      this.selectors.products_fallback
    );

    // Gom 2 cái vào một mảng, bỏ null
    const allProductsEls = [products1, products2].filter(
      Boolean
    ) as HTMLElement[];

    if (allProductsEls.length === 0) return [];

    // Nối tất cả kết quả extractListings từ mỗi element
    return allProductsEls.flatMap((el) =>
      this.extractListings(el)
    ) as ISyncItem[];
  };

  extractListings(productsEl: HTMLElement) {
    const children = Array.from(productsEl.children);

    return children.map((child) => {
      // Lấy title
      const titleEl = child.querySelector('span[dir="auto"], div[dir="auto"]');
      const title = titleEl?.textContent?.trim() || "";

      // Lấy giá
      const priceEl = Array.from(
        child.querySelectorAll('span[dir="auto"]')
      ).find(
        (el) =>
          /\d/.test(el.textContent || "") && /[AU$]/.test(el.textContent || "")
      );

      const priceMatch = priceEl?.textContent?.match(/[\d,]+(?:\.\d+)?/);
      const price = priceMatch
        ? parseFloat(priceMatch[0].replace(/,/g, ""))
        : 0;

      return { title, price, el: productsEl };
    });
  }

  closeTab = async (data: IItem) => {
    chrome.runtime.sendMessage({
      type: "close-tab",
      payload: data,
    });
  };

  clickOptionOfProduct(el: HTMLElement, data: IItem) {
    // Tìm nút "More options" cho sản phẩm đó
    const optionEl = el.querySelector(
      `[aria-label="More options for ${data.title}"]`
    );

    if (!optionEl)
      throw new Error(
        `Not found option buttin in product ${data.title}, ID: ${data.id}`
      );

    // Click vào nút "More options" để mở menu
    (optionEl as any).click?.();
  }

  async getOptionEls(el: HTMLElement, data: IItem) {
    this.clickOptionOfProduct(el, data);

    // Delay 2 giây để menu hiển thị hoàn toàn
    await delay(2000);

    // Lấy tất cả các item trong menu (thường là 'Edit', 'Delete', ...)
    const items = Array.from(document.querySelectorAll('[role="menuitem"]'));

    return items;
  }

  clickItemInList(items: Element[], innerText: string) {
    // Tìm item chứa chữ "delete"
    const item = items.find((item) =>
      item.textContent.toLocaleLowerCase().includes(innerText)
    );

    if (!item) throw new Error(`Not found item ${innerText} in options list`);

    // Click vào item "Delete"
    (item as any).click?.();
  }

  getItemInList(items: Element[], innerText: string) {
    // Tìm item chứa chữ "delete"
    const item = items.find((item) =>
      item.textContent.toLocaleLowerCase().includes(innerText)
    );

    if (!item) throw new Error(`Not found item ${innerText} in options list`);

    return item;
  }

  handleDelete = async (payload: IItem) => {
    // Lấy tất cả sản phẩm hiện tại trên Facebook Marketplace
    const products = await facebookService.getProducts();

    // Tìm sản phẩm khớp với title và price từ payload
    const product = products.find((product) => {
      return product.title == payload.title && product.price == payload.price;
    });

    console.log({ payload, product, products });

    // Nếu không tìm thấy sản phẩm nào khớp thì kết thúc
    if (!product) return;

    const el = product.el; // element HTML đại diện cho sản phẩm trên trang

    // Lấy tất cả các item trong menu (thường là 'Edit', 'Delete', ...)
    const items = await this.getOptionEls(el, payload);

    console.log({ items });

    // // Tìm item chứa chữ "delete"
    this.clickItemInList(items, "delete");

    // Delay 1 giây để modal xác nhận xóa hiện ra
    await delay(1000);

    // Lấy nút "Options" trong modal (hoặc fallback nếu xpath chính không tìm thấy)
    const confirmBtn = await thiefService.getElementByXPath(
      this.selectors.option_btn,
      {
        xpathFallback: this.selectors.option_btn_fallback,
      }
    );

    console.log({ confirmBtn });

    // Click vào nút "Options" trong modal nếu tìm thấy
    confirmBtn?.click();

    // Lấy nút "Close" của modal feedback (nếu có) để đóng modal sau khi xóa
    const closeBtnModalFeedback = await thiefService.getElementByXPath(
      this.selectors.close_btn_modal_feedback
    );

    closeBtnModalFeedback?.click();

    // Gọi API backend để đánh dấu sản phẩm đã xóa (published = false)
    await productApi.finistDelete(payload, { published: false });

    // Gửi message đến background/content script thông báo là delete đã xong
    chrome.runtime.sendMessage({ type: "delete-done" });
  };

  syncListing = async () => {
    const url = window.location.href;
    if (!url.includes(this.sellingPath)) return;

    const products = await facebookService.getProducts();

    const response = await productApi.sync(
      products.map((item) => ({
        title: item.title,
        price: item.price,
      })) as ISyncItem[]
    );

    console.log({ response });
  };

  extractMarketplaceItemId(url: string): string | null {
    const match = url.match(/\/marketplace\/item\/(\d+)/);
    return match ? match[1] : null;
  }

  handleGetPublistID = async (payload: IItem) => {
    // Lấy tất cả sản phẩm hiện tại trên Facebook Marketplace
    const products = await facebookService.getProducts();

    // Tìm sản phẩm khớp với title và price từ payload
    const product = products.find((product) => {
      return product.title == payload.title && product.price == payload.price;
    });

    console.log({ payload, product, products });

    // Nếu không tìm thấy sản phẩm nào khớp thì kết thúc
    if (!product) return;

    const el = product.el; // element HTML đại diện cho sản phẩm trên trang

    // Lấy tất cả các item trong menu (thường là 'Edit', 'Delete', ...)
    const items = await this.getOptionEls(el, payload);

    const item = this.getItemInList(items, "view listing");

    const publistID = this.extractMarketplaceItemId((item as any)["href"]);

    this.clickOptionOfProduct(el, payload);

    return publistID;
  };
}

export const facebookService = new FacebookService();
