<?php
/**
 * EcoBe Job Search Proxy — Multi-source
 * Place at: vianexu.com/clients/ecobe/jobsearch/index.php
 *
 * GET ?action=search&q=marketing+manager&location=Switzerland
 * GET ?action=detail&id=4376463275&source=linkedin
 */

header('Content-Type: application/json');
header('Access-Control-Allow-Origin: *');

$action   = $_GET['action']   ?? '';
$query    = $_GET['q']        ?? 'HR';
$location = $_GET['location'] ?? 'Switzerland';
$id       = preg_replace('/[^0-9]/', '', $_GET['id'] ?? '');
$source   = $_GET['source']   ?? 'linkedin';

// ── cURL helper ───────────────────────────────────────────────────────────────
function curlFetch($url, $extraHeaders = []) {
  $ch = curl_init();
  curl_setopt_array($ch, [
    CURLOPT_URL            => $url,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_FOLLOWLOCATION => true,
    CURLOPT_TIMEOUT        => 20,
    CURLOPT_ENCODING       => '',
    CURLOPT_HTTPHEADER     => array_merge([
      'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36',
      'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
      'Accept-Language: en-US,en;q=0.5',
    ], $extraHeaders),
    CURLOPT_SSL_VERIFYPEER => false,
  ]);
  $html   = curl_exec($ch);
  $status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
  $error  = curl_error($ch);
  curl_close($ch);
  return ['html' => $html ?: '', 'status' => $status, 'error' => $error];
}

// ── Parallel fetch with curl_multi ────────────────────────────────────────────
function curlMultiFetch($urls) {
  $mh      = curl_multi_init();
  $handles = [];

  foreach ($urls as $key => $url) {
    $ch = curl_init();
    curl_setopt_array($ch, [
      CURLOPT_URL            => $url,
      CURLOPT_RETURNTRANSFER => true,
      CURLOPT_FOLLOWLOCATION => true,
      CURLOPT_TIMEOUT        => 20,
      CURLOPT_ENCODING       => '',
      CURLOPT_HTTPHEADER     => [
        'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36',
        'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
        'Accept-Language: en-US,en;q=0.5',
      ],
      CURLOPT_SSL_VERIFYPEER => false,
    ]);
    $handles[$key] = $ch;
    curl_multi_add_handle($mh, $ch);
  }

  $running = null;
  do { curl_multi_exec($mh, $running); } while ($running);

  $results = [];
  foreach ($handles as $key => $ch) {
    $results[$key] = [
      'html'   => curl_multi_getcontent($ch) ?: '',
      'status' => curl_getinfo($ch, CURLINFO_HTTP_CODE),
    ];
    curl_multi_remove_handle($mh, $ch);
    curl_close($ch);
  }
  curl_multi_close($mh);
  return $results;
}

function cleanText($str) {
  return html_entity_decode(trim(preg_replace('/\s+/', ' ', strip_tags($str))), ENT_QUOTES | ENT_HTML5, 'UTF-8');
}

// ── Parse LinkedIn jobs ────────────────────────────────────────────────────────
function parseLinkedIn($html) {
  $jobs = [];
  preg_match_all('/class="[^"]*base-search-card__title[^"]*"[^>]*>([^<]+)</', $html, $titles);
  preg_match_all('/class="[^"]*base-search-card__subtitle[^"]*"[\s\S]{0,200}?href="[^"]*"[^>]*>([^<]+)</', $html, $companies);
  preg_match_all('/class="[^"]*job-search-card__location[^"]*"[^>]*>([^<]+)</', $html, $locations);
  preg_match_all('/href="(https:\/\/[a-z]+\.linkedin\.com\/jobs\/view\/[^"?&]+)/', $html, $links);

  $count = min(count($titles[1]), count($links[1]), 8);
  for ($i = 0; $i < $count; $i++) {
    preg_match('/-(\d+)$/', $links[1][$i], $idMatch);
    $jobs[] = [
      'source'   => 'LinkedIn',
      'title'    => cleanText($titles[1][$i]    ?? ''),
      'company'  => cleanText($companies[1][$i] ?? ''),
      'location' => cleanText($locations[1][$i] ?? ''),
      'url'      => $links[1][$i],
      'id'       => $idMatch[1] ?? null,
    ];
  }
  return $jobs;
}

// ── Parse Indeed jobs ──────────────────────────────────────────────────────────
function parseIndeed($html) {
  $jobs = [];
  preg_match_all('/<h2[^>]*class="[^"]*jobTitle[^"]*"[^>]*>[\s\S]*?<span[^>]*>([^<]+)<\/span>/', $html, $titles);
  preg_match_all('/class="[^"]*companyName[^"]*"[^>]*>([^<\n]+)</', $html, $companies);
  preg_match_all('/class="[^"]*companyLocation[^"]*"[^>]*>([^<\n]+)</', $html, $locations);
  preg_match_all('/href="(\/rc\/clk\?jk=[^"&]+)/', $html, $links);

  $count = min(count($titles[1]), 6);
  for ($i = 0; $i < $count; $i++) {
    preg_match('/jk=([a-z0-9]+)/', $links[1][$i] ?? '', $idMatch);
    $jobs[] = [
      'source'   => 'Indeed',
      'title'    => cleanText($titles[1][$i]    ?? ''),
      'company'  => cleanText($companies[1][$i] ?? ''),
      'location' => cleanText($locations[1][$i] ?? ''),
      'url'      => isset($links[1][$i]) ? 'https://www.indeed.com' . $links[1][$i] : 'https://www.indeed.com',
      'id'       => $idMatch[1] ?? null,
    ];
  }
  return $jobs;
}

// ── Parse Glassdoor jobs ───────────────────────────────────────────────────────
function parseGlassdoor($html) {
  $jobs = [];
  preg_match_all('/"jobTitle"\s*:\s*"([^"]+)"/', $html, $titles);
  preg_match_all('/"employerName"\s*:\s*"([^"]+)"/', $html, $companies);
  preg_match_all('/"locationName"\s*:\s*"([^"]+)"/', $html, $locations);
  preg_match_all('/"jobListingId"\s*:\s*(\d+)/', $html, $ids);

  $count = min(count($titles[1]), 5);
  for ($i = 0; $i < $count; $i++) {
    $jid = $ids[1][$i] ?? null;
    $jobs[] = [
      'source'   => 'Glassdoor',
      'title'    => cleanText($titles[1][$i]    ?? ''),
      'company'  => cleanText($companies[1][$i] ?? ''),
      'location' => cleanText($locations[1][$i] ?? ''),
      'url'      => $jid ? "https://www.glassdoor.com/job-listing/j?jl={$jid}" : 'https://www.glassdoor.com/Job/jobs.htm',
      'id'       => $jid,
    ];
  }
  return $jobs;
}

// ══════════════════════════════════════════════════════════════════════════════
// ACTION: search
// ══════════════════════════════════════════════════════════════════════════════
if ($action === 'search') {
  $q = urlencode($query);
  $l = urlencode($location);

  $urls = [
    'linkedin'  => "https://www.linkedin.com/jobs/search/?keywords={$q}&location={$l}&sortBy=DD&f_TPR=r2592000",
    'indeed'    => "https://www.indeed.com/jobs?q={$q}&l={$l}&sort=date&limit=10&lang=en&fromage=30",
    'glassdoor' => "https://www.glassdoor.com/Job/jobs.htm?suggestCount=0&suggestChosen=false&clickSource=searchBtn&typedKeyword={$q}&locT=N&locId=0&jobType=&sc.keyword={$q}&d=Jobs&locationSuggest={$l}",
  ];

  $results = curlMultiFetch($urls);
  $jobs    = [];

  if ($results['linkedin']['status'] === 200) {
    $jobs = array_merge($jobs, parseLinkedIn($results['linkedin']['html']));
  }
  if ($results['indeed']['status'] === 200) {
    $lJobs = parseIndeed($results['indeed']['html']);
    if (count($lJobs)) $jobs = array_merge($jobs, $lJobs);
  }
  if ($results['glassdoor']['status'] === 200) {
    $gJobs = parseGlassdoor($results['glassdoor']['html']);
    if (count($gJobs)) $jobs = array_merge($jobs, $gJobs);
  }

  // Remove duplicates by title+company
  $seen   = [];
  $unique = [];
  foreach ($jobs as $job) {
    $key = strtolower($job['title'] . '|' . $job['company']);
    if (!isset($seen[$key]) && !empty($job['title'])) {
      $seen[$key] = true;
      $unique[]   = $job;
    }
  }

  echo json_encode([
    'jobs'     => array_slice($unique, 0, 12),
    'count'    => count($unique),
    'sources'  => array_unique(array_column($unique, 'source')),
    'query'    => $query,
    'location' => $location,
  ]);

// ══════════════════════════════════════════════════════════════════════════════
// ACTION: detail
// ══════════════════════════════════════════════════════════════════════════════
} elseif ($action === 'detail') {
  if (!$id) { echo json_encode(['error' => 'Missing job ID']); exit; }

  if ($source === 'indeed') {
    $url    = "https://www.indeed.com/viewjob?jk={$id}";
    $result = curlFetch($url);
    $html   = $result['html'];

    preg_match('/<h1[^>]*class="[^"]*jobsearch-JobInfoHeader-title[^"]*"[^>]*>([\s\S]*?)<\/h1>/', $html, $titleM);
    preg_match('/class="[^"]*companyName[^"]*"[^>]*>([^<]+)</', $html, $companyM);
    preg_match('/class="[^"]*companyLocation[^"]*"[^>]*>([^<]+)</', $html, $locationM);
    preg_match('/id="jobDescriptionText"[^>]*>([\s\S]*?)<\/div>/', $html, $descM);

    $desc = cleanText($descM[1] ?? '');
    echo json_encode([
      'id'          => $id,
      'source'      => 'Indeed',
      'title'       => cleanText($titleM[1]    ?? ''),
      'company'     => cleanText($companyM[1]  ?? ''),
      'location'    => cleanText($locationM[1] ?? ''),
      'description' => substr($desc, 0, 2000),
      'url'         => $url,
    ]);

  } else {
    // LinkedIn (default)
    $url    = "https://www.linkedin.com/jobs-guest/jobs/api/jobPosting/{$id}";
    $result = curlFetch($url);
    $html   = $result['html'];

    if ($result['status'] !== 200 || empty($html)) {
      echo json_encode(['error' => 'Failed to fetch job detail', 'status' => $result['status']]);
      exit;
    }

    preg_match('/<h2[^>]*class="[^"]*topcard__title[^"]*"[^>]*>([^<]+)<\/h2>/', $html, $titleM);
    preg_match('/class="topcard__org-name-link[^"]*"[^>]*>([^<]+)<\/a>/', $html, $companyM);
    preg_match('/class="topcard__flavor topcard__flavor--bullet"[^>]*>([^<]+)<\/span>/', $html, $locationM);
    preg_match_all('/class="description__job-criteria-text[^"]*"[^>]*>\s*([^<]+)\s*<\/span>/', $html, $criteriaM);
    preg_match('/class="[^"]*description__text[^"]*"[^>]*>([\s\S]*?)<\/div>\s*<\/section>/', $html, $descM);

    $desc     = cleanText($descM[1] ?? '');
    $criteria = array_map('trim', $criteriaM[1] ?? []);

    echo json_encode([
      'id'          => $id,
      'source'      => 'LinkedIn',
      'title'       => cleanText($titleM[1]    ?? ''),
      'company'     => cleanText($companyM[1]  ?? ''),
      'location'    => cleanText($locationM[1] ?? ''),
      'criteria'    => array_values(array_filter($criteria)),
      'description' => substr($desc, 0, 2000),
      'url'         => "https://www.linkedin.com/jobs/view/{$id}",
    ]);
  }

} else {
  echo json_encode(['error' => 'Invalid action. Use ?action=search or ?action=detail']);
}
