import { Page } from "puppeteer-core";
import { randomDelay } from "../utils/browser";
import { Job } from "../types/job";

export class BrowserService {
  private page: Page;

  constructor(page: Page) {
    this.page = page;
  }

  async searchJobs(keywords: string, location: string) {
    try {
      const keywordInput = await this.page.waitForSelector(
        "#searchBar-jobTitle, input[name='sc.keyword'], input[placeholder*='Job title']",
        { timeout: 10000 }
      );

      if (keywordInput) {
        await keywordInput.click({ clickCount: 3 });
        await keywordInput.type(keywords, { delay: 130 });
        await randomDelay(1000, 2000);
      }

      const locationInput = await this.page.waitForSelector(
        "#searchBar-location, input[name='locKeyword'], input[placeholder*='Location']",
        { timeout: 5000 }
      );

      if (locationInput) {
        await locationInput.click({ clickCount: 3 });
        await locationInput.type(location, { delay: 130 });
        await randomDelay(1000, 2000);
        await locationInput.press("Enter");

        await this.page.waitForNavigation({
          waitUntil: "networkidle2",
          timeout: 30000,
        });
      }
    } catch (error) {
      console.log(
        "Search form not found, attempting to extract jobs from current page..."
      );
    }
  }

  async extractJobListings(location: string): Promise<Job[]> {
    try {
      await this.page.waitForSelector(
        'li[data-test="jobListing"], .JobsList_jobListItem__wjTHv, [data-jobid]',
        { timeout: 10000 }
      );
    } catch (error) {
      console.log("No job listings found on the page");
      return [];
    }

    const jobs = await this.page.evaluate((location) => {
      const jobElements = document.querySelectorAll(`
        li[data-test="jobListing"],
        .JobsList_jobListItem__wjTHv,
        li[data-jobid],
        .react-job-listing
      `) as NodeListOf<HTMLElement>;

      const jobs: any[] = [];
      console.log("Found job elements:", jobElements.length);

      jobElements.forEach((element, index) => {
        try {
          const jobId =
            element.getAttribute("data-jobid") ||
            element.getAttribute("data-brandviews")?.match(/jlid=(\d+)/)?.[1] ||
            `job-${index + 1}`;

          const titleElement = element.querySelector(`
            a[data-test="job-title"],
            .JobCard_jobTitle__GLyJ1,
            .jobLink,
            a[id*="job-title"]
          `) as HTMLAnchorElement;

          const companyElement = element.querySelector(`
            .EmployerProfile_compactEmployerName__9MGcV,
            [data-test="employer-name"] a,
            .employerName,
            .EmployerProfile_employerNameContainer__ptolz span
          `) as HTMLElement;

          const descriptionElement = element.querySelector(`
            .JobDetails_jobDescription__uW_fK,
            .JobDetails_showHidden__C_FOA,
            [class*="jobDescription"]
          `) as HTMLElement;

          const jobPostingTimeElement = element.querySelector(`
            .JobCard_listingAge__jJsuc,
            [data-test="job-age"],
            .listingAge
          `) as HTMLElement;

          const title = titleElement?.textContent?.trim() || "";
          const company = companyElement?.textContent?.trim() || "";
          const description = descriptionElement?.textContent?.trim() || "";
          const jobPosting = jobPostingTimeElement?.textContent?.trim() || "";

          const jobLink = titleElement?.href
            ? titleElement.href.startsWith("http")
              ? titleElement.href
              : `https://www.glassdoor.com${titleElement.href}`
            : "";

          const companyLink =
            companyElement?.tagName === "A"
              ? (companyElement as HTMLAnchorElement).href?.startsWith("http")
                ? (companyElement as HTMLAnchorElement).href
                : `https://www.glassdoor.com${
                    (companyElement as HTMLAnchorElement).href
                  }`
              : "";

          let jobPostingDate = new Date();

          try {
            if (jobPosting.includes("d")) {
              const match = jobPosting.match(/(\d+)\s*d/);
              if (match) {
                const daysAgo = parseInt(match[1], 10);
                if (!isNaN(daysAgo) && daysAgo >= 0) {
                  jobPostingDate.setDate(jobPostingDate.getDate() - daysAgo);
                }
              }
            } else if (jobPosting.includes("h")) {
              const match = jobPosting.match(/(\d+)\s*h/);
              if (match) {
                const hoursAgo = parseInt(match[1], 10);
                if (!isNaN(hoursAgo) && hoursAgo >= 0) {
                  jobPostingDate.setHours(jobPostingDate.getHours() - hoursAgo);
                }
              }
            }

            if (isNaN(jobPostingDate.getTime())) {
              jobPostingDate = new Date();
            }
          } catch (error) {
            console.warn(
              `Failed to parse job posting date: "${jobPosting}", using current date`
            );
            jobPostingDate = new Date();
          }

          const parsedJobId = Number.parseInt(jobId, 10);

          jobs.push({
            title,
            company,
            location,
            description: description,
            criteria: {},
            jobLink,
            companyLink,
            provider: 2,
            id: parsedJobId,
            jobPostTime: jobPostingDate.toISOString(),
            status: 0,
          });
        } catch (error) {
          console.error(`Error extracting job ${index}:`, error);
        }
      });

      console.log("Extracted jobs:", jobs.length);
      return jobs;
    }, location);

    console.log(`Found ${jobs.length} jobs on Glassdoor`);

    return jobs.map((job) => ({
      ...job,
      jobPostTime: new Date(job.jobPostTime),
    }));
  }
}
