AlkantarClanX12

Your IP : 216.73.217.24


Current Path : /www/capitalgmcbuickregina_830/public/wp-content/themes/lbx-egypt/app/
Upload File :
Current File : /www/capitalgmcbuickregina_830/public/wp-content/themes/lbx-egypt/app/helpers.php

<?php

use Illuminate\Support\Facades\Log;

/**
 * Theme helpers.
 * Theme helpers are in the global namespace for blade usage
 */

// namespace App;

// add_filter('acorn/throw_error_exception', function ($e) {
//     dd($e);
// }, 1, 999);



// Since we're using namespaces, the natual function names
// are no longer sufficient. Instead we need to use "App\\function_name".
// Since this is a pain, we'll use wrapper functions.
//
// These functions are called over the native functions, while in our namespace.
// To call a base function, you can override with \function_name.
//
// e.g. \add_action('init', 'App\function_name')
// function add_action($name, $callable, $priority = 10, $args = 1) {
//     return is_string($callable) && 0 !== strpos($callable, __NAMESPACE__)
//         ? \add_action($name, __NAMESPACE__."\\$callable", $priority, $args)
//         : \add_action($name, $callable, $priority, $args);
// }

if (!function_exists('add_actions')) {
  function add_actions($names, $callable, $priority = 10, $args = 1)
  {
    collect($names)->each(function ($name) use ($callable, $priority, $args) {
      add_action($name, $callable, $priority, $args);
    });
  }
}

if (!function_exists('add_filters')) {
  function add_filters($names, $callable, $priority = 10, $args = 1)
  {
    collect($names)->each(function ($name) use ($callable, $priority, $args) {
      add_filter($name, $callable, $priority, $args);
    });
  }
}

if (!function_exists('config')) {
  function config($string)
  {
    return \Roots\config($string);
  }
}

if (!function_exists('env')) {
  function env($string)
  {
    return \Roots\env($string);
  }
}

//THEME LOCALIZATION
load_theme_textdomain('leadbox', get_template_directory() . '/languages');

// Adding Leadbox Patterns
//Removing default patterns
remove_theme_support('core-block-patterns');

$lbSettings = get_leadbox_settings();
$showroom_page = get_page_by_title(ucfirst($lbSettings['manufacturer']) . " Showroom");
if ($showroom_page === null && $lbSettings['manufacturer']) {
  $sr_post = array(
    'post_title' => wp_strip_all_tags(ucfirst($lbSettings['manufacturer']) . " Showroom"),
    'post_content' => "<!-- wp:sage/showroom /-->",
    'post_status' => 'draft',
    'post_author' => 1,
    'post_category' => array(1),
    'post_type' => 'page'
  );
  // Insert the Showroom page into the database
  wp_insert_post($sr_post);

  // Create the Showroom Model page
  $sr_model_post = array(
    'post_title' => wp_strip_all_tags("Model"),
    'post_content' => "",
    'post_status' => 'publish',
    'post_author' => 1,
    'post_category' => array(1),
    'post_type' => 'page'
  );
  // Insert the Showroom Model page into the database
  wp_insert_post($sr_model_post);
  $showroom_model_page = get_page_by_title("Model");
  update_post_meta($showroom_model_page->ID, '_wp_page_template', 'template-showroom-model.blade.php');
}

//Including our patterns
//Adding Patterns Categories
add_action('current_screen', function ($screen) {
  if ( ! is_admin() || ! $screen ) return;

  $is_block_editor = method_exists($screen, 'is_block_editor') ? $screen->is_block_editor() : false;
  if ( ! $is_block_editor ) return;

  // Rutas locales en el TEMA PADRE
  $parent_dir = trailingslashit(get_template_directory());
  $cat_path   = $parent_dir . 'assets/patterns/categories-egypt.json';
  $pat_path   = $parent_dir . 'assets/patterns/patterns-egypt.json';

  // ----- Categorías
  $cats = get_transient('lb_patterns_categories_egypt');
  if ($cats === false) {
    if (function_exists('wp_json_file_decode') && file_exists($cat_path)) {
      $cats = wp_json_file_decode($cat_path, ['associative' => false]) ?: [];
    } else {
      $json_cat = @file_get_contents($cat_path);
      $cats = $json_cat ? json_decode($json_cat) : [];
    }
    set_transient('lb_patterns_categories_egypt', $cats, HOUR_IN_SECONDS * 12);
  }

  if (!empty($cats)) {
    foreach ($cats as $category) {
      if (!empty($category->name) && !empty($category->label)) {
        register_block_pattern_category(
          $category->name,
          ['label' => _x($category->label, 'Block pattern category', 'textdomain')]
        );
      }
    }
  }

  // ----- Patrones
  $patterns = get_transient('lb_patterns_list_egypt');
  if ($patterns === false) {
    if (function_exists('wp_json_file_decode') && file_exists($pat_path)) {
      $patterns = wp_json_file_decode($pat_path, ['associative' => false]) ?: [];
    } else {
      $json_pat = @file_get_contents($pat_path);
      $patterns = $json_pat ? json_decode($json_pat) : [];
    }
    set_transient('lb_patterns_list_egypt', $patterns, HOUR_IN_SECONDS * 12);
  }

  if (!empty($patterns)) {
    foreach ($patterns as $pattern) {
      if (empty($pattern->name) || empty($pattern->title) || empty($pattern->content) || empty($pattern->category)) {
        continue;
      }
      register_block_pattern(
        $pattern->name,
        [
          'title'       => __($pattern->title, 'textdomain'),
          'description' => _x($pattern->description ?? '', '', 'textdomain'),
          'content'     => str_replace("'", '"', $pattern->content),
          'categories'  => [$pattern->category],
        ]
      );
    }
  }
});

/* END PATTERNS */

// Global variable of the VDP data for Yoast and SEO functions
global $vdp_vehicle_data;
if (preg_match('[view|vue|form|forme]', $_SERVER["REQUEST_URI"])) {
  $vdp_url = explode("-", $_SERVER["REQUEST_URI"]);
  if (isset($_SERVER["QUERY_STRING"]) && strlen($_SERVER["QUERY_STRING"]) > 0) {
    $vdp_url[count($vdp_url) - 1] = str_replace("?" . $_SERVER["QUERY_STRING"], "", $vdp_url[count($vdp_url) - 1]);
  }
  $vdp_vehicle_data = get_vehicle_by_id(str_replace("/", "", $vdp_url[count($vdp_url) - 1]));
}

function get_dealer_hours_additional()
{
  return get_option('dealer-settings-hours-options');
}
function get_custom_finance_array()
{
  return get_option('dealer-settings-used-finance-custom-options');
}

function get_dealer_hours()
{
  $hours = get_option('dealer-settings-hours-options');
  $days = collect(['monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday', 'sunday']);
  $types = collect(['sale', 'service', 'parts', 'additionalone', 'additionaltwo', 'additionalthree']);

  if (isset($hours) && ($hours != false)) {
    return collect($hours)->groupBy(function ($_, $key) use ($types) {
      return $types->first(function ($v) use ($key) {
        return strpos($key, $v) === 0;
      });
    }, $preserve_keys = true)->map(function ($hours, $type) use ($days) {
      return $days->mapWithKeys(function ($day) use ($hours, $type) {
        $string = $hours->get("{$type}_hours_{$day}_closed", $default = false)
          ? 'Closed'
          : sprintf(
            "%s - %s",
            $hours->get("{$type}_hours_{$day}_start", ''),
            $hours->get("{$type}_hours_{$day}_end", '')
          );

        return [ucfirst($day) => $string];
      });
    });
  } else {
    $result["sale"] = array();
    $result["service"] = array();
    $result["parts"] = array();
    return $result;
  }
}

function get_dealer_contact()
{
  return get_option('dealer-settings-contact-options');
}

/**
 * Normaliza una coordenada (latitud/longitud) a un string decimal limpio, con
 * un máximo de 6 decimales y sin ceros sobrantes. Evita el artefacto de punto
 * flotante (p. ej. 45.33 -> 45.329999999999998) que aparece al castear a float
 * y serializar. Devuelve siempre string para que el JSON-LD sea estable en
 * cualquier configuración de `serialize_precision`.
 *
 * @param  mixed  $value
 * @return string Coordenada normalizada, o '' si no es numérica.
 */
function lbx_normalize_coordinate($value)
{
  $value = trim((string) $value);

  if ($value === '' || !is_numeric($value)) {
    return '';
  }

  // number_format redondea de forma decimal (no binaria) a 6 decimales.
  $formatted = number_format((float) $value, 6, '.', '');
  $formatted = rtrim($formatted, '0'); // quita ceros finales: 45.330000 -> 45.33
  $formatted = rtrim($formatted, '.'); // por si queda un punto suelto: 45. -> 45

  return $formatted;
}

/**
 * Serializa un array a JSON para un bloque <script type="application/ld+json">.
 * Fuerza serialize_precision=-1 durante la serialización para que los números
 * decimales (p. ej. coordenadas) usen su representación más corta y exacta, sin
 * el artefacto de punto flotante, sea cual sea la configuración del servidor.
 *
 * @param  mixed $data
 * @return string|false
 */
function lbx_json_ld($data)
{
  $previous = @ini_set('serialize_precision', '-1');

  $json = wp_json_encode(
    $data,
    JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE | JSON_HEX_TAG | JSON_PRETTY_PRINT
  );

  if ($previous !== false) {
    @ini_set('serialize_precision', $previous);
  }

  return $json;
}

/**
 * Elimina recursivamente las propiedades vacías ('' o null) de un schema y
 * descarta los sub-objetos que quedan sin datos reales (solo con claves de
 * metadata como @type o unitText).
 *
 * @param  array $node
 * @return array
 */
function lbx_schema_prune(array $node)
{
  $meta = ['@context', '@type', 'unitText', 'priceCurrency'];

  foreach ($node as $key => $value) {
    if (is_array($value)) {
      $value = lbx_schema_prune($value);

      // Si solo sobreviven claves de metadata, el sub-objeto no aporta nada.
      if (empty(array_diff(array_keys($value), $meta))) {
        unset($node[$key]);
        continue;
      }

      $node[$key] = $value;
      continue;
    }

    if ($value === null || $value === '') {
      unset($node[$key]);
    }
  }

  return $node;
}

/**
 * Convierte los horarios de un departamento (día => "start - end" | "Closed")
 * en una lista de OpeningHoursSpecification. Los días cerrados o con rangos
 * no parseables se OMITEN: un día ausente se interpreta como cerrado y evita
 * la ambigüedad de un 00:00-00:00.
 *
 * @param  iterable|mixed $dayRanges Formato de get_dealer_hours()['sale'|'service'|'parts'].
 * @return array
 */
function lbx_opening_hours_schema($dayRanges)
{
  $specs = [];

  if (!is_iterable($dayRanges)) {
    return $specs;
  }

  foreach ($dayRanges as $day => $range) {
    $range = trim((string) $range);
    if ($range === '' || strtolower($range) === 'closed') {
      continue;
    }

    $parts = explode(' - ', $range);
    if (count($parts) !== 2) {
      continue;
    }

    $opens  = strtotime(trim($parts[0]));
    $closes = strtotime(trim($parts[1]));
    if ($opens === false || $closes === false) {
      continue;
    }

    $specs[] = [
      '@type'     => 'OpeningHoursSpecification',
      'dayOfWeek' => $day,
      'opens'     => date('H:i', $opens),
      'closes'    => date('H:i', $closes),
    ];
  }

  return $specs;
}

/**
 * Decide si el schema AutoDealer se emite en la página actual según el setting
 * "Schema Scope" (Dealer Settings → Contact → Schema):
 *  - '' | 'all' (default): todas las páginas — variante SD "Suggested" y
 *    comportamiento histórico del theme.
 *  - 'required': solo homepage + las páginas listadas en schema_required_pages
 *    (slugs separados por comas; vacío = about-us y service) — el mínimo que
 *    exige SD como "Required".
 *
 * @return bool
 */
function lbx_autodealer_schema_in_scope()
{
  $contact = get_dealer_contact();
  $contact = is_array($contact) ? $contact : [];

  if (trim((string) ($contact['schema_scope'] ?? '')) !== 'required') {
    return true;
  }

  if (is_front_page()) {
    return true;
  }

  $slugs = array_values(array_filter(array_map(
    'trim',
    explode(',', (string) ($contact['schema_required_pages'] ?? ''))
  )));
  if (empty($slugs)) {
    $slugs = ['about-us', 'service'];
  }

  return is_page($slugs);
}

/**
 * Construye el structured data AutoDealer + LocalBusiness del dealer para el
 * <head> global (LBT-1510, Shift Digital AI-Readiness A6).
 *
 * Autocontenido: lee Dealer Settings / Leadbox Settings directamente, sin
 * depender de variables inyectadas por composers a la vista. Devuelve el
 * array ya podado (sin propiedades vacías); si el site no tiene ni el nombre
 * del dealer configurado — o la página actual está fuera del Schema Scope
 * configurado — devuelve [] y no se emite nada.
 *
 * @return array
 */
function lbx_autodealer_schema()
{
  if (!lbx_autodealer_schema_in_scope()) {
    return [];
  }

  $contact  = get_dealer_contact();
  $contact  = is_array($contact) ? $contact : [];
  $branding = get_dealer_branding();
  $branding = is_array($branding) ? $branding : [];

  $dealerName = trim((string) ($contact['dealer_name'] ?? ''));
  $dealerUrl  = trim((string) ($contact['dealer_url'] ?? ''));

  // @id estable por entidad: el mismo IRI identifica al dealer en todas las
  // páginas del site (y permite referenciarlo desde otros schemas).
  $idBase = $dealerUrl !== '' ? $dealerUrl : home_url('/');
  if (!preg_match('#^https?://#i', $idBase)) {
    $idBase = 'https://' . ltrim($idBase, '/');
  }

  // Teléfonos por departamento: alimentan telephone (plano, para lectores
  // legacy) y contactPoint (con contactType, para entity matching).
  $phones = [
    'sales'   => trim((string) ($contact['sale_phone'] ?? '')),
    'service' => trim((string) ($contact['service_phone'] ?? '')),
    'parts'   => trim((string) ($contact['parts_phone'] ?? '')),
  ];

  $contactPoints = [];
  foreach ($phones as $department => $phone) {
    if ($phone === '') {
      continue;
    }
    $contactPoints[] = [
      '@type'       => 'ContactPoint',
      'contactType' => $department,
      'telephone'   => $phone,
    ];
  }

  // Marcas que vende el dealer: manufacturer principal + all_brands (lista
  // separada por comas). Ambos son texto libre en Leadbox Settings, así que
  // los valores todo-minúsculas se normalizan (acrónimos conocidos incluidos);
  // los que ya traen mayúsculas se respetan tal cual.
  $lbSettings = get_leadbox_settings();
  $lbSettings = is_array($lbSettings) ? $lbSettings : [];

  $acronyms = ['bmw' => 'BMW', 'gmc' => 'GMC', 'mini' => 'MINI', 'fiat' => 'FIAT', 'ram' => 'RAM'];
  $brands = [];
  $seenBrands = [];
  $brandNames = array_merge(
    [(string) ($lbSettings['manufacturer'] ?? '')],
    explode(',', (string) ($lbSettings['all_brands'] ?? ''))
  );
  foreach ($brandNames as $brandName) {
    $brandName = trim($brandName);
    $brandKey  = mb_strtolower($brandName);
    if ($brandName === '' || isset($seenBrands[$brandKey])) {
      continue;
    }
    $seenBrands[$brandKey] = true;
    if ($brandName === $brandKey) {
      $brandName = $acronyms[$brandKey] ?? ucwords($brandName);
    }
    $brands[] = [
      '@type' => 'Brand',
      'name'  => $brandName,
    ];
  }

  // sameAs: perfiles sociales de Dealer Settings → Social Media.
  $social = get_option('dealer-settings-socialmedia-options');
  $social = is_array($social) ? $social : [];
  $sameAs = [];
  foreach ($social as $key => $socialUrl) {
    if (substr((string) $key, -12) !== '_socialmedia') {
      continue;
    }
    $socialUrl = trim((string) $socialUrl);
    if ($socialUrl === '') {
      continue;
    }
    if (!preg_match('#^https?://#i', $socialUrl)) {
      $socialUrl = 'https://' . ltrim($socialUrl, '/');
    }
    // Descarta valores que no son URLs reales (p. ej. "FB" o "n/a"): el host
    // debe tener al menos un punto.
    $socialHost = parse_url($socialUrl, PHP_URL_HOST);
    if (!is_string($socialHost) || strpos($socialHost, '.') === false) {
      continue;
    }
    $sameAs[] = $socialUrl;
  }
  $sameAs = array_values(array_unique($sameAs));

  $hours        = get_dealer_hours();
  $saleHours    = lbx_opening_hours_schema($hours['sale'] ?? []);
  $serviceHours = lbx_opening_hours_schema($hours['service'] ?? []);
  $partsHours   = lbx_opening_hours_schema($hours['parts'] ?? []);

  // Departamentos como LocalBusiness anidados; solo se emiten si tienen
  // alguna señal real (teléfono u horarios propios).
  $departments = [];
  if ($phones['service'] !== '' || !empty($serviceHours)) {
    $departments[] = [
      '@type'                     => 'AutoRepair',
      'name'                      => trim($dealerName . ' Service'),
      'telephone'                 => $phones['service'],
      'openingHoursSpecification' => $serviceHours,
    ];
  }
  if ($phones['parts'] !== '' || !empty($partsHours)) {
    $departments[] = [
      '@type'                     => 'AutoPartsStore',
      'name'                      => trim($dealerName . ' Parts'),
      'telephone'                 => $phones['parts'],
      'openingHoursSpecification' => $partsHours,
    ];
  }

  $schema = [
    '@context'                  => 'http://schema.org',
    '@type'                     => ['AutoDealer', 'LocalBusiness'],
    '@id'                       => rtrim($idBase, '/') . '/#dealer',
    'name'                      => $dealerName,
    'url'                       => $dealerUrl,
    'logo'                      => $branding['logo_image'] ?? '',
    'image'                     => $branding['logo_image'] ?? '',
    'telephone'                 => array_values(array_unique(array_filter($phones))),
    'contactPoint'              => $contactPoints,
    'brand'                     => $brands,
    'sameAs'                    => $sameAs,
    'currenciesAccepted'        => ['CAD'],
    'openingHoursSpecification' => $saleHours,
    'department'                => $departments,
    'address'                   => [
      '@type'           => 'PostalAddress',
      'addressLocality' => $contact['address_city'] ?? '',
      'addressRegion'   => $contact['address_province'] ?? '',
      'postalCode'      => $contact['address_postal_code'] ?? '',
      'streetAddress'   => $contact['address_line_1'] ?? '',
    ],
  ];

  // Geo: solo si latitude y longitude son numéricas (Dealer Settings →
  // Contact → Address). Coordenadas malas son peores que no tener geo.
  $lat = isset($contact['latitude'])  ? trim((string) $contact['latitude'])  : '';
  $lng = isset($contact['longitude']) ? trim((string) $contact['longitude']) : '';
  if (is_numeric($lat) && is_numeric($lng)) {
    $schema['geo'] = [
      '@type'     => 'GeoCoordinates',
      'latitude'  => (float) lbx_normalize_coordinate($lat),
      'longitude' => (float) lbx_normalize_coordinate($lng),
    ];
  }

  $schema = lbx_schema_prune($schema);

  // Sin nombre no hay entidad que declarar: mejor no emitir nada.
  if (!isset($schema['name'])) {
    return [];
  }

  return $schema;
}

/**
 * Mapea un drivetrain de inventario (AWD, 4WD, FWD…) a su valor canónico de
 * DriveWheelConfigurationValue; si no matchea ninguno devuelve el texto tal
 * cual (schema.org acepta texto libre).
 *
 * @param  mixed  $drivetrain
 * @return string
 */
function lbx_drivewheel_configuration($drivetrain)
{
  $drivetrain = trim((string) $drivetrain);
  $driveMap = [
    'AWD' => 'https://schema.org/AllWheelDriveConfiguration',
    '4WD' => 'https://schema.org/FourWheelDriveConfiguration',
    '4X4' => 'https://schema.org/FourWheelDriveConfiguration',
    'FWD' => 'https://schema.org/FrontWheelDriveConfiguration',
    'RWD' => 'https://schema.org/RearWheelDriveConfiguration',
  ];
  $driveKey = strtoupper(preg_replace('/[^A-Za-z0-9]/', '', $drivetrain));

  return $driveMap[$driveKey] ?? $drivetrain;
}

/**
 * URL absoluta del VDP de un vehículo, replicando el slug que construye la
 * vehicle card (spa-vehicle-card.vue.js → viewSlug):
 * /view/{condition}-{year}-{make}-{model}[-{vin}]-{id}/ (/vue/ en francés).
 * El flag use-slug-vin sale del genius config, igual que en la card.
 *
 * @param  array  $vehicle Item del array `vehicles` de inventory.json.
 * @return string
 */
function lbx_vehicle_vdp_url(array $vehicle)
{
  $slugify = static function ($value) {
    return str_replace(' ', '-', strtolower(trim((string) $value)));
  };

  // El JS solo elimina la PRIMERA '/' del modelo (String.replace sin flag global).
  $model = $slugify($vehicle['model'] ?? '');
  $slashPos = strpos($model, '/');
  if ($slashPos !== false) {
    $model = substr_replace($model, '', $slashPos, 1);
  }

  $parts = [
    $slugify($vehicle['condition'] ?? ''),
    $slugify($vehicle['year'] ?? ''),
    $slugify($vehicle['make'] ?? ''),
    $model,
  ];

  $useVin = (defined('GENIUS') && isset(GENIUS['vehicle-card']['data']['use-slug-vin']))
    ? GENIUS['vehicle-card']['data']['use-slug-vin']
    : false;
  if ($useVin && !empty($vehicle['vin'])) {
    $parts[] = (string) $vehicle['vin'];
  }

  $parts[] = (string) ($vehicle['id'] ?? '');

  $base = (function_exists('isFrench') && isFrench()) ? '/vue/' : '/view/';

  return home_url($base . implode('-', $parts) . '/');
}

/**
 * Construye el ItemList de Car (schema.org) de una vista de inventario
 * (SRP/VLP) a partir de los vehículos YA filtrados/ordenados/paginados que la
 * vista renderiza (LBT-1508, Shift Digital AI-Readiness A4).
 *
 * Solo emite en vistas de inventario reales: los bloques con `filter` activo.
 * Los carousels (home, etc.) usan el mismo bloque con filter=false y se
 * omiten. La lista se acota a la primera "página" visible del SRP
 * (vehiclePerPage o loadMoreBtnItemsPerPage del genius config, fallback 24)
 * para que el JSON-LD refleje lo que el usuario ve sin inflar el HTML.
 *
 * @param  array $vehicles Vehículos de la vista (post filter/sort/paginate).
 * @param  array $options  Opciones del bloque inventory-block.
 * @return array
 */
function lbx_srp_itemlist_schema(array $vehicles, array $options = [])
{
  if (!filter_var($options['filter'] ?? false, FILTER_VALIDATE_BOOLEAN)) {
    return [];
  }

  if (empty($vehicles)) {
    return [];
  }

  $cap = 24;
  if (defined('GENIUS') && isset(GENIUS['srp-layout']['data']) && is_array(GENIUS['srp-layout']['data'])) {
    $layoutData = GENIUS['srp-layout']['data'];
    if (!empty($layoutData['vehiclePerPage'])) {
      $cap = (int) $layoutData['vehiclePerPage'];
    } elseif (!empty($layoutData['loadMoreBtnItemsPerPage'])) {
      $cap = (int) $layoutData['loadMoreBtnItemsPerPage'];
    }
  }
  $vehicles = array_slice(array_values($vehicles), 0, max(1, $cap));

  $items = [];
  foreach ($vehicles as $vehicle) {
    if (!is_array($vehicle)) {
      continue;
    }

    $condition = trim((string) ($vehicle['condition'] ?? ''));
    $isNew = strtolower($condition) === 'new';
    $url = lbx_vehicle_vdp_url($vehicle);

    $offer = [
      '@type'         => 'Offer',
      'availability'  => !empty($vehicle['incoming']) ? 'https://schema.org/OutOfStock' : 'https://schema.org/InStock',
      'priceCurrency' => 'CAD',
      'url'           => $url,
    ];
    $price = $vehicle['price'] ?? null;
    if (is_numeric($price) && (float) $price > 0) {
      $offer['price'] = (string) $price;
    }

    $car = [
      '@type'                       => 'Car',
      'name'                        => trim(preg_replace('/\s+/', ' ', sprintf(
        '%s %s %s %s %s',
        $condition,
        $vehicle['year'] ?? '',
        $vehicle['make'] ?? '',
        $vehicle['model'] ?? '',
        $vehicle['trim'] ?? ''
      ))),
      'url'                         => $url,
      'image'                       => (string) ($vehicle['picture'] ?? ''),
      'brand'                       => [
        '@type' => 'Brand',
        'name'  => (string) ($vehicle['make'] ?? ''),
      ],
      'model'                       => (string) ($vehicle['model'] ?? ''),
      'vehicleModelDate'            => (string) ($vehicle['year'] ?? ''),
      'itemCondition'               => $isNew
        ? 'https://schema.org/NewCondition'
        : 'https://schema.org/UsedCondition',
      'driveWheelConfiguration'     => lbx_drivewheel_configuration($vehicle['drivetrain'] ?? ''),
      'vehicleIdentificationNumber' => (string) ($vehicle['vin'] ?? ''),
      'sku'                         => (string) ($vehicle['stocknumber'] ?? ''),
      'offers'                      => $offer,
    ];

    // Kilometraje: en usados y demos (mismo criterio que las cards).
    if ((!$isNew || !empty($vehicle['demo'])) && is_numeric($vehicle['mileage'] ?? null)) {
      $car['mileageFromOdometer'] = [
        '@type'    => 'QuantitativeValue',
        'value'    => (string) $vehicle['mileage'],
        'unitText' => 'KM',
      ];
    }

    $items[] = [
      '@type'    => 'ListItem',
      'position' => count($items) + 1,
      'item'     => $car,
    ];
  }

  if (empty($items)) {
    return [];
  }

  $schema = [
    '@context'        => 'http://schema.org',
    '@type'           => 'ItemList',
    'name'            => wp_strip_all_tags((string) get_the_title()),
    'numberOfItems'   => count($items),
    'itemListElement' => $items,
  ];

  return lbx_schema_prune($schema);
}

/**
 * Renderiza el <script> JSON-LD del ItemList del SRP, o '' si la vista no
 * aplica (bloque sin filtro activo o sin vehículos). Pensado para llamarse
 * desde layouts/srp-layout/* justo después de paginar.
 *
 * @param  mixed $vehicles Vehículos ya filtrados/paginados de la vista.
 * @param  mixed $options  Opciones del bloque inventory-block.
 * @return string
 */
function lbx_render_srp_itemlist_schema($vehicles, $options = [])
{
  if (!is_array($vehicles)) {
    return '';
  }

  $schema = lbx_srp_itemlist_schema($vehicles, is_array($options) ? $options : []);
  if (empty($schema)) {
    return '';
  }

  return "\n<script type=\"application/ld+json\">\n" . lbx_json_ld($schema) . "\n</script>\n";
}

/**
 * Construye el structured data Car (schema.org) de un vehículo para las
 * plantillas VDP/product/form y lo devuelve ya serializado como JSON-LD.
 *
 * Reemplaza los bloques JSON armados a mano en los blades: al construir el
 * schema como array PHP y serializarlo con lbx_json_ld(), la salida es JSON
 * válido por construcción, incluso con descripciones multi-párrafo (saltos de
 * línea, comillas, HTML). La descripción se emite como texto plano y las
 * propiedades opcionales sin valor se omiten en vez de emitirse como cadenas
 * vacías (p. ej. nunca se emite "price": "" en vehículos sin precio).
 *
 * @param array      $data     JSON per-vehicle (uploads/data/<id>.json).
 * @param array|null $contact  Datos de contacto del dealer.
 * @param array|null $branding Branding del dealer (logo).
 * @param array      $args     Overrides por plantilla: name, image, url, mileage.
 * @return string|false
 */
function lbx_vehicle_car_schema($data, $contact = null, $branding = null, $args = [])
{
  $data     = is_array($data) ? $data : [];
  $contact  = is_array($contact) ? $contact : [];
  $branding = is_array($branding) ? $branding : [];

  // Descripción: texto plano, sin HTML, sin saltos de línea y acotada.
  $description = (string) ($data['description'] ?? '');
  if ($description !== '') {
    $description = wp_strip_all_tags($description);
    $description = html_entity_decode($description, ENT_QUOTES | ENT_HTML5, 'UTF-8');
    $description = str_replace("\xC2\xA0", ' ', $description); // nbsp
    $description = trim(preg_replace('/\s+/u', ' ', $description));

    if (mb_strlen($description) > 5000) {
      $description = mb_substr($description, 0, 5000);
      $cut = mb_strrpos($description, ' ');
      if ($cut !== false && $cut > 4000) {
        $description = mb_substr($description, 0, $cut);
      }
      $description .= '…';
    }
  }

  // drivetrain -> valor canónico de DriveWheelConfigurationValue (o el texto
  // tal cual si no matchea ninguno).
  $driveWheelConfiguration = lbx_drivewheel_configuration($data['drivetrain'] ?? '');

  $offer = [
    '@type'         => 'Offer',
    'availability'  => !empty($data['incoming']) ? 'https://schema.org/OutOfStock' : 'https://schema.org/InStock',
    'priceCurrency' => 'CAD',
    'url'           => (string) ($args['url'] ?? ''),
    'seller'        => [
      '@type'     => 'AutoDealer',
      'name'      => (string) ($contact['dealer_name'] ?? ''),
      'telephone' => (string) ($contact['sale_phone'] ?? ''),
      'image'     => (string) ($branding['logo_image'] ?? ''),
      'address'   => [
        '@type'           => 'PostalAddress',
        'addressLocality' => (string) ($contact['address_city'] ?? ''),
        'addressRegion'   => (string) ($contact['address_province'] ?? ''),
        'postalCode'      => (string) ($contact['address_postal_code'] ?? ''),
        'streetAddress'   => (string) ($contact['address_line_1'] ?? ''),
      ],
    ],
  ];

  $price = $data['price'] ?? null;
  if (is_numeric($price) && (float) $price > 0) {
    $offer['price'] = (string) $price;
  }

  // seats/doors en 0 son data ausente, no un valor real: se omiten.
  $seats = $data['seats'] ?? null;
  $seats = (is_numeric($seats) && (int) $seats > 0) ? (string) $seats : '';
  $doors = $data['doors'] ?? null;
  $doors = (is_numeric($doors) && (int) $doors > 0) ? (string) $doors : '';

  $schema = [
    '@context'                    => 'http://schema.org',
    '@type'                       => 'Car',
    'name'                        => (string) ($args['name'] ?? ''),
    'image'                       => (string) ($args['image'] ?? ''),
    'itemCondition'               => strtolower((string) ($data['condition'] ?? '')) == 'new'
      ? 'http://schema.org/NewCondition'
      : 'http://schema.org/UsedCondition',
    'manufacturer'                => (string) ($data['make'] ?? ''),
    'vehicleIdentificationNumber' => (string) ($data['vin'] ?? ''),
    'vehicleModelDate'            => (string) ($data['year'] ?? ''),
    'brand'                       => (string) ($data['make'] ?? ''),
    'model'                       => (string) ($data['model'] ?? ''),
    'description'                 => $description,
    'vehicleInteriorColor'        => (string) ($data['interiorcolor'] ?? ''),
    'bodyType'                    => (string) ($data['bodystyle'] ?? ''),
    'vehicleSeatingCapacity'      => $seats,
    'mileageFromOdometer'         => [
      '@type'    => 'QuantitativeValue',
      'value'    => (string) ($args['mileage'] ?? ($data['mileage'] ?? '')),
      'unitText' => 'KM',
    ],
    'numberOfDoors'               => $doors,
    'vehicleEngine'               => [
      '@type'    => 'EngineSpecification',
      'name'     => (string) ($data['engine'] ?? ''),
      'fuelType' => (string) ($data['fueltype'] ?? ''),
    ],
    'driveWheelConfiguration'     => $driveWheelConfiguration,
    'vehicleTransmission'         => (string) ($data['transmission'] ?? ''),
    'color'                       => (string) ($data['exteriorcolor'] ?? ''),
    'sku'                         => (string) ($data['stocknumber'] ?? ''),
    'offers'                      => $offer,
  ];

  return lbx_json_ld(lbx_schema_prune($schema));
}

/**
 * ¿La página que se está mostrando es una página de Preguntas Frecuentes?
 *
 * Se considera FAQ si usa la plantilla template-faq.blade.php o si su slug
 * contiene "faq" (cubre rutas como /faq/ o /finance/credit-faq/ aunque no
 * usen la plantilla dedicada).
 *
 * @return bool
 */
function lbx_is_faq_page()
{
  if (!function_exists('is_page') || !is_page()) {
    return false;
  }

  if (get_page_template_slug() === 'template-faq.blade.php') {
    return true;
  }

  $queried = get_queried_object();

  return ($queried instanceof WP_Post)
    && stripos((string) $queried->post_name, 'faq') !== false;
}

/**
 * Imprime el structured data FAQPage (schema.org) en el <head> de las páginas
 * de Preguntas Frecuentes.
 *
 * Lee el contenido ya publicado de la página y deriva los pares pregunta/
 * respuesta con lbx_build_faq_entities(). Solo emite el bloque JSON-LD si se
 * detectan al menos dos pares, de modo que nunca se imprime un schema vacío o
 * incompleto. Reutiliza lbx_json_ld() para la serialización.
 *
 * Si un plugin SEO (p. ej. Yoast) ya genera el FAQPage desde su propio bloque
 * de FAQ, se aborta para no duplicar el structured data.
 *
 * @return void
 */
function lbx_render_faqpage_schema()
{
  if (!lbx_is_faq_page()) {
    return;
  }

  $post = get_queried_object();
  if (!($post instanceof WP_Post) || trim((string) $post->post_content) === '') {
    return;
  }

  $html = apply_filters('the_content', $post->post_content);

  // Si un plugin SEO (p. ej. Yoast) ya genera el FAQPage desde su propio bloque
  // de FAQ, no duplicamos el structured data.
  if (
    stripos($html, 'schema-faq-question') !== false
    || stripos($html, 'wp-block-yoast-faq-block') !== false
  ) {
    return;
  }

  $entities = lbx_build_faq_entities($html);

  if (count($entities) < 2) {
    return;
  }

  $schema = [
    '@context'   => 'https://schema.org',
    '@type'      => 'FAQPage',
    'mainEntity' => $entities,
  ];

  echo "\n  <script type=\"application/ld+json\">\n"
    . lbx_json_ld($schema)
    . "\n  </script>\n";
}

/**
 * Extrae los pares pregunta/respuesta de un fragmento HTML para construir el
 * mainEntity de un FAQPage schema.
 *
 * La heurística es tolerante a los distintos formatos que usan los sitios:
 *  - Pregunta: un encabezado <h2>–<h6>, o un <p> cuyo contenido sea íntegramente
 *    negrita (<strong>/<b>), siempre que el texto termine en "?".
 *  - Respuesta: el texto de los párrafos siguientes hasta la próxima pregunta.
 *  - Un encabezado que no termina en "?" se trata como título de sección y cierra
 *    la respuesta en curso.
 *  - Se elimina el prefijo "Q:" / "A:" que anteponen algunos sitios.
 *
 * Las respuestas se guardan como texto plano (válido para schema.org), por lo que
 * no se conserva el HTML interno (listas, enlaces) de la respuesta.
 *
 * @param  string $html
 * @return array  Lista de nodos Question; vacío si no se detecta ninguno.
 */
function lbx_build_faq_entities($html)
{
  $html = trim((string) $html);
  if ($html === '' || !class_exists('DOMDocument')) {
    return [];
  }

  $dom      = new DOMDocument();
  $previous = libxml_use_internal_errors(true);
  $dom->loadHTML('<?xml encoding="utf-8" ?><div id="lbx-faq-root">' . $html . '</div>');
  libxml_clear_errors();
  libxml_use_internal_errors($previous);

  $xpath = new DOMXPath($dom);
  $root  = $xpath->query('//div[@id="lbx-faq-root"]')->item(0);
  if (!$root) {
    return [];
  }

  // Encabezados y párrafos en orden de documento (atravesando los contenedores
  // que generan los bloques de Gutenberg).
  $nodes = $xpath->query('.//h2|.//h3|.//h4|.//h5|.//h6|.//p', $root);

  $entities = [];
  $current  = null;

  foreach ($nodes as $node) {
    $question = lbx_faq_extract_question($node);

    if ($question !== null) {
      $entities[] = [
        '@type'          => 'Question',
        'name'           => $question,
        'acceptedAnswer' => ['@type' => 'Answer', 'text' => ''],
      ];
      $current = count($entities) - 1;
      continue;
    }

    // Encabezado que no es pregunta: separador de sección.
    if (strtolower($node->nodeName)[0] === 'h') {
      $current = null;
      continue;
    }

    if ($current !== null) {
      $text = lbx_faq_clean_text($node->textContent, true);
      if ($text !== '') {
        $existing = $entities[$current]['acceptedAnswer']['text'];
        $entities[$current]['acceptedAnswer']['text'] =
          $existing === '' ? $text : $existing . ' ' . $text;
      }
    }
  }

  // Descarta preguntas que se quedaron sin respuesta.
  return array_values(array_filter($entities, function ($q) {
    return $q['acceptedAnswer']['text'] !== '';
  }));
}

/**
 * Devuelve el texto de la pregunta si $node es un nodo pregunta, o null si no.
 *
 * Es pregunta un encabezado <h2>–<h6> o un <p> cuyo contenido sea íntegramente
 * negrita, siempre que el texto (ya sin el prefijo "Q:") termine en "?".
 *
 * @param  DOMElement $node
 * @return string|null
 */
function lbx_faq_extract_question(DOMElement $node)
{
  $tag  = strtolower($node->nodeName);
  $text = lbx_faq_clean_text($node->textContent, false);

  if ($text === '' || substr($text, -1) !== '?') {
    return null;
  }

  if (in_array($tag, ['h2', 'h3', 'h4', 'h5', 'h6'], true)) {
    return $text;
  }

  if ($tag !== 'p') {
    return null;
  }

  // <p> que solo contiene negrita (y, a lo sumo, saltos de línea) => pregunta.
  $hasBold = false;
  foreach ($node->childNodes as $child) {
    if ($child->nodeType === XML_TEXT_NODE) {
      if (trim($child->textContent) !== '') {
        return null;
      }
    } elseif ($child->nodeType === XML_ELEMENT_NODE) {
      $childTag = strtolower($child->nodeName);
      if (in_array($childTag, ['strong', 'b'], true)) {
        $hasBold = true;
      } elseif ($childTag !== 'br') {
        return null;
      }
    }
  }

  return $hasBold ? $text : null;
}

/**
 * Normaliza el texto de un nodo: colapsa los espacios en blanco, decodifica las
 * entidades y elimina el prefijo "Q:" o "A:" que anteponen algunos sitios.
 *
 * @param  string $raw
 * @param  bool   $isAnswer  Si es respuesta quita el prefijo "A:"; si no, "Q:".
 * @return string
 */
function lbx_faq_clean_text($raw, $isAnswer = false)
{
  $text = html_entity_decode((string) $raw, ENT_QUOTES | ENT_HTML5, 'UTF-8');
  $text = preg_replace('/\s+/u', ' ', $text);
  $text = trim($text);

  $prefix = $isAnswer ? 'A' : 'Q';
  $text   = preg_replace('/^' . $prefix . '\s*:\s*/u', '', $text);

  return trim($text);
}

function get_iboost_option()
{
  $option = "disabled";
  $lbSettings = get_leadbox_settings();
  if (
    isset($lbSettings) && !empty($lbSettings) && isset($lbSettings["iboost"])
    && !empty($lbSettings["iboost"]) && (strlen($lbSettings["iboost"]) > 0)
  ) {
    $option = strtolower($lbSettings["iboost"]);
  }

  return $option;
}

function get_dealer_iboost()
{
  $dealer_input = null;
  $lbSettings = get_leadbox_settings();
  if (
    isset($lbSettings) && !empty($lbSettings) && isset($lbSettings["iboost_token"])
    && !empty($lbSettings["iboost_token"]) && (strlen($lbSettings["iboost_token"]) > 0)
  ) {
    $dealer_input = $lbSettings["iboost_token"];
  }

  return $dealer_input;
}

function get_dealer_policies()
{
  return get_option('dealer-settings-policies-options');
}

function get_dealer_labels()
{
  return get_option('dealer-settings-labels-options');
}
function get_dealer_listings()
{
  return get_option('dealer-settings-listing-options');
}

function get_dealer_branding()
{
  return get_option('dealer-settings-branding-options');
}

function get_dealer_disclaimer()
{
  return get_option('dealer-settings-disclaimer-options');
}

function get_dealer_filter()
{
  return get_option('dealer-settings-filter-options');
}

function get_newsletter_status()
{
  return get_option('dealer-settings-branding-options')['newsletter_enabled_option'];
}

function is_my_garage_active()
{
  $options = get_option('dealer-settings-my-garage-options', []);
  $my_garage_status = is_array($options) && isset($options['my_garage_status'])
      ? $options['my_garage_status']
      : '';

  $my_garage_is_active = LBX_is_plugin_activated('Leadbox Saved Vehicles');

  return (strtolower($my_garage_status) === 'enabled' && $my_garage_is_active);
}

function format_phone($data)
{
  if (preg_match('/^\+\d(\d{3})(\d{3})(\d{4})$/', $data, $matches)) {
    $result = $matches[1] . '-' . $matches[2] . '-' . $matches[3];
    return $result;
  }
}

function format_phone_v2($data)
{
  if (preg_match('/^\+\d(\d{3})(\d{3})(\d{4})$/', $data, $matches)) {
    $result = '(' . $matches[1] . ') ' . $matches[2] . '-' . $matches[3];
    return $result;
  }
}

function change_image($image)
{
  $vdp_str = get_query_var('vdp_string');
  $vdp_arr = explode('-', $vdp_str);
  $id = array_pop($vdp_arr);

  $data = $GLOBALS['vdp_vehicle_data'];

  $id_feature_image = get_queried_object_id();
  $branding = get_dealer_branding();
  if (isset($data['pictures'])) {
    $file = $data['pictures'][0];
  }

  if (has_post_thumbnail($id_feature_image)) {
    return wp_get_attachment_image_src(get_post_thumbnail_id($id_feature_image), 'full')[0];
  } else {
    if (isset($id) && $id > 0) {
      if (isset($data['pictures']) && url_exists($file)) {

        $image = $data['pictures'][0];
        if (strpos($image, '?ts=') !== false) {
          $expStr = explode("?ts=", $image);
          if (count($expStr) > 0) {
            if (str_contains($expStr[0], "http")) {
              if (str_contains($expStr[0], "-XXL"))
                $image = str_replace("-XXL", "-large.jpg", $expStr[0]);
              else
                $image = $expStr[0] . '-large.jpg';
            } else {
              if (str_contains($expStr[0], "-XXL"))
                $image = 'https:' . str_replace("-XXL", "-large.jpg", $expStr[0]);
              else
                $image = 'https:' . $expStr[0] . '-large.jpg';
            }
          }
          return str_replace("http:", "https:", $image);

        } else {
          if (str_contains($image, "-XXL"))
            return str_replace("-XXL", "-large.jpg", str_replace("http:", "https:", $image));
          else
            return str_replace("http:", "https:", $image) . '-large.jpg';

        }
      } else {
        return $branding['logo_image'];
      }
    } else {
      return $branding['logo_image'];
    }
  }
}

function getFilesInFolder($folder, $extension)
{
  $target = realpath(get_template_directory() . $folder);
  dd($folder, $target);

  if (!$target) {
    return array();
  } else {
    $files = scandir($target);

    return array_filter($files, function ($file) use ($extension) {
      if (in_array($file, ['.', '..'])) {
        return array();
      }
      return ends_with($file, $extension);
    });
  }

}

function getFormLocale_text()
{
  $idiom = get_locale();
  $view = 'forme';
  if (strpos($idiom, 'en') !== false) {
    $view = 'form';
  }
  return $view;
}

function getDetailLocale_text()
{
  $idiom = get_locale();
  $view = 'vue';
  if (strpos($idiom, 'en') !== false) {
    $view = 'view';
  }
  return $view;
}

function verifyRebateToTranslate($rebate)
{
  $idiom = get_locale();

  if (strpos($idiom, 'en') !== false) {
    return $rebate;
  }

  if (strpos(strtolower($rebate), 'delivery allowance') !== false) {
    return 'Rabais à la livraison';
  }

  if (strpos(strtolower($rebate), 'ev rebate retail') !== false) {
    return 'Rabais gouvernement VE';
  }

  return $rebate;
}

function getInventoryLocale_text()
{
  $idiom = get_locale();
  $view = 'inventaire-neufs';
  if (strpos($idiom, 'en') !== false) {
    $view = 'new-inventory';
  }
  return $view;
}

function getFormPageLocale($form)
{

  $textForm = getFormLocale_name($form);
  return '/' . getFormLocale_text() . '/' . $textForm;
}

function modelTotal($regex, $trim = false, $model = '')
{
  $inventory = get_search_inventory();

  $total = 0;
  $matches = [];

  if(strtolower($model) == 'escapeplug-inhybrid'){
      foreach ($inventory as $vehicle) {
        if (isset($vehicle) && isset($vehicle["condition"]) && strtolower($vehicle["condition"]) == 'new') {
          if (strtolower("escape") == strtolower($vehicle['model']) && (strtolower($vehicle['trim']) == 'plug-in hybrid' || strtolower($vehicle['trim']) == 'phev')){
            $regex = '/(plug-inhybrid|phev)/';
            preg_match($regex, strtolower($vehicle['trim']), $matches);
            if (isset($matches) && count($matches) > 0) {
              $total++;
            }
          }
        }
      }
    }
    else {
      if ($trim) {
        foreach ($inventory as $vehicle) {
          if (isset($vehicle) && isset($vehicle["condition"]) && strtolower($vehicle["condition"]) == 'new') {
            if (strtolower($model) == strtolower($vehicle['model'])) {
              preg_match($regex, strtolower($vehicle['trim']), $matches);
              if (isset($matches) && count($matches) > 0) {
                $total++;
              }
            }
          }
        }
      } else {
        if(strtolower($model) == 'transit'){
          $regex = '/transit (cargo van|cutaway)[a-zA-Z ]*/';
         }
        else if(strtolower($model) == 'superduty'){
          $regex = '/super duty [a-zA-Z ]*/';
        }
        foreach ($inventory as $vehicle) {
          if (isset($vehicle) && isset($vehicle["condition"]) && strtolower($vehicle["condition"]) == 'new') {
            preg_match($regex, strtolower($vehicle['model']), $matches);
            if (isset($matches) && count($matches) > 0) {
              $total++;
            }
          }
        }
      }
    }



  return $total;
}

function modelPrice($regex, $istrim = false)
{
  $inventory = get_search_inventory();

  $price = 0;
  $matches = [];

  foreach ($inventory as $vehicle) {
    if (($vehicle["price"] > 0 && $vehicle["price"] < $price) || $price == 0) {
      if (isset($vehicle) && isset($vehicle["condition"]) && strtolower($vehicle["condition"]) == 'new') {
        if (!$istrim) {
          preg_match($regex, strtolower(str_replace(' ', '-', $vehicle['model'])), $matches);
          if (isset($matches) && count($matches) > 0) {
            $price = $vehicle["price"];
          }
        } else {

          preg_match($regex, strtolower(str_replace(' ', '-', $vehicle['model'])) . '' . strtolower(str_replace(' ', '-', $vehicle['trim'])), $matches);
          if (isset($matches) && count($matches) > 0) {
            $price = $vehicle["price"];
          }
        }
      }
    }
  }

  return currency_format($price);
}

function currency_format_decimals($n,$d)
{
    $lang = get_locale();
    if ($lang == 'fr_CA')
        return (number_format(floatval($n), $d, ',', ' ')) . ' $';
    else
        return "$" . (number_format(floatval($n), $d));
}

function getFormLocale_name($name)
{
  $idiom = get_locale();
  switch ($name) {
    case 'contact-us':
      if (strpos($idiom, 'en') !== false) {
        return $name;
      } else {
        return 'contactez-nous';
      }
      break;
    case 'request-more-information':
      if (strpos($idiom, 'en') !== false) {
        return $name;
      } else {
        return 'demande-d-informations';
      }
      break;
    case 'book-a-test-drive':
      if (strpos($idiom, 'en') !== false) {
        return $name;
      } else {
        return 'reservez-un-essai-routier';
      }
      break;
    case 'trade-in-appraisal':
      if (strpos($idiom, 'en') !== false) {
        return $name;
      } else {
        return 'evaluation-du-vehicule-dechange';
      }
      break;
    case 'confirm-availability':
      if (strpos($idiom, 'en') !== false) {
        return $name;
      } else {
        return 'confirmez-la-disponibilite';
      }
      break;
    case 'book-a-service-appointment':
      if (strpos($idiom, 'en') !== false) {
        return $name;
      } else {
        return 'prenez-rendez-vous';
      }
      break;
    case 'schedule-viewing':
      if (strpos($idiom, 'en') !== false) {
        return $name;
      } else {
        return 'planifier-un-rendez-vous';
      }
      break;
    case 'model-test-drive':
      if (strpos($idiom, 'en') !== false) {
        return $name;
      } else {
        return 'essai-de-modele';
      }
      break;
    case 'model-trade-in':
      if (strpos($idiom, 'en') !== false) {
        return $name;
      } else {
        return 'modele-reprise';
      }
      break;
    case 'model-reserve-now':
      if (strpos($idiom, 'en') !== false) {
        return $name;
      } else {
        return 'modele-reservez-maintenant';
      }
      break;
    case 'model-confirm-availability':
      if (strpos($idiom, 'en') !== false) {
          return $name;
      } else {
          return 'modele-confirmer-la-disponibilite';
      }
      break;
    case 'get-offer-information':
      if (strpos($idiom, 'en') !== false) {
        return $name;
      } else {
        return 'obtenir-des-informations-sur-l-offre';
      }
      break;
    default:
      return $name;
      break;
  }
}

function isFrench()
{
  return false !== strpos(get_locale(), 'fr');
}

function outerLabelOmnisearch($outerLabel)
{
  if (isset($outerLabel)) {
    echo ($outerLabel);
  } else {
    _e('Search', 'leadbox');
  }
}
function innerLabelOmnisearch($innerLabel)
{
  if (isset($innerLabel)) {
    echo ($innerLabel);
  } else {
    _e('Search by Type, Year, Make, Model or Stock #', 'leadbox');
  }
}

function getVehiclesYearUsed($yearVehicle)
{
  $year = date('Y');
  $totalYear = $year - $yearVehicle;
  return $totalYear;
}

function get_leadbox_settings()
{
  return get_option('leadbox-settings');
}

function get_leadbox_finance_settings()
{
  return get_option('dealer-settings-branding-options');
}

function get_leadbox_used_finance_settings()
{
  return get_option('dealer-settings-used-finance-options');
}

function has_dealer_listings() {
  if (function_exists('get_dealer_listings')) {
    if (
      (!empty(get_listing_image_new())) ||
      (!empty(get_listing_image_new_fr())) ||
      (!empty(get_listing_image_used())) ||
      (!empty(get_listing_image_used_fr()))
    ) {
        return true;
    }
  }
  return false;
}


function get_listing_image_new()
{
  $dealer_input = "";
  $listingSettings = get_dealer_listings();
  if (
    isset($listingSettings) && !empty($listingSettings) && isset($listingSettings["image_new"])
    && !empty($listingSettings["image_new"]) && (strlen($listingSettings["image_new"]) > 0)
  ) {
    $dealer_input = $listingSettings["image_new"];
  }

  return $dealer_input;
}
//get listing link new
function get_listing_link_new()
{
  $dealer_input = "";
  $listingSettings = get_dealer_listings();
  if (
    isset($listingSettings) && !empty($listingSettings) && isset($listingSettings["link_new"])
    && !empty($listingSettings["link_new"]) && (strlen($listingSettings["link_new"]) > 0)
  ) {
    $dealer_input = $listingSettings["link_new"];
  }

  return $dealer_input;
}

//get linsting image new fr
function get_listing_image_new_fr()
{
  $dealer_input = "";
  $listingSettings = get_dealer_listings();
  if (
    isset($listingSettings) && !empty($listingSettings) && isset($listingSettings["image_new_fr"])
    && !empty($listingSettings["image_new_fr"]) && (strlen($listingSettings["image_new_fr"]) > 0)
  ) {
    $dealer_input = $listingSettings["image_new_fr"];
  }

  return $dealer_input;
}

//get listing link new fr
function get_listing_link_new_fr()
{
  $dealer_input = "";
  $listingSettings = get_dealer_listings();
  if (
    isset($listingSettings) && !empty($listingSettings) && isset($listingSettings["link_new_fr"])
    && !empty($listingSettings["link_new_fr"]) && (strlen($listingSettings["link_new_fr"]) > 0)
  ) {
    $dealer_input = $listingSettings["link_new_fr"];
  }

  return $dealer_input;
}

//get insert after new
function get_insert_after_new()
{
  $dealer_input = 0;
  $listingSettings = get_dealer_listings();
  if (
    isset($listingSettings) && !empty($listingSettings) && isset($listingSettings["insert_after_new"])
    && !empty($listingSettings["insert_after_new"]) && (strlen($listingSettings["insert_after_new"]) > 0)
  ) {
    $dealer_input = $listingSettings["insert_after_new"];
  }

  return $dealer_input;
}

//get limit date new
function get_limit_date_new()
{
  $dealer_input = "";
  $listingSettings = get_dealer_listings();
  if (
    isset($listingSettings) && !empty($listingSettings) && isset($listingSettings["limit_date_new"])
    && !empty($listingSettings["limit_date_new"]) && (strlen($listingSettings["limit_date_new"]) > 0)
  ) {
    $dealer_input = $listingSettings["limit_date_new"];
  }

  return $dealer_input;
}

//get limit date used
function get_limit_date_used()
{
  $dealer_input = "";
  $listingSettings = get_dealer_listings();
  if (
    isset($listingSettings) && !empty($listingSettings) && isset($listingSettings["limit_date_used"])
    && !empty($listingSettings["limit_date_used"]) && (strlen($listingSettings["limit_date_used"]) > 0)
  ) {
    $dealer_input = $listingSettings["limit_date_used"];
  }

  return $dealer_input;
}


//get activate limit date
function get_activate_limit_date()
{
  $dealer_input = "";
  $listingSettings = get_dealer_listings();
  if (
    isset($listingSettings) && !empty($listingSettings) && isset($listingSettings["activate_limit_date"])
    && !empty($listingSettings["activate_limit_date"]) && (strlen($listingSettings["activate_limit_date"]) > 0)
  ) {
    $dealer_input = $listingSettings["activate_limit_date"];
  }

  return $dealer_input;
}

//get activate limit date used
function get_activate_limit_date_used()
{
  $dealer_input = "";
  $listingSettings = get_dealer_listings();
  if (
    isset($listingSettings) && !empty($listingSettings) && isset($listingSettings["activate_limit_date_used"])
    && !empty($listingSettings["activate_limit_date_used"]) && (strlen($listingSettings["activate_limit_date_used"]) > 0)
  ) {
    $dealer_input = $listingSettings["activate_limit_date_used"];
  }

  return $dealer_input;
}

function has_passed_limit_date() {
  $limit_date = function_exists('get_limit_date_new') ? get_limit_date_new() : null;
  $current_date = date('Y-m-d');
  $activate_limit_date = function_exists('get_activate_limit_date') ? get_activate_limit_date() : 'Disabled';

  // Verificar si la fecha límite es válida
  if (!$limit_date) {
      return false;
  }

  // Convertir fechas a objetos DateTime
  $limit_date_obj = DateTime::createFromFormat('Y-m-d', $limit_date);
  $current_date_obj = DateTime::createFromFormat('Y-m-d', $current_date);

  if (!$limit_date_obj) {
      return false; // Si la fecha límite no se pudo convertir, retornamos false
  }

  return ($activate_limit_date === 'Enabled' && $limit_date_obj < $current_date_obj);
}

function has_passed_limit_date_used() {
  $limit_date = function_exists('get_limit_date_used') ? get_limit_date_used() : null;
  $current_date = date('Y-m-d');
  $activate_limit_date = function_exists('get_activate_limit_date_used') ? get_activate_limit_date_used() : 'Disabled';

  // Verificar si la fecha límite es válida
  if (!$limit_date) {
      return false;
  }

  // Convertir fechas a objetos DateTime
  $limit_date_obj = DateTime::createFromFormat('Y-m-d', $limit_date);
  $current_date_obj = DateTime::createFromFormat('Y-m-d', $current_date);

  if (!$limit_date_obj) {
      return false; // Si la fecha límite no es válida, retorna false
  }

  return ($activate_limit_date === 'Enabled' && $limit_date_obj < $current_date_obj);
}


//get listing image used
function get_listing_image_used()
{
  $dealer_input = "";
  $listingSettings = get_dealer_listings();
  if (
    isset($listingSettings) && !empty($listingSettings) && isset($listingSettings["image_used"])
    && !empty($listingSettings["image_used"]) && (strlen($listingSettings["image_used"]) > 0)
  ) {
    $dealer_input = $listingSettings["image_used"];
  }

  return $dealer_input;
}

//get listing link used
function get_listing_link_used()
{
  $dealer_input = "";
  $listingSettings = get_dealer_listings();
  if (
    isset($listingSettings) && !empty($listingSettings) && isset($listingSettings["link_used"])
    && !empty($listingSettings["link_used"]) && (strlen($listingSettings["link_used"]) > 0)
  ) {
    $dealer_input = $listingSettings["link_used"];
  }

  return $dealer_input;
}

//get listing image used fr
function get_listing_image_used_fr()
{
  $dealer_input = "";
  $listingSettings = get_dealer_listings();
  if (
    isset($listingSettings) && !empty($listingSettings) && isset($listingSettings["image_used_fr"])
    && !empty($listingSettings["image_used_fr"]) && (strlen($listingSettings["image_used_fr"]) > 0)
  ) {
    $dealer_input = $listingSettings["image_used_fr"];
  }

  return $dealer_input;
}

//get listing link used fr
function get_listing_link_used_fr()
{
  $dealer_input = "";
  $listingSettings = get_dealer_listings();
  if (
    isset($listingSettings) && !empty($listingSettings) && isset($listingSettings["link_used_fr"])
    && !empty($listingSettings["link_used_fr"]) && (strlen($listingSettings["link_used_fr"]) > 0)
  ) {
    $dealer_input = $listingSettings["link_used_fr"];
  }

  return $dealer_input;
}


/* -------------------------------------------------------------------------
 * LBT-1462 — Multiple inventory-insert images (repeatable list)
 *
 * The legacy feature stored a single image per (new|used) x (en|fr) slot in
 * the flat option `dealer-settings-listing-options`. This adds a repeatable
 * list stored in `dealer-settings-listing-images-options` (an array of
 * entries). `get_listing_images()` is the single source of truth for the SRP
 * render: when the repeater is empty it transparently migrates the legacy
 * flat keys into equivalent entries, so existing single-image configs keep
 * working without a data write.
 * ---------------------------------------------------------------------- */

//raw repeater option (array of entries) or empty array
function get_dealer_listing_images()
{
  $entries = get_option('dealer-settings-listing-images-options');
  return is_array($entries) ? $entries : array();
}

/**
 * Global config for how the listing-insert images are placed:
 *   mode   'grouped' (default) | 'individual'
 *   offset cards between insertions (grouped mode)
 *   repeat number of full cycles (grouped mode); 0 = repeat until inventory ends
 *
 * Stored in the companion option `dealer-settings-listing-images-config`.
 * Defaults to grouped with the legacy interval as offset so existing
 * single-image configs keep inserting exactly as before.
 */
function get_listing_images_config()
{
  $cfg = get_option('dealer-settings-listing-images-config');
  $cfg = is_array($cfg) ? $cfg : array();

  $mode = isset($cfg['mode']) ? strtolower(trim($cfg['mode'])) : 'grouped';
  if (!in_array($mode, array('grouped', 'individual'), true)) {
    $mode = 'grouped';
  }

  $legacyInterval = function_exists('get_insert_after_new') ? (int) get_insert_after_new() : 0;
  $offset = isset($cfg['offset']) && $cfg['offset'] !== '' ? max(0, (int) $cfg['offset']) : $legacyInterval;
  $repeat = isset($cfg['repeat']) ? max(0, (int) $cfg['repeat']) : 0;

  return array(
    'mode'   => $mode,
    'offset' => $offset,
    'repeat' => $repeat,
  );
}

//fill defaults + cast a single entry to a stable shape
function normalize_listing_image_entry($entry)
{
  $entry = is_array($entry) ? $entry : array();

  $condition = isset($entry['condition']) ? strtolower(trim($entry['condition'])) : 'both';
  if (!in_array($condition, array('new', 'used', 'both'), true)) {
    $condition = 'both';
  }

  $language = isset($entry['language']) ? strtolower(trim($entry['language'])) : 'both';
  if (!in_array($language, array('en', 'fr', 'both'), true)) {
    $language = 'both';
  }

  $target = isset($entry['target']) ? trim($entry['target']) : '_self';
  if (!in_array($target, array('_self', '_blank'), true)) {
    $target = '_self';
  }

  $activate = isset($entry['activate_limit_date']) ? trim($entry['activate_limit_date']) : 'Disabled';
  $activate = ($activate === 'Enabled') ? 'Enabled' : 'Disabled';

  // How the image sits in its card: 'contain' letterboxes (no crop, default),
  // 'cover' fills and crops. Default 'contain' to never lose promo content.
  $fit = isset($entry['fit']) ? strtolower(trim($entry['fit'])) : 'contain';
  if (!in_array($fit, array('cover', 'contain'), true)) {
    $fit = 'contain';
  }

  return array(
    'image'               => isset($entry['image']) ? trim($entry['image']) : '',
    'link'                => isset($entry['link']) ? trim($entry['link']) : '',
    'target'              => $target,
    'insert_after'        => isset($entry['insert_after']) ? max(0, (int) $entry['insert_after']) : 0,
    'repeat_every'        => isset($entry['repeat_every']) ? max(0, (int) $entry['repeat_every']) : 0,
    'condition'           => $condition,
    'language'            => $language,
    'fit'                 => $fit,
    'limit_date'          => isset($entry['limit_date']) ? trim($entry['limit_date']) : '',
    'activate_limit_date' => $activate,
    'alt'                 => isset($entry['alt']) ? trim($entry['alt']) : '',
  );
}

//build entries from the legacy flat keys (backwards-compat migration on read)
function migrate_legacy_listing_images()
{
  // Legacy behaviour REPEATS each image every `insert_after_new` cards (a single
  // global interval drove both New and Used). Preserve that by migrating to a
  // repeating entry (repeat_every = interval), not a one-time insert.
  $interval = function_exists('get_insert_after_new') ? (int) get_insert_after_new() : 0;

  $legacy = array(
    // image getter, link getter, condition, language, limit_date getter, activate getter
    array('get_listing_image_new',     'get_listing_link_new',     'new',  'en', 'get_limit_date_new',  'get_activate_limit_date'),
    array('get_listing_image_new_fr',  'get_listing_link_new_fr',  'new',  'fr', 'get_limit_date_new',  'get_activate_limit_date'),
    array('get_listing_image_used',    'get_listing_link_used',    'used', 'en', 'get_limit_date_used', 'get_activate_limit_date_used'),
    array('get_listing_image_used_fr', 'get_listing_link_used_fr', 'used', 'fr', 'get_limit_date_used', 'get_activate_limit_date_used'),
  );

  $entries = array();
  foreach ($legacy as $row) {
    list($imageFn, $linkFn, $condition, $language, $limitFn, $activateFn) = $row;
    $image = function_exists($imageFn) ? $imageFn() : '';
    if (empty($image)) {
      continue; // only migrate configured slots
    }
    $entries[] = normalize_listing_image_entry(array(
      'image'               => $image,
      'link'                => function_exists($linkFn) ? $linkFn() : '',
      'target'              => '_self',
      'insert_after'        => 0,
      'repeat_every'        => $interval, // reproduce the legacy "repeat every N" behaviour
      'condition'           => $condition,
      'language'            => $language,
      'fit'                 => 'contain', // preserve the legacy natural (no-crop) look
      'limit_date'          => function_exists($limitFn) ? $limitFn() : '',
      'activate_limit_date' => function_exists($activateFn) ? $activateFn() : 'Disabled',
      'alt'                 => '',
    ));
  }

  return $entries;
}

//single source of truth for the SRP render: normalized list, migrated when empty
function get_listing_images()
{
  $entries = get_dealer_listing_images();

  if (!empty($entries)) {
    return array_values(array_filter(array_map('normalize_listing_image_entry', $entries), function ($e) {
      return !empty($e['image']);
    }));
  }

  return migrate_legacy_listing_images();
}

//whether any listing-insert image is configured (new + legacy)
function has_dealer_listing_images()
{
  $images = get_listing_images();
  return !empty($images);
}

//per-entry expiration (mirrors has_passed_limit_date but scoped to one entry)
function listing_image_entry_expired($entry)
{
  $entry = normalize_listing_image_entry($entry);

  if ($entry['activate_limit_date'] !== 'Enabled') {
    return false;
  }
  if (empty($entry['limit_date'])) {
    return false;
  }

  $limit_date_obj = DateTime::createFromFormat('Y-m-d', $entry['limit_date']);
  if (!$limit_date_obj) {
    return false;
  }
  $current_date_obj = DateTime::createFromFormat('Y-m-d', date('Y-m-d'));

  return ($limit_date_obj < $current_date_obj);
}

/**
 * LBT-1462 Round 3: resolve a reusable listing-image group (created in the plugin,
 * option `lbx_listing_image_groups`) into the same shape the SRP render pipeline
 * already consumes — entries[] (normalized) + config{ mode, start, offset, repeat }.
 *
 * Returns null when the group is missing, disabled, or its group-level expiration
 * date has passed (which hides the whole group). Per-image language + expiration are
 * NOT applied here — the blade's existing entry filter handles those uniformly for
 * both the group and the legacy/global source.
 *
 * @param string $group_id  Group id chosen in the Inventory block ('' = none).
 * @return array|null ['config' => [...], 'entries' => [...]] or null.
 */
function get_listing_image_group($group_id)
{
  if (empty($group_id)) {
    return null;
  }

  $groups = get_option('lbx_listing_image_groups', array());
  if (!is_array($groups) || !isset($groups[$group_id]) || !is_array($groups[$group_id])) {
    return null;
  }
  $group = $groups[$group_id];

  // Inactive groups render nothing.
  if (empty($group['active'])) {
    return null;
  }

  // Group-level expiration hides the entire group once the date has passed.
  if (!empty($group['date_enabled']) && !empty($group['limit_date'])) {
    $limit = DateTime::createFromFormat('Y-m-d', $group['limit_date']);
    $today = DateTime::createFromFormat('Y-m-d', date('Y-m-d'));
    if ($limit && $today && $limit < $today) {
      return null;
    }
  }

  $offset = isset($group['offset']) ? max(1, (int) $group['offset']) : 1;

  $images  = (isset($group['images']) && is_array($group['images'])) ? $group['images'] : array();
  $entries = array();
  foreach ($images as $img) {
    if (!is_array($img)) {
      continue;
    }
    // Only active images render (manual on/off). Missing key = active (defensive).
    if (array_key_exists('active', $img) && empty($img['active'])) {
      continue;
    }
    // Map the group image shape to the render entry shape. Position lives on the
    // group (offset), so per-entry insert_after/repeat_every are 0. Condition and
    // language are forced to 'both': a group image shows regardless of the vehicle's
    // new/used status or the page language. The per-image date toggle maps to
    // activate_limit_date so the shared listing_image_entry_expired() filter in the
    // blade drops expired images.
    $entries[] = normalize_listing_image_entry(array(
      'image'               => isset($img['image']) ? $img['image'] : '',
      'link'                => isset($img['link']) ? $img['link'] : '',
      'target'              => isset($img['target']) ? $img['target'] : '_self',
      'insert_after'        => 0,
      'repeat_every'        => 0,
      'condition'           => 'both',
      'language'            => 'both',
      'fit'                 => isset($img['fit']) ? $img['fit'] : 'contain',
      'limit_date'          => isset($img['limit_date']) ? $img['limit_date'] : '',
      'activate_limit_date' => !empty($img['date_enabled']) ? 'Enabled' : 'Disabled',
      'alt'                 => isset($img['alt']) ? $img['alt'] : '',
    ));
  }

  return array(
    // Groups always cycle (grouped mode). No `start` — the first image lands on card
    // `offset` (spa-inventory falls back to start=offset when start is absent).
    // `repeat` = 0 means "until the end of the SRP" (images repeat indefinitely).
    'config'  => array('mode' => 'grouped', 'offset' => $offset, 'repeat' => 0),
    'entries' => $entries,
  );
}


function get_calculated_msrp_label()
{
  if (get_locale() == 'fr_CA') {
    return get_calculated_msrp_fr_label();
  } else {
    return get_calculated_msrp_en_label();
  }
}

function get_calculated_msrp_en_label()
{
  $dealer_input = "Basic MSRP";
  $labelSettings = get_dealer_labels();
  if (
    isset($labelSettings) && !empty($labelSettings) && isset($labelSettings["calculated_msrp"])
    && !empty($labelSettings["calculated_msrp"]) && (strlen($labelSettings["calculated_msrp"]) > 0)
  ) {
    $dealer_input = $labelSettings["calculated_msrp"];
  }

  return $dealer_input;

}

function get_calculated_msrp_fr_label()
{
  $dealer_input = "PDSF de base";
  $labelSettings = get_dealer_labels();
  if (
    isset($labelSettings) && !empty($labelSettings) && isset($labelSettings["calculated_msrp_fr"])
    && !empty($labelSettings["calculated_msrp_fr"]) && (strlen($labelSettings["calculated_msrp_fr"]) > 0)
  ) {
    $dealer_input = $labelSettings["calculated_msrp_fr"];
  }

  return $dealer_input;

}

function get_vehicle_price_label($condition = null)
{
  if(!$condition)
    $condition = "new";

  if($condition == "new"){
    return get_new_vehicle_price_label();
  }
  else {
    return get_used_vehicle_price_label();
  }
}

function get_new_vehicle_price_label()
{
  if (get_locale() == 'fr_CA') {
    return get_new_vehicle_price_fr_label();
  } else {
    return get_new_vehicle_price_en_label();
  }
}

function get_new_vehicle_price_en_label()
{
  $dealer_input = "MSRP";
  $labelSettings = get_dealer_labels();
  if (
    isset($labelSettings) && !empty($labelSettings) && isset($labelSettings["new_vehicle_price"])
    && !empty($labelSettings["new_vehicle_price"]) && (strlen($labelSettings["new_vehicle_price"]) > 0)
  ) {
    $dealer_input = $labelSettings["new_vehicle_price"];
  }

  return $dealer_input;

}

function get_new_vehicle_price_fr_label()
{
  $dealer_input = "PDSF";
  $labelSettings = get_dealer_labels();
  if (
    isset($labelSettings) && !empty($labelSettings) && isset($labelSettings["new_vehicle_price_fr"])
    && !empty($labelSettings["new_vehicle_price_fr"]) && (strlen($labelSettings["new_vehicle_price_fr"]) > 0)
  ) {
    $dealer_input = $labelSettings["new_vehicle_price_fr"];
  }

  return $dealer_input;

}

function get_after_discount_price_label($condition = null)
{
  if(!$condition)
    $condition = "new";

  if($condition == "new"){
    if (get_locale() == 'fr_CA') {
      return get_after_discount_price_fr_label();
    } else {
      return get_after_discount_price_en_label();
    }
  }
  else {
     if (get_locale() == 'fr_CA') {
      return get_used_after_discount_price_fr_label();
    } else {
      return get_used_after_discount_price_en_label();
    }
  }

}

function get_after_discount_price_en_label()
{
  $dealer_input = "";
  $labelSettings = get_dealer_labels();
  if (
    isset($labelSettings) && !empty($labelSettings) && isset($labelSettings["after_discount_price"])
    && !empty($labelSettings["after_discount_price"]) && (strlen($labelSettings["after_discount_price"]) > 0)
  ) {
    $dealer_input = $labelSettings["after_discount_price"];
  }

  return $dealer_input;

}

function get_after_discount_price_fr_label()
{
  $dealer_input = "";
  $labelSettings = get_dealer_labels();
  if (
    isset($labelSettings) && !empty($labelSettings) && isset($labelSettings["after_discount_price_fr"])
    && !empty($labelSettings["after_discount_price_fr"]) && (strlen($labelSettings["after_discount_price_fr"]) > 0)
  ) {
    $dealer_input = $labelSettings["after_discount_price_fr"];
  }

  return $dealer_input;

}

function get_used_after_discount_price_en_label()
{
  $dealer_input = "";
  $labelSettings = get_dealer_labels();
  if (
    isset($labelSettings) && !empty($labelSettings) && isset($labelSettings["used_after_discount_price"])
    && !empty($labelSettings["used_after_discount_price"]) && (strlen($labelSettings["used_after_discount_price"]) > 0)
  ) {
    $dealer_input = $labelSettings["used_after_discount_price"];
  }
  else if (
    isset($labelSettings) && !empty($labelSettings) && isset($labelSettings["after_discount_price"])
    && !empty($labelSettings["after_discount_price"]) && (strlen($labelSettings["after_discount_price"]) > 0)
  ) {
    $dealer_input = $labelSettings["after_discount_price"];
  }

  return $dealer_input;

}

function get_used_after_discount_price_fr_label()
{
  $dealer_input = "";
  $labelSettings = get_dealer_labels();
  if (
    isset($labelSettings) && !empty($labelSettings) && isset($labelSettings["used_after_discount_price_fr"])
    && !empty($labelSettings["used_after_discount_price_fr"]) && (strlen($labelSettings["used_after_discount_price_fr"]) > 0)
  ) {
    $dealer_input = $labelSettings["used_after_discount_price_fr"];
  }
  else if (
    isset($labelSettings) && !empty($labelSettings) && isset($labelSettings["after_discount_price_fr"])
    && !empty($labelSettings["after_discount_price_fr"]) && (strlen($labelSettings["after_discount_price_fr"]) > 0)
  ) {
    $dealer_input = $labelSettings["after_discount_price_fr"];
  }

  return $dealer_input;

}

function get_special_price_label()
{
  if (get_locale() == 'fr_CA') {
    return get_special_price_fr_label();
  } else {
    return get_special_price_en_label();
  }
}


function get_special_price_en_label()
{
  $dealer_input = "Special Price";
  $labelSettings = get_dealer_labels();
  if (
    isset($labelSettings) && !empty($labelSettings) && isset($labelSettings["special_price"])
    && !empty($labelSettings["special_price"]) && (strlen($labelSettings["special_price"]) > 0)
  ) {
    $dealer_input = $labelSettings["special_price"];
  }

  return $dealer_input;

}

function get_special_price_fr_label()
{
  $dealer_input = "Prix spéciale";
  $labelSettings = get_dealer_labels();
  if (
    isset($labelSettings) && !empty($labelSettings) && isset($labelSettings["special_price_fr"])
    && !empty($labelSettings["special_price_fr"]) && (strlen($labelSettings["special_price_fr"]) > 0)
  ) {
    $dealer_input = $labelSettings["special_price_fr"];
  }

  return $dealer_input;

}

function get_special_discount_label()
{
  if (get_locale() == 'fr_CA') {
    return get_special_discount_fr_label();
  } else {
    return get_special_discount_en_label();
  }
}

function get_special_discount_en_label()
{
  $dealer_input = "Special Discount";
  $labelSettings = get_dealer_labels();
  if (
    isset($labelSettings) && !empty($labelSettings) && isset($labelSettings["special_discount_price"])
    && !empty($labelSettings["special_discount_price"]) && (strlen($labelSettings["special_discount_price"]) > 0)
  ) {
    $dealer_input = $labelSettings["special_discount_price"];
  }

  return $dealer_input;

}

function get_special_discount_fr_label()
{
  $dealer_input = "Remise spéciale";
  $labelSettings = get_dealer_labels();
  if (
    isset($labelSettings) && !empty($labelSettings) && isset($labelSettings["special_discount_price_fr"])
    && !empty($labelSettings["special_discount_price_fr"]) && (strlen($labelSettings["special_discount_price_fr"]) > 0)
  ) {
    $dealer_input = $labelSettings["special_discount_price_fr"];
  }

  return $dealer_input;

}

//! Helper tag custom funcion

function getTagStyles($colorLabel, $limitLabel, $version) {
  $backgroundColor = $colorLabel != '#000000' ? "background-color: $colorLabel !important;" : '';
  $adjustedLimitLabel = $version === 1 ? $limitLabel + 1 : $limitLabel; // Sumar 2 al valor original
  $characterTrunk = $limitLabel > 0 ? "width: {$adjustedLimitLabel}ch; display:inline-block;" : 'display: inline-block; white-space: nowrap;';
  return [
      'backgroundColor' => $backgroundColor,
      'characterTrunk' => $characterTrunk
  ];
}

//! Sale pending tags

function get_salepending_tag_label()
{
  if (get_locale() == 'fr_CA') {
    return get_salepending_tag_fr_label();
  } else {
    return get_salepending_tag_en_label();
  }
}

function get_salepending_tag_en_label()
{
  $dealer_input = "Sale Pending";
  $labelSettings = get_dealer_labels();
  if (
    isset($labelSettings) && !empty($labelSettings) && isset($labelSettings["salepending_tag_label"])
    && !empty($labelSettings["salepending_tag_label"]) && (strlen($labelSettings["salepending_tag_label"]) > 0)
  ) {
    $dealer_input = $labelSettings["salepending_tag_label"];
  }

  return $dealer_input;
}

function get_salepending_tag_fr_label()
{
  $dealer_input = "Vente en cours";
  $labelSettings = get_dealer_labels();
  if (
    isset($labelSettings) && !empty($labelSettings) && isset($labelSettings["salepending_tag_label_fr"])
    && !empty($labelSettings["salepending_tag_label_fr"]) && (strlen($labelSettings["salepending_tag_label_fr"]) > 0)
  ) {
    $dealer_input = $labelSettings["salepending_tag_label_fr"];
  }

  return $dealer_input;
}

// color tag salepending
function get_salepending_tag_color_label()
{
  $dealer_input = "bg-primary";
  $labelSettings = get_dealer_labels();
  if (
    isset($labelSettings) && !empty($labelSettings) && isset($labelSettings["salepending_tag_label_color"])
    && !empty($labelSettings["salepending_tag_label_color"]) && (strlen($labelSettings["salepending_tag_label_color"]) != "#000000")
  ) {
    $dealer_input = $labelSettings["salepending_tag_label_color"];
  }

  return $dealer_input;
}
// limit tag salepending
function get_salepending_tag_limit_label()
{
  $dealer_input = 0;
  $labelSettings = get_dealer_labels();
  if (
    isset($labelSettings) && !empty($labelSettings) && isset($labelSettings["salepending_tag_label_limit"])
    && !empty($labelSettings["salepending_tag_label_limit"]) && ($labelSettings["salepending_tag_label_limit"] > 0)
  ) {
    $dealer_input = $labelSettings["salepending_tag_label_limit"];
  }

  return $dealer_input;
}

//! special tag

function get_special_tag_label()
{
  if (get_locale() == 'fr_CA') {
    return get_special_tag_fr_label();
  } else {
    return get_special_tag_en_label();
  }
}

function get_special_tag_en_label()
{
  $dealer_input = "Special";
  $labelSettings = get_dealer_labels();
  if (
    isset($labelSettings) && !empty($labelSettings) && isset($labelSettings["special_tag_label"])
    && !empty($labelSettings["special_tag_label"]) && (strlen($labelSettings["special_tag_label"]) > 0)
  ) {
    $dealer_input = $labelSettings["special_tag_label"];
  }

  return $dealer_input;
}

function get_special_tag_fr_label()
{
  $dealer_input = "Spéciaux";
  $labelSettings = get_dealer_labels();
  if (
    isset($labelSettings) && !empty($labelSettings) && isset($labelSettings["special_tag_label_fr"])
    && !empty($labelSettings["special_tag_label_fr"]) && (strlen($labelSettings["special_tag_label_fr"]) > 0)
  ) {
    $dealer_input = $labelSettings["special_tag_label_fr"];
  }

  return $dealer_input;
}

// color tag special
function get_special_tag_color_label()
{
  $dealer_input = "bg-primary";
  $labelSettings = get_dealer_labels();
  if (
    isset($labelSettings) && !empty($labelSettings) && isset($labelSettings["special_tag_label_color"])
    && !empty($labelSettings["special_tag_label_color"]) && (strlen($labelSettings["special_tag_label_color"]) != "#000000")
  ) {
    $dealer_input = $labelSettings["special_tag_label_color"];
  }

  return $dealer_input;
}
// limit tag special
function get_special_tag_limit_label()
{
  $dealer_input = 0;
  $labelSettings = get_dealer_labels();
  if (
    isset($labelSettings) && !empty($labelSettings) && isset($labelSettings["special_tag_label_limit"])
    && !empty($labelSettings["special_tag_label_limit"]) && ($labelSettings["special_tag_label_limit"] > 0)
  ) {
    $dealer_input = $labelSettings["special_tag_label_limit"];
  }

  return $dealer_input;
}

//! certified tag

function get_certified_tag_label()
{
  if (get_locale() == 'fr_CA') {
    return get_certified_tag_fr_label();
  } else {
    return get_certified_tag_en_label();
  }
}

function get_certified_tag_en_label()
{
  $dealer_input = "Certified";
  $labelSettings = get_dealer_labels();
  if (
    isset($labelSettings) && !empty($labelSettings) && isset($labelSettings["certified_tag_label"])
    && !empty($labelSettings["certified_tag_label"]) && (strlen($labelSettings["certified_tag_label"]) > 0)
  ) {
    $dealer_input = $labelSettings["certified_tag_label"];
  }

  return $dealer_input;
}

function get_certified_tag_fr_label()
{
  $dealer_input = "Certifié";
  $labelSettings = get_dealer_labels();
  if (
    isset($labelSettings) && !empty($labelSettings) && isset($labelSettings["certified_tag_label_fr"])
    && !empty($labelSettings["certified_tag_label_fr"]) && (strlen($labelSettings["certified_tag_label_fr"]) > 0)
  ) {
    $dealer_input = $labelSettings["certified_tag_label_fr"];
  }

  return $dealer_input;
}

// color tag certified
function get_certified_tag_color_label()
{
  $dealer_input = "bg-primary";
  $labelSettings = get_dealer_labels();
  if (
    isset($labelSettings) && !empty($labelSettings) && isset($labelSettings["certified_tag_label_color"])
    && !empty($labelSettings["certified_tag_label_color"]) && (strlen($labelSettings["certified_tag_label_color"]) != "#000000")
  ) {
    $dealer_input = $labelSettings["certified_tag_label_color"];
  }

  return $dealer_input;
}
// limit tag certified
function get_certified_tag_limit_label()
{
  $dealer_input = 0;
  $labelSettings = get_dealer_labels();
  if (
    isset($labelSettings) && !empty($labelSettings) && isset($labelSettings["certified_tag_label_limit"])
    && !empty($labelSettings["certified_tag_label_limit"]) && ($labelSettings["certified_tag_label_limit"] > 0)
  ) {
    $dealer_input = $labelSettings["certified_tag_label_limit"];
  }

  return $dealer_input;
}

//! asis tag

function get_asis_tag_label()
{
  if (get_locale() == 'fr_CA') {
    return get_asis_tag_fr_label();
  } else {
    return get_asis_tag_en_label();
  }
}

function get_asis_tag_en_label()
{
  $dealer_input = "As Is";
  $labelSettings = get_dealer_labels();
  if (
    isset($labelSettings) && !empty($labelSettings) && isset($labelSettings["asis_tag_label"])
    && !empty($labelSettings["asis_tag_label"]) && (strlen($labelSettings["asis_tag_label"]) > 0)
  ) {
    $dealer_input = $labelSettings["asis_tag_label"];
  }

  return $dealer_input;
}

function get_asis_tag_fr_label()
{
  $dealer_input = "Comme si";
  $labelSettings = get_dealer_labels();
  if (
    isset($labelSettings) && !empty($labelSettings) && isset($labelSettings["asis_tag_label_fr"])
    && !empty($labelSettings["asis_tag_label_fr"]) && (strlen($labelSettings["asis_tag_label_fr"]) > 0)
  ) {
    $dealer_input = $labelSettings["asis_tag_label_fr"];
  }

  return $dealer_input;
}

// color tag asis
function get_asis_tag_color_label()
{
  $dealer_input = "bg-primary";
  $labelSettings = get_dealer_labels();
  if (
    isset($labelSettings) && !empty($labelSettings) && isset($labelSettings["asis_tag_label_color"])
    && !empty($labelSettings["asis_tag_label_color"]) && (strlen($labelSettings["asis_tag_label_color"]) != "#000000")
  ) {
    $dealer_input = $labelSettings["asis_tag_label_color"];
  }

  return $dealer_input;
}
// limit tag asis
function get_asis_tag_limit_label()
{
  $dealer_input = 0;
  $labelSettings = get_dealer_labels();
  if (
    isset($labelSettings) && !empty($labelSettings) && isset($labelSettings["asis_tag_label_limit"])
    && !empty($labelSettings["asis_tag_label_limit"]) && ($labelSettings["asis_tag_label_limit"] > 0)
  ) {
    $dealer_input = $labelSettings["asis_tag_label_limit"];
  }

  return $dealer_input;
}

//! incoming tag

function get_incoming_tag_label()
{
  if (get_locale() == 'fr_CA') {
    return get_incoming_tag_fr_label();
  } else {
    return get_incoming_tag_en_label();
  }
}


function get_incoming_tag_en_label()
{
  $dealer_input = "Incoming";
  $labelSettings = get_dealer_labels();
  if (
    isset($labelSettings) && !empty($labelSettings) && isset($labelSettings["incoming_tag_label"])
    && !empty($labelSettings["incoming_tag_label"]) && (strlen($labelSettings["incoming_tag_label"]) > 0)
  ) {
    $dealer_input = $labelSettings["incoming_tag_label"];
  }

  return $dealer_input;
}

function get_incoming_tag_fr_label()
{
  $dealer_input = "En transit";
  $labelSettings = get_dealer_labels();
  if (
    isset($labelSettings) && !empty($labelSettings) && isset($labelSettings["incoming_tag_label_fr"])
    && !empty($labelSettings["incoming_tag_label_fr"]) && (strlen($labelSettings["incoming_tag_label_fr"]) > 0)
  ) {
    $dealer_input = $labelSettings["incoming_tag_label_fr"];
  }

  return $dealer_input;
}
// color tag incoming
function get_incoming_tag_color_label()
{
  $dealer_input = "bg-primary";
  $labelSettings = get_dealer_labels();
  if (
    isset($labelSettings) && !empty($labelSettings) && isset($labelSettings["incoming_tag_label_color"])
    && !empty($labelSettings["incoming_tag_label_color"]) && (strlen($labelSettings["incoming_tag_label_color"]) != "#000000")
  ) {
    $dealer_input = $labelSettings["incoming_tag_label_color"];
  }

  return $dealer_input;
}
// limit tag incoming
function get_incoming_tag_limit_label()
{
  $dealer_input = 0;
  $labelSettings = get_dealer_labels();
  if (
    isset($labelSettings) && !empty($labelSettings) && isset($labelSettings["incoming_tag_label_limit"])
    && !empty($labelSettings["incoming_tag_label_limit"]) && ($labelSettings["incoming_tag_label_limit"] > 0)
  ) {
    $dealer_input = $labelSettings["incoming_tag_label_limit"];
  }

  return $dealer_input;
}

//! Demo Tags

function get_demo_tag_label()
{
  if (get_locale() == 'fr_CA') {
    return get_demo_tag_fr_label();
  } else {
    return get_demo_tag_en_label();
  }
}
function get_demo_tag_en_label()
{
  $dealer_input = "Demo";
  $labelSettings = get_dealer_labels();
  if (
    isset($labelSettings) && !empty($labelSettings) && isset($labelSettings["demo_tag_label"])
    && !empty($labelSettings["demo_tag_label"]) && (strlen(trim($labelSettings["demo_tag_label"])) > 0)
  ) {
    $dealer_input = $labelSettings["demo_tag_label"];
  }

  return $dealer_input;
}

function get_demo_tag_fr_label()
{
  $dealer_input = "Démo";
  $labelSettings = get_dealer_labels();
  if (
    isset($labelSettings) && !empty($labelSettings) && isset($labelSettings["demo_tag_label_fr"])
    && !empty($labelSettings["demo_tag_label_fr"]) && (strlen(trim($labelSettings["demo_tag_label_fr"])) > 0)
  ) {
    $dealer_input = $labelSettings["demo_tag_label_fr"];
  }

  return $dealer_input;
}
// color tag demo
function get_demo_tag_color_label()
{
  $dealer_input = "bg-primary";
  $labelSettings = get_dealer_labels();
  if (
    isset($labelSettings) && !empty($labelSettings) && isset($labelSettings["demo_tag_label_color"])
    && !empty($labelSettings["demo_tag_label_color"]) && (strlen($labelSettings["demo_tag_label_color"]) != "#000000")
  ) {
    $dealer_input = $labelSettings["demo_tag_label_color"];
  }

  return $dealer_input;
}
// limit tag demo
function get_demo_tag_limit_label()
{
  $dealer_input = 0;
  $labelSettings = get_dealer_labels();
  if (
    isset($labelSettings) && !empty($labelSettings) && isset($labelSettings["demo_tag_label_limit"])
    && !empty($labelSettings["demo_tag_label_limit"]) && ($labelSettings["demo_tag_label_limit"] > 0)
  ) {
    $dealer_input = $labelSettings["demo_tag_label_limit"];
  }

  return $dealer_input;
}

function get_tax_and_lic_label($condition = "NEW", $include_tax = false)
{
  if (get_locale() == 'fr_CA') {
    return get_tax_and_lic_fr_label($condition, $include_tax);
  } else {
    return get_tax_and_lic_en_label($condition, $include_tax);
  }
}
function get_tax_and_lic_label_asterix($condition = "NEW", $include_tax = false)
{
  if (get_locale() == 'fr_CA') {
    return get_tax_and_lic_fr_label($condition, $include_tax) . " *";
  } else {
    return get_tax_and_lic_en_label($condition, $include_tax) . " *";
  }
}

function get_tax_and_lic_en_label($condition = "NEW", $include_tax = false)
{
  $dealer_input = $include_tax ? "+ Lic" : "+ Tax & Lic";
  $labelSettings = get_dealer_labels();

  if (strtoupper($condition) === "USED") {
    if (
      isset($labelSettings) && !empty($labelSettings) && isset($labelSettings["used_tax_and_lic_label"])
      && !empty($labelSettings["used_tax_and_lic_label"]) && (strlen($labelSettings["used_tax_and_lic_label"]) > 0)
    ) {
      $dealer_input = $include_tax ? "" : $labelSettings["used_tax_and_lic_label"];
    } elseif (
              isset($labelSettings) && !empty($labelSettings)
              && isset($labelSettings["used_tax_label"]) && !empty($labelSettings["used_tax_label"]) && (strlen($labelSettings["used_tax_label"]) > 0)
              && isset($labelSettings["used_lic_label"]) && !empty($labelSettings["used_lic_label"]) && (strlen($labelSettings["used_lic_label"]) > 0)
              ) {
              $dealer_input = $include_tax ? "+ " . $labelSettings["used_lic_label"] : "+ " . $labelSettings["used_tax_label"] . " & " .  $labelSettings["used_lic_label"];
    }
  } else {
    if (
      isset($labelSettings) && !empty($labelSettings) && isset($labelSettings["tax_and_lic_label"])
      && !empty($labelSettings["tax_and_lic_label"]) && (strlen($labelSettings["tax_and_lic_label"]) > 0)
    ) {
      $dealer_input = $include_tax ? "" : $labelSettings["tax_and_lic_label"];
    } elseif (
              isset($labelSettings) && !empty($labelSettings)
              && isset($labelSettings["new_tax_label"]) && !empty($labelSettings["new_tax_label"]) && (strlen($labelSettings["new_tax_label"]) > 0)
              && isset($labelSettings["new_lic_label"]) && !empty($labelSettings["new_lic_label"]) && (strlen($labelSettings["new_lic_label"]) > 0)
              ) {
              $dealer_input = $include_tax ? "+ " . $labelSettings["new_lic_label"] : "+ " . $labelSettings["new_tax_label"] . " & " .  $labelSettings["new_lic_label"];
    }
  }

  return $dealer_input;

}

function get_tax_and_lic_fr_label($condition = "NEW", $include_tax = false)
{
  $dealer_input = $include_tax ? "+ Imm." : "+ Taxes et Imm";
  $labelSettings = get_dealer_labels();

  if (strtoupper($condition) === "USED") {
    if (
      isset($labelSettings) && !empty($labelSettings) && isset($labelSettings["used_tax_and_lic_label_fr"])
      && !empty($labelSettings["used_tax_and_lic_label_fr"]) && (strlen($labelSettings["used_tax_and_lic_label_fr"]) > 0)
    ) {
      $dealer_input = $include_tax ? "" : $labelSettings["used_tax_and_lic_label_fr"];
    } elseif (
              isset($labelSettings) && !empty($labelSettings)
              && isset($labelSettings["used_tax_label_fr"]) && !empty($labelSettings["used_tax_label_fr"]) && (strlen($labelSettings["used_tax_label_fr"]) > 0)
              && isset($labelSettings["used_lic_label_fr"]) && !empty($labelSettings["used_lic_label_fr"]) && (strlen($labelSettings["used_lic_label_fr"]) > 0)
              ) {
              $dealer_input = $include_tax ? "+ " . $labelSettings["used_lic_label_fr"] : "+ " . $labelSettings["used_tax_label_fr"] . " et " .  $labelSettings["used_lic_label_fr"];
    }
  } else {
    if (
      isset($labelSettings) && !empty($labelSettings) && isset($labelSettings["tax_and_lic_label_fr"])
      && !empty($labelSettings["tax_and_lic_label_fr"]) && (strlen($labelSettings["tax_and_lic_label_fr"]) > 0)
    ) {
      $dealer_input = $include_tax ? "" : $labelSettings["tax_and_lic_label_fr"];
    } elseif (
              isset($labelSettings) && !empty($labelSettings)
              && isset($labelSettings["new_tax_label_fr"]) && !empty($labelSettings["new_tax_label_fr"]) && (strlen($labelSettings["new_tax_label_fr"]) > 0)
              && isset($labelSettings["new_lic_label_fr"]) && !empty($labelSettings["new_lic_label_fr"]) && (strlen($labelSettings["new_lic_label_fr"]) > 0)
              ) {
              $dealer_input = $include_tax ? "+ " . $labelSettings["new_lic_label_fr"] : "+ " . $labelSettings["new_tax_label_fr"] . " et " .  $labelSettings["new_lic_label_fr"];
    }
  }

  return $dealer_input;

}

function get_tax_and_lic_en_label_asterix()
{
  $dealer_input = "+ Tax & Lic *";
  $labelSettings = get_dealer_labels();
  if (
    isset($labelSettings) && !empty($labelSettings) && isset($labelSettings["tax_and_lic_label"])
    && !empty($labelSettings["tax_and_lic_label"]) && (strlen($labelSettings["tax_and_lic_label"]) > 0)
  ) {
    $dealer_input = "+ Tax & Lic *";
  }

  return $dealer_input;

}

function get_tax_and_lic_fr_label_asterix()
{
  $dealer_input = "+ taxes et imm.";
  $labelSettings = get_dealer_labels();
  if (
    isset($labelSettings) && !empty($labelSettings) && isset($labelSettings["tax_and_lic_label_fr"])
    && !empty($labelSettings["tax_and_lic_label_fr"]) && (strlen($labelSettings["tax_and_lic_label_fr"]) > 0)
  ) {
    $dealer_input = "+ taxes et imm. *";
  }

  return $dealer_input;

}

function get_rebates_label()
{
  if (get_locale() == 'fr_CA') {
    return get_rebates_fr_label();
  } else {
    return get_rebates_en_label();
  }
}

function get_rebates_en_label()
{
  $dealer_input = "Discounts and Rebates";
  $labelSettings = get_dealer_labels();
  if (
    isset($labelSettings) && !empty($labelSettings) && isset($labelSettings["rebates_label"])
    && !empty($labelSettings["rebates_label"]) && (strlen($labelSettings["rebates_label"]) > 0)
  ) {
    $dealer_input = $labelSettings["rebates_label"];
  }

  return $dealer_input;

}

function get_rebates_fr_label()
{
  $dealer_input = "Réductions et rabais";
  $labelSettings = get_dealer_labels();
  if (
    isset($labelSettings) && !empty($labelSettings) && isset($labelSettings["rebates_label_fr"])
    && !empty($labelSettings["rebates_label_fr"]) && (strlen($labelSettings["rebates_label_fr"]) > 0)
  ) {
    $dealer_input = $labelSettings["rebates_label_fr"];
  }

  return $dealer_input;

}

function get_additional_rebates_label()
{
  if (get_locale() == 'fr_CA') {
    return get_additional_rebates_fr_label();
  } else {
    return get_additional_rebates_en_label();
  }
}

function get_additional_rebates_en_label()
{
  $dealer_input = "Additional Rebate";
  $labelSettings = get_dealer_labels();
  if (
    isset($labelSettings) && !empty($labelSettings) && isset($labelSettings["additional_rebates_label"])
    && !empty($labelSettings["additional_rebates_label"]) && (strlen($labelSettings["additional_rebates_label"]) > 0)
  ) {
    $dealer_input = $labelSettings["additional_rebates_label"];
  }

  return $dealer_input;

}

function get_additional_rebates_fr_label()
{
  $dealer_input = "Rabais supplémentaires";
  $labelSettings = get_dealer_labels();
  if (
    isset($labelSettings) && !empty($labelSettings) && isset($labelSettings["additional_rebates_label_fr"])
    && !empty($labelSettings["additional_rebates_label_fr"]) && (strlen($labelSettings["additional_rebates_label_fr"]) > 0)
  ) {
    $dealer_input = $labelSettings["additional_rebates_label_fr"];
  }

  return $dealer_input;

}

function get_used_vehicle_price_label()
{
  if (get_locale() == 'fr_CA') {
    return get_used_vehicle_price_fr_label();
  } else {
    return get_used_vehicle_price_en_label();
  }
}

function get_used_vehicle_price_en_label()
{
  $dealer_input = "Vehicle Price";
  $labelSettings = get_dealer_labels();
  if (
    isset($labelSettings) && !empty($labelSettings) && isset($labelSettings["used_vehicle_price"])
    && !empty($labelSettings["used_vehicle_price"]) && (strlen($labelSettings["used_vehicle_price"]) > 0)
  ) {
    $dealer_input = $labelSettings["used_vehicle_price"];
  }

  return $dealer_input;
}

function get_used_vehicle_price_fr_label()
{
  $dealer_input = "Prix ​​du véhicule";
  $labelSettings = get_dealer_labels();
  if (
    isset($labelSettings) && !empty($labelSettings) && isset($labelSettings["used_vehicle_price_fr"])
    && !empty($labelSettings["used_vehicle_price_fr"]) && (strlen($labelSettings["used_vehicle_price_fr"]) > 0)
  ) {
    $dealer_input = $labelSettings["used_vehicle_price_fr"];
  }

  return $dealer_input;

}

function get_phone_sales_label()
{
  if (get_locale() == 'fr_CA') {
    return get_phone_sales_fr_label();
  } else {
    return get_phone_sales_en_label();
  }
}

function get_phone_sales_en_label()
{
  $dealer_input = "Sales";
  $labelSettings = get_dealer_labels();
  if (
    isset($labelSettings) && !empty($labelSettings) && isset($labelSettings["phone_sales_label"])
    && !empty($labelSettings["phone_sales_label"]) && (strlen($labelSettings["phone_sales_label"]) > 0)
  ) {
    $dealer_input = $labelSettings["phone_sales_label"];
  }

  return $dealer_input;

}

function get_phone_sales_fr_label()
{
  $dealer_input = "Ventes";
  $labelSettings = get_dealer_labels();
  if (
    isset($labelSettings) && !empty($labelSettings) && isset($labelSettings["phone_sales_label_fr"])
    && !empty($labelSettings["phone_sales_label_fr"]) && (strlen($labelSettings["phone_sales_label_fr"]) > 0)
  ) {
    $dealer_input = $labelSettings["phone_sales_label_fr"];
  }

  return $dealer_input;

}

function get_phone_parts_label()
{
  if (get_locale() == 'fr_CA') {
    return get_phone_parts_fr_label();
  } else {
    return get_phone_parts_en_label();
  }
}

function get_phone_parts_en_label()
{
  $dealer_input = "Parts";
  $labelSettings = get_dealer_labels();
  if (
    isset($labelSettings) && !empty($labelSettings) && isset($labelSettings["phone_parts_label"])
    && !empty($labelSettings["phone_parts_label"]) && (strlen($labelSettings["phone_parts_label"]) > 0)
  ) {
    $dealer_input = $labelSettings["phone_parts_label"];
  }

  return $dealer_input;

}

function get_phone_parts_fr_label()
{
  $dealer_input = "Pièces";
  $labelSettings = get_dealer_labels();
  if (
    isset($labelSettings) && !empty($labelSettings) && isset($labelSettings["phone_parts_label_fr"])
    && !empty($labelSettings["phone_parts_label_fr"]) && (strlen($labelSettings["phone_parts_label_fr"]) > 0)
  ) {
    $dealer_input = $labelSettings["phone_parts_label_fr"];
  }

  return $dealer_input;

}

function get_phone_service_label()
{
  if (get_locale() == 'fr_CA') {
    return get_phone_service_fr_label();
  } else {
    return get_phone_service_en_label();
  }
}

function get_phone_service_en_label()
{
  $dealer_input = "Service";
  $labelSettings = get_dealer_labels();
  if (
    isset($labelSettings) && !empty($labelSettings) && isset($labelSettings["phone_service_label"])
    && !empty($labelSettings["phone_service_label"]) && (strlen($labelSettings["phone_service_label"]) > 0)
  ) {
    $dealer_input = $labelSettings["phone_service_label"];
  }

  return $dealer_input;

}

function get_phone_service_fr_label()
{
  $dealer_input = "Service";
  $labelSettings = get_dealer_labels();
  if (
    isset($labelSettings) && !empty($labelSettings) && isset($labelSettings["phone_service_label_fr"])
    && !empty($labelSettings["phone_service_label_fr"]) && (strlen($labelSettings["phone_service_label_fr"]) > 0)
  ) {
    $dealer_input = $labelSettings["phone_service_label_fr"];
  }

  return $dealer_input;

}

function get_phone_fax_label()
{
  return isFrench()
    ? get_phone_fax_fr_label()
    : get_phone_fax_en_label();
}

function get_phone_fax_en_label()
{
  $dealer_input = "Fax";
  $labelSettings = get_dealer_labels();
  if (
    isset($labelSettings) && !empty($labelSettings) && isset($labelSettings["phone_fax_label"])
    && !empty($labelSettings["phone_fax_label"]) && (strlen($labelSettings["phone_fax_label"]) > 0)
  ) {
    $dealer_input = $labelSettings["phone_fax_label"];
  }

  return $dealer_input;

}

function get_phone_fax_fr_label()
{
  $dealer_input = "Fax";
  $labelSettings = get_dealer_labels();
  if (
    isset($labelSettings) && !empty($labelSettings) && isset($labelSettings["phone_fax_label_fr"])
    && !empty($labelSettings["phone_fax_label_fr"]) && (strlen($labelSettings["phone_fax_label_fr"]) > 0)
  ) {
    $dealer_input = $labelSettings["phone_fax_label_fr"];
  }

  return $dealer_input;

}

function get_phone_body_shop_label()
{
  return isFrench()
    ? get_phone_body_shop_fr_label()
    : get_phone_body_shop_en_label();
}

function get_phone_body_shop_en_label()
{
  $dealer_input = "Body Shop";
  $labelSettings = get_dealer_labels();
  if (
    isset($labelSettings) && !empty($labelSettings) && isset($labelSettings["phone_body_shop_label"])
    && !empty($labelSettings["phone_body_shop_label"]) && (strlen($labelSettings["phone_body_shop_label"]) > 0)
  ) {
    $dealer_input = $labelSettings["phone_body_shop_label"];
  }

  return $dealer_input;

}

function get_phone_body_shop_fr_label()
{
  $dealer_input = "Atelier de carrosserie";
  $labelSettings = get_dealer_labels();
  if (
    isset($labelSettings) && !empty($labelSettings) && isset($labelSettings["phone_body_shop_label_fr"])
    && !empty($labelSettings["phone_body_shop_label_fr"]) && (strlen($labelSettings["phone_body_shop_label_fr"]) > 0)
  ) {
    $dealer_input = $labelSettings["phone_body_shop_label_fr"];
  }

  return $dealer_input;

}

function get_phone_sms_label()
{
  return isFrench()
    ? get_phone_sms_fr_label()
    : get_phone_sms_en_label();
}

function get_phone_sms_en_label()
{
  $dealer_input = "SMS";
  $labelSettings = get_dealer_labels();
  if (
    isset($labelSettings) && !empty($labelSettings) && isset($labelSettings["phone_sms_label"])
    && !empty($labelSettings["phone_sms_label"]) && (strlen($labelSettings["phone_sms_label"]) > 0)
  ) {
    $dealer_input = $labelSettings["phone_sms_label"];
  }

  return $dealer_input;

}

function get_phone_sms_fr_label()
{
  $dealer_input = "SMS";
  $labelSettings = get_dealer_labels();
  if (
    isset($labelSettings) && !empty($labelSettings) && isset($labelSettings["phone_sms_label_fr"])
    && !empty($labelSettings["phone_sms_label_fr"]) && (strlen($labelSettings["phone_sms_label_fr"]) > 0)
  ) {
    $dealer_input = $labelSettings["phone_sms_label_fr"];
  }

  return $dealer_input;

}

function get_phone_collision_label()
{
  return isFrench()
    ? get_phone_collision_fr_label()
    : get_phone_collision_en_label();
}

function get_phone_collision_en_label()
{
  $dealer_input = "Collision";
  $labelSettings = get_dealer_labels();
  if (
    isset($labelSettings) && !empty($labelSettings) && isset($labelSettings["phone_collision_label"])
    && !empty($labelSettings["phone_collision_label"]) && (strlen($labelSettings["phone_collision_label"]) > 0)
  ) {
    $dealer_input = $labelSettings["phone_collision_label"];
  }

  return $dealer_input;

}

function get_phone_collision_fr_label()
{
  $dealer_input = "Collision";
  $labelSettings = get_dealer_labels();
  if (
    isset($labelSettings) && !empty($labelSettings) && isset($labelSettings["phone_collision_label_fr"])
    && !empty($labelSettings["phone_collision_label_fr"]) && (strlen($labelSettings["phone_collision_label_fr"]) > 0)
  ) {
    $dealer_input = $labelSettings["phone_collision_label_fr"];
  }

  return $dealer_input;

}

function get_phone_accessories_label()
{
  return isFrench()
    ? get_phone_accessories_fr_label()
    : get_phone_accessories_en_label();
}

function get_phone_accessories_en_label()
{
  $dealer_input = "Accessories";
  $labelSettings = get_dealer_labels();
  if (
    isset($labelSettings) && !empty($labelSettings) && isset($labelSettings["phone_accessories_label"])
    && !empty($labelSettings["phone_accessories_label"]) && (strlen($labelSettings["phone_accessories_label"]) > 0)
  ) {
    $dealer_input = $labelSettings["phone_accessories_label"];
  }

  return $dealer_input;

}

function get_phone_accessories_fr_label()
{
  $dealer_input = "Accessoires";
  $labelSettings = get_dealer_labels();
  if (
    isset($labelSettings) && !empty($labelSettings) && isset($labelSettings["phone_accessories_label_fr"])
    && !empty($labelSettings["phone_accessories_label_fr"]) && (strlen($labelSettings["phone_accessories_label_fr"]) > 0)
  ) {
    $dealer_input = $labelSettings["phone_accessories_label_fr"];
  }

  return $dealer_input;

}


/* Hooks tester */
function test_hook()
{
  echo ('This hook works!');
}

function get_lbx_image_path($route)
{
  $fr_path = isFrench() ? 'fr/' : '';

  $childRoute = get_stylesheet_directory() . '/assets/images/' . $fr_path;
  $childRouteUri = get_stylesheet_directory_uri() . '/assets/images/' . $fr_path;

  $parentRouteUri = get_template_directory_uri() . '/resources/images/' . $fr_path;

  return file_exists($childRoute . $route)
    ? $childRouteUri . $route
    : $parentRouteUri . $route;
}

function url_exists($file)
{
  // $file_headers = @get_headers($file);
  // foreach($file_headers as $key => $value){
  //     if ($value == 'HTTP/1.1 404 Not Found'){
  //         return false;
  //     }
  // }
  return true;
}

//Exclude pages from WordPress Search
function french_time_format($str_time)
{
  $exploded_str_time = explode(':', $str_time);
  $hours = (strpos($str_time, 'pm') && $exploded_str_time[0] != 12) ?
    $exploded_str_time[0] + 12 :
    $exploded_str_time[0];

  $minutes = preg_replace(['/am/', '/pm/'], ['', ''], $exploded_str_time[1]);

  return $hours . 'h' . $minutes;
}

function get_dealer_french_hours($hours)
{
  foreach ($hours["sale"] as $key => $value)
    if ($value != 'Closed') {
      $exploded_time = explode('-', str_replace(' ', '', $value));
      $since_time = french_time_format($exploded_time[0]);
      $to_time = french_time_format($exploded_time[1]);
      $hours["sale"] = $since_time . " - " . $to_time;
    }
  foreach ($hours["service"] as $key => $value)
    if ($value != 'Closed') {
      $exploded_time = explode('-', str_replace(' ', '', $value));
      $since_time = french_time_format($exploded_time[0]);
      $to_time = french_time_format($exploded_time[1]);
      $hours["service"] = $since_time . " - " . $to_time;
    }
  foreach ($hours["parts"] as $key => $value)
    if ($value != 'Closed') {
      $exploded_time = explode('-', str_replace(' ', '', $value));
      $since_time = french_time_format($exploded_time[0]);
      $to_time = french_time_format($exploded_time[1]);
      $hours["parts"] = $since_time . " - " . $to_time;
    }

  return $hours;
}

function get_min_open_today($day)
{
  $hours = get_dealer_hours();
  $hours_additional_settings = get_dealer_hours_additional();
  $sale_hours = $hours["sale"];
  $service_hours = $hours["service"];
  $parts_hours = $hours["parts"];
  $exploded_time = explode('-', str_replace(' ', '', $sale_hours[ucfirst($day)]));
  $exploded_time_service = explode('-', str_replace(' ', '', $service_hours[ucfirst($day)]));
  $exploded_time_parts = explode('-', str_replace(' ', '', $parts_hours[ucfirst($day)]));
  $hours_array = [];

  if ($exploded_time[0] != 'Closed') {
    array_push($hours_array, date("H:i", strtotime($exploded_time[0])));
  }
  if ($exploded_time_service[0] != 'Closed' && $hours_additional_settings['servicehourstatus'] == 'Enabled') {
    array_push($hours_array, date("H:i", strtotime($exploded_time_service[0])));
  }
  if ($exploded_time_parts[0] != 'Closed' && $hours_additional_settings['parthourstatus'] == 'Enabled') {
    array_push($hours_array, date("H:i", strtotime($exploded_time_parts[0])));
  }

  if (count($hours_array) == 0)
    return 'Closed';

  sort($hours_array);

  if (!isFrench()) {
    return date('g:ia', strtotime($hours_array[0]));
  } else {
    return french_time_format(date('h:ia', strtotime($hours_array[0])));
  }
}

function get_max_open_today($day)
{
  $hours = get_dealer_hours();
  $hours_additional_settings = get_dealer_hours_additional();
  $sale_hours = $hours["sale"];
  $service_hours = $hours["service"];
  $parts_hours = $hours["parts"];
  $exploded_time = explode('-', str_replace(' ', '', $sale_hours[ucfirst($day)]));
  $exploded_time_service = explode('-', str_replace(' ', '', $service_hours[ucfirst($day)]));
  $exploded_time_parts = explode('-', str_replace(' ', '', $parts_hours[ucfirst($day)]));
  $hours_array = [];

  if ($exploded_time[0] != 'Closed') {
    array_push($hours_array, date("H:i", strtotime($exploded_time[1])));
  }
  if ($exploded_time_service[0] != 'Closed' && $hours_additional_settings['servicehourstatus'] == 'Enabled') {
    array_push($hours_array, date("H:i", strtotime($exploded_time_service[1])));
  }
  if ($exploded_time_parts[0] != 'Closed' && $hours_additional_settings['parthourstatus'] == 'Enabled') {
    array_push($hours_array, date("H:i", strtotime($exploded_time_parts[1])));
  }

  if (count($hours_array) == 0)
    return 'Closed';

  rsort($hours_array);

  if (!isFrench()) {
    return date('g:ia', strtotime($hours_array[0]));
  } else {
    return french_time_format(date('h:ia', strtotime($hours_array[0])));
  }
}


/* GET FORD ADOBE TAGGING */
function show_ford_adobe_tagging()
{
  $show = false;
  $lbSettings = get_leadbox_settings();
  if (
    isset($lbSettings) && !empty($lbSettings) && isset($lbSettings["ford_adobe_option"])
    && !empty($lbSettings["ford_adobe_option"]) && (strtolower($lbSettings["ford_adobe_option"]) == "enabled")
  ) {
    $show = true;
  }

  return $show;
}

/* SHOW MODEL E PRICE */
function show_model_e_setting()
{
  $show = false;
  $lbSettings = get_leadbox_settings();
  if (
    isset($lbSettings) && !empty($lbSettings) && isset($lbSettings["model_e_setting"])
    && !empty($lbSettings["model_e_setting"]) && (strtolower($lbSettings["model_e_setting"]) == "enabled")
  ) {
    $show = true;
  }

  return $show;
}

/* GET FORD DEALER CODE */
function get_ford_dealer_code()
{
  $dealer_code = null;
  $lbSettings = get_leadbox_settings();
  if (
    isset($lbSettings) && !empty($lbSettings) && isset($lbSettings["ford_dealer_code"])
    && !empty($lbSettings["ford_dealer_code"]) && (strlen($lbSettings["ford_dealer_code"]) > 0)
  ) {
    $dealer_code = $lbSettings["ford_dealer_code"];
  }

  return $dealer_code;
}

function get_graphql_url()
{
  $graphql_url = null;
  $lbSettings = get_leadbox_settings();
  if (
    isset($lbSettings) && !empty($lbSettings) && isset($lbSettings["graphql_url"])
    && !empty($lbSettings["graphql_url"]) && (strlen($lbSettings["graphql_url"]) > 0)
  ) {
    $graphql_url = $lbSettings["graphql_url"];
  }

  return $graphql_url;
}

function get_live_agent_option()
{
  $dealer_code = null;
  $lbSettings = get_leadbox_settings();
  if (
    isset($lbSettings) && !empty($lbSettings) && isset($lbSettings["live_agent"])
    && !empty($lbSettings["live_agent"]) && (strlen($lbSettings["live_agent"]) > 0)
  ) {
    $dealer_code = $lbSettings["live_agent"];
  }

  return $dealer_code;
}

function get_live_agent_code()
{
  $dealer_code = null;
  $lbSettings = get_leadbox_settings();
  if (
    isset($lbSettings) && !empty($lbSettings) && isset($lbSettings["live_agent_code"])
    && !empty($lbSettings["live_agent_code"]) && (strlen($lbSettings["live_agent_code"]) > 0)
  ) {
    $dealer_code = $lbSettings["live_agent_code"];
  }

  return $dealer_code;
}

function get_moto_insight_option()
{
  $option = "disabled";
  $lbSettings = get_leadbox_settings();
  if (
    isset($lbSettings) && !empty($lbSettings) && isset($lbSettings["moto_insight"])
    && !empty($lbSettings["moto_insight"]) && (strlen($lbSettings["moto_insight"]) > 0)
  ) {
    $option = strtolower($lbSettings["moto_insight"]);
  }

  return $option;
}

function get_moto_insight_url()
{
  $dealer_input = null;
  $lbSettings = get_leadbox_settings();
  if (
    isset($lbSettings) && !empty($lbSettings) && isset($lbSettings["moto_insight_url"])
    && !empty($lbSettings["moto_insight_url"]) && (strlen($lbSettings["moto_insight_url"]) > 0)
  ) {
    $dealer_input = $lbSettings["moto_insight_url"];
  }
  return $dealer_input;
}

function show_moto_insight_button()
{
  if (get_moto_insight_option() == 'enabled' && get_moto_insight_url() != '') {
    return true;
  } else {
    return false;
  }
}

function get_moto_insight_label()
{
  $dealer_input = "BUILD YOUR DEAL";
  $lbSettings = get_leadbox_settings();
  if (
    isset($lbSettings) && !empty($lbSettings) && isset($lbSettings["moto_insight_label"])
    && !empty($lbSettings["moto_insight_label"]) && (strlen($lbSettings["moto_insight_label"]) > 0)
  ) {
    $dealer_input = $lbSettings["moto_insight_label"];
  }

  return $dealer_input;

}

function get_moto_insight_label_fr()
{
  $dealer_input = "CONSTRUISEZ VOTRE OFFRE";
  $lbSettings = get_leadbox_settings();
  if (
    isset($lbSettings) && !empty($lbSettings) && isset($lbSettings["moto_insight_label_fr"])
    && !empty($lbSettings["moto_insight_label_fr"]) && (strlen($lbSettings["moto_insight_label_fr"]) > 0)
  ) {
    $dealer_input = $lbSettings["moto_insight_label_fr"];
  }
  return $dealer_input;
}

function get_carfax_option()
{
  $option = "disabled";
  $lbSettings = get_leadbox_settings();
  if (
    isset($lbSettings) && !empty($lbSettings) && isset($lbSettings["carfax"])
    && !empty($lbSettings["carfax"]) && (strlen($lbSettings["carfax"]) > 0)
  ) {
    $option = strtolower($lbSettings["carfax"]);
  }

  return $option;
}


function get_cartender_option()
{
  $option = "disabled";
  $lbSettings = get_leadbox_settings();
  if (
    isset($lbSettings) && !empty($lbSettings) && isset($lbSettings["cartender"])
    && !empty($lbSettings["cartender"]) && (strlen($lbSettings["cartender"]) > 0)
  ) {
    $option = strtolower($lbSettings["cartender"]);
  }

  return $option;
}

function get_cartender_url()
{
  $dealer_input = null;
  $lbSettings = get_leadbox_settings();
  if (
    isset($lbSettings) && !empty($lbSettings) && isset($lbSettings["cartender_url"])
    && !empty($lbSettings["cartender_url"]) && (strlen($lbSettings["cartender_url"]) > 0)
  ) {
    $dealer_input = $lbSettings["cartender_url"];
  }
  return $dealer_input;
}

function show_cartender_button()
{
  if (get_cartender_option() == 'enabled' && get_cartender_url() != '') {
    return true;
  } else {
    return false;
  }
}

function get_cartender_label()
{
  $dealer_input = "VIDEO OVERVIEW";
  $lbSettings = get_leadbox_settings();
  if (
    isset($lbSettings) && !empty($lbSettings) && isset($lbSettings["cartender_label"])
    && !empty($lbSettings["cartender_label"]) && (strlen($lbSettings["cartender_label"]) > 0)
  ) {
    $dealer_input = $lbSettings["cartender_label"];
  }

  return $dealer_input;

}

function get_cartender_label_fr()
{
  $dealer_input = "VIDEO OVERVIEW";
  $lbSettings = get_leadbox_settings();
  if (
    isset($lbSettings) && !empty($lbSettings) && isset($lbSettings["cartender_label_fr"])
    && !empty($lbSettings["cartender_label_fr"]) && (strlen($lbSettings["cartender_label_fr"]) > 0)
  ) {
    $dealer_input = $lbSettings["cartender_label_fr"];
  }
  return $dealer_input;
}

const LBX_ADOBE_JSON = <<<'JSON'
[
  {
    "nonvehicle": [
      {
        "pagename": "dc:specials:offers:contact us:thank you",
        "channel": "specials",
        "hier": "specials",
        "pagenamenovehicle": "dc:specials:offers:contact us:thank you",
        "slugs": "contact-us-specials-offers,contact-specials-offers,specials-offers",
        "tool": "default form",
        "tooldescriptor": "offers:contact",
        "leadtype": "offers:contact",
        "variantname": "form-submit",
        "action": "lead submitted|tool"
      },
      {
        "pagename": "dc:specials:new specials:contact us:thank you",
        "channel": "specials",
        "hier": "specials",
        "pagenamenovehicle": "dc:specials:new specials:contact us:thank you",
        "slugs": "contact-us-new-specials,contact-new-specials,new-specials",
        "tool": "default form",
        "tooldescriptor": "new specials:contact",
        "leadtype": "new specials:contact",
        "variantname": "form-submit",
        "action": "lead submitted|tool"
      },
      {
        "pagename": "dc:specials:used specials:contact us:thank you",
        "channel": "specials",
        "hier": "specials",
        "pagenamenovehicle": "dc:specials:used specials:contact us:thank you",
        "slugs": "contact-us-used-specials,contact-used-specials,used-specials",
        "tool": "default form",
        "tooldescriptor": "used specials:contact",
        "leadtype": "used specials:contact",
        "variantname": "form-submit",
        "action": "lead submitted|tool"
      },
      {
        "pagename": "dc:specials:finance:contact us:thank you",
        "channel": "specials",
        "hier": "specials",
        "pagenamenovehicle": "dc:specials:finance:contact us:thank you",
        "slugs": "contact-us-finance,contact-finance,finance",
        "tool": "default form",
        "tooldescriptor": "finance:contact",
        "leadtype": "finance:contact",
        "variantname": "form-submit",
        "action": "lead submitted|tool"
      },
      {
        "pagename": "dc:specials:service:contact us:thank you",
        "channel": "specials",
        "hier": "specials",
        "pagenamenovehicle": "dc:specials:service:contact us:thank you",
        "slugs": "contact-us-specials-service,contact-us-service-specials,contact-specials-service,specials-service",
        "tool": "default form",
        "tooldescriptor": "service:contact",
        "leadtype": "service:contact",
        "variantname": "form-submit",
        "action": "lead submitted|tool"
      },
      {
        "pagename": "dc:specials:parts:contact us:thank you",
        "channel": "specials",
        "hier": "specials",
        "pagenamenovehicle": "dc:specials:parts:contact us:thank you",
        "slugs": "contact-us-specials-parts,contact-us-parts-specials,contact-specials-parts,specials-parts",
        "tool": "default form",
        "tooldescriptor": "parts:contact",
        "leadtype": "parts:contact",
        "variantname": "form-submit",
        "action": "lead submitted|tool"
      },
      {
        "pagename": "dc:service:request appointment:thank you",
        "channel": "service and parts",
        "hier": "service and parts:request appointment",
        "pagenamenovehicle": "dc:service:request appointment:thank you",
        "slugs": "book-an-appointment,book-appointment,service,request-appointment,schedule-service,book-a-service-appointment,service-appointment",
        "tool": "default form",
        "tooldescriptor": "request appointment",
        "leadtype": "request appointment",
        "variantname": "form-submit",
        "action": "lead submitted|tool"
      },
      {
        "pagename": "dc:service:order parts:contact us:thank you",
        "channel": "service and parts",
        "hier": "service and parts:order parts",
        "pagenamenovehicle": "dc:service:order parts:contact us:thank you",
        "slugs": "parts,contact-us-service-order-parts,order-parts",
        "tool": "default form",
        "tooldescriptor": "order parts:contact",
        "leadtype": "order parts:contact",
        "variantname": "form-submit",
        "action": "lead submitted|tool"
      },
      {
        "pagename": "dc:service:accessories:contact us:thank you",
        "channel": "service and parts",
        "hier": "service and parts:accessories",
        "pagenamenovehicle": "dc:service:accessories:contact us:thank you",
        "slugs": "accessories,contact-us-service-accessories,service-accessories,order-accessories",
        "tool": "default form",
        "tooldescriptor": "accessories:contact",
        "leadtype": "accessories:contact",
        "variantname": "form-submit",
        "action": "lead submitted|tool"
      },
      {
        "pagename": "dc:ev lifestyle:test drive:thank you",
        "channel": "ev landing page",
        "hier": "shopping tools:ev lifestyle:test drive",
        "pagenamenovehicle": "dc:ev lifestyle:test drive:thank you",
        "slugs": "ev-lifestyle-test-drive-thank-you",
        "tool": "event:lead submitted",
        "tooldescriptor": "ev lifestyle:test drive",
        "leadtype": "ev ownership:test drive:thank you",
        "variantname": "test-drive-submit",
        "action": "lead submitted|test drive|tool"
      },
      {
        "pagename": "dc:ev ownership:contact us:thank you",
        "channel": "ev ownership",
        "hier": "ev ownership",
        "pagenamenovehicle": "dc:ev ownership:contact us:thank you",
        "slugs": "ev-ownership-contact-us-thank-you",
        "tool": "ev ownership:contact us",
        "tooldescriptor": "ev ownership:contact us",
        "leadtype": "ev ownership:contact us",
        "variantname": "form-submit",
        "action": "lead submitted|tool"
      },
      {
        "pagename": "dc:ev lifestyle:contact us:thank you",
        "channel": "ev landing page",
        "hier": "ev lifestyle",
        "pagenamenovehicle": "dc:ev lifestyle:contact us:thank you",
        "slugs": "ev-lifestyle-contact-us-thank-you",
        "tool": "ev lifestyle:contact us",
        "tooldescriptor": "ev lifestyle:contact us",
        "leadtype": "ev lifestyle:contact us",
        "variantname": "form-submit",
        "action": "lead submitted|tool"
      },
      {
        "pagename": "dc:ev vhp:contact us:thank you",
        "channel": "ev vhp",
        "hier": "shopping tools:ev vhp:contact us",
        "pagenamenovehicle": "dc:ev vhp:contact us:thank you",
        "slugs": "ev-vhp-contact-us-thank-you",
        "tool": "ev vhp:contact us",
        "tooldescriptor": "ev vhp:contact",
        "leadtype": "ev vhp:contact",
        "variantname": "form-submit",
        "action": "lead submitted|tool"
      },
      {
        "pagename": "dc:about us:thank you",
        "channel": "about us",
        "hier": "about us",
        "pagenamenovehicle": "dc:about us:thank you",
        "slugs": "about-us,contact-about-us,contact-us-about-us",
        "tool": "default form",
        "tooldescriptor": "about us:contact",
        "leadtype": "about us:contact",
        "variantname": "form-submit",
        "action": "lead submitted|tool"
      },
      {
        "pagename": "dc:about us:contact us:thank you",
        "channel": "about us",
        "hier": "about us:contact us",
        "pagenamenovehicle": "dc:about us:contact us:thank you",
        "slugs": "contact,contact-us",
        "tool": "default form",
        "tooldescriptor": "contact us:contact",
        "leadtype": "contact us:contact",
        "variantname": "form-submit",
        "action": "lead submitted|tool"
      },
      {
        "pagename": "dc:about us:careers:contact us:thank you",
        "channel": "about us",
        "hier": "about us:careers",
        "pagenamenovehicle": "dc:about us:careers:contact us:thank you",
        "slugs": "contact-us-careers,careers",
        "tool": "default form",
        "tooldescriptor": "careers:contact",
        "leadtype": "careers:contact",
        "variantname": "form-submit",
        "action": "lead submitted|tool"
      },
      {
        "pagename": "dc:test drive:thank you",
        "channel": "test drive",
        "hier": "shopping tools:test drive",
        "pagenamenovehicle": "dc:test drive:thank you",
        "slugs": "test-drive,schedule-test-drive,book-test-drive,test-drive-no-vehicle,book-a-test-drive-no-vehicle",
        "tool": "event:lead submitted",
        "tooldescriptor": "test drive",
        "leadtype": "test drive",
        "variantname": "test-drive-submit",
        "action": "lead submitted|test drive|tool"
      },
      {
        "pagename": "dc:value your trade:thank you",
        "channel": "search inventory",
        "hier": "shopping tools:value your trade",
        "pagenamenovehicle": "dc:value your trade:thank you",
        "slugs": "trade-in,trade-in-value,trade-in-appraisal,value-your-trade,trade-in-appraisal-no-vehicle,value-your-trade-no-vehicle",
        "tool": "event:value your trade",
        "tooldescriptor": "vehicle details:value your trade",
        "leadtype": "vdp:value your trade",
        "variantname": "vrmi-submit",
        "action": "lead submitted|vehicle quote|tool"
      },
      {
        "pagename": "dc:ev ownership:get updates:thank you",
        "channel": "ev ownership",
        "hier": "ev ownership",
        "pagenamenovehicle": "dc:ev ownership:get updates:thank you",
        "slugs": "ev-ownership-get-updates",
        "tool": "ev ownership:get updates",
        "tooldescriptor": "ev ownership:get updates",
        "leadtype": "ev ownership:get updates",
        "variantname": "form-submit",
        "action": "lead submitted|tool"
      }
    ],
    "vehicle": [
      {
        "pagename": "dc:{new|used|cpo}:si:vehicle details:test drive:thank you:<nameplate>",
        "channel": "test drive",
        "hier": "shopping tools:test drive:<vehicle category>:<nameplate>",
        "pagenamenovehicle": "dc:{new|used|cpo}:si:vehicle details:test drive:thank you",
        "slugs": "test-drive,book-a-test-drive",
        "tool": "event:lead submitted",
        "tooldescriptor": "vehicle details:test drive",
        "leadtype": "vdp:test drive",
        "variantname": "test-drive-submit",
        "action": "lead submitted|test drive|tool"
      },
      {
        "pagename": "dc:home:vrmi:thank you:<nameplate>",
        "channel": "home",
        "hier": "home:<model year>:<vehicle category>:<nameplate>",
        "pagenamenovehicle": "dc:home:vrmi:thank you",
        "slugs": "vrmi-home",
        "tool": "event:vrmi",
        "tooldescriptor": "home:vrmi",
        "leadtype": "home:vrmi",
        "variantname": "value-your-trade-submit",
        "action": "lead submitted|appraisals|tool"
      },
      {
        "pagename": "dc:{new|used|cpo}:si:vls:vrmi:thank you:<nameplate>",
        "channel": "get quote",
        "hier": "shopping tools:get quote:<vehicle category>:<nameplate>",
        "pagenamenovehicle": "dc:{new|used|cpo}:si:vls:vrmi:thank you",
        "slugs": "get-quote,quick-quote",
        "tool": "event:get quote",
        "tooldescriptor": "search inventory:get quote",
        "leadtype": "si:vrmi",
        "variantname": "value-your-trade-submit",
        "action": "lead submitted|appraisals|tool"
      },
      {
        "pagename": "dc:{new|used|cpo}:si:vehicle details:vrmi:thank you:<nameplate>",
        "channel": "get quote",
        "hier": "shopping tools:get quote:<vehicle category>:<nameplate>",
        "pagenamenovehicle": "dc:{new|used|cpo}:si:vehicle details:vrmi:thank you",
        "slugs": "request-information,request-more-information,get-quote,quick-quote",
        "tool": "event:get quote",
        "tooldescriptor": "vehicle details:get quote",
        "leadtype": "vdp:vrmi",
        "variantname": "vrmi-submit",
        "action": "lead submitted|appraisals|tool"
      },
      {
        "pagename": "dc:{new|used|cpo}:si:vehicle details:value your trade:thank you:<nameplate>",
        "channel": "search inventory",
        "hier": "shopping tools:value your trade:<vehicle category>:<nameplate>",
        "pagenamenovehicle": "dc:{new|used|cpo}:si:vehicle details:value your trade:thank you",
        "slugs": "trade-in-appraisal,value-your-trade",
        "tool": "event:value your trade",
        "tooldescriptor": "vehicle details:value your trade",
        "leadtype": "vdp:value your trade",
        "variantname": "vrmi-submit",
        "action": "lead submitted|vehicle quote|tool"
      }
    ],
    "vls": [
      {
        "pagename": "dc:{new|used|cpo}:si:vls:vrmi:thank you:<nameplate>",
        "channel": "get quote",
        "hier": "shopping tools:get quote:<vehicle category>:<nameplate>",
        "pagenamenovehicle": "dc:{new|used|cpo}:si:vls:vrmi:thank you",
        "slugs": "request-information,request-more-information",
        "tool": "event:get quote",
        "tooldescriptor": "search inventory:get quote",
        "leadtype": "si:vrmi",
        "variantname": "vrmi-submit",
        "action": "lead submitted|appraisals|tool"
      }
    ],
    "home-vrmi": [
      {
        "pagename": "dc:home:vrmi:thank you:<nameplate>",
        "channel": "home",
        "hier": "home:<model year>:<vehicle category>:<nameplate>",
        "pagenamenovehicle": "dc:home:vrmi:thank you",
        "slugs": "home,request-information,request-more-information,ask-a-question,ask-question",
        "tool": "event:vrmi",
        "tooldescriptor": "home:vrmi",
        "leadtype": "home:vrmi",
        "variantname": "vrmi-submit",
        "action": "lead submitted|appraisals|tool"
      }
    ],
    "pages": [
      {
        "pagename": "dc:ev lifestyle:test drive:thank you",
        "channel": "ev landing page",
        "hier": "shopping tools:ev lifestyle:test drive",
        "pagenamenovehicle": "dc:ev lifestyle:test drive:thank you",
        "slugs": "ev-lifestyle-test-drive-thank-you",
        "tool": "event:lead submitted",
        "tooldescriptor": "ev lifestyle:test drive",
        "leadtype": "ev ownership:test drive:thank you",
        "variantname": "test-drive-submit",
        "action": "lead submitted|test drive|tool"
      },
      {
        "pagename": "dc:ev ownership:contact us:thank you",
        "channel": "ev ownership",
        "hier": "ev ownership",
        "pagenamenovehicle": "dc:ev ownership:contact us:thank you",
        "slugs": "ev-ownership-contact-us-thank-you"
      },
      {
        "pagename": "dc:ev vhp:contact us:thank you",
        "channel": "ev vhp",
        "hier": "shopping tools:ev vhp:contact us",
        "pagenamenovehicle": "dc:ev vhp:contact us:thank you",
        "slugs": "ev-vhp-contact-us-thank-you"
      },
      {
        "pagename": "dc:ev ownership:contact us",
        "channel": "ev ownership",
        "hier": "ev ownership",
        "pagenamenovehicle": "dc:ev ownership:contact us",
        "slugs": "ev-ownership-contact-us,contact-us-ev-ownership"
      },
      {
        "pagename": "dc:home",
        "channel": "home",
        "hier": "home",
        "pagenamenovehicle": "dc:home",
        "slugs": "home,welcome"
      },
      {
        "pagename": "dc:help:privacy",
        "channel": "help",
        "hier": "help:privacy",
        "pagenamenovehicle": "dc:help:privacy",
        "slugs": "privacy"
      },
      {
        "pagename": "dc:help:disclosures",
        "channel": "help",
        "hier": "help:disclosures",
        "pagenamenovehicle": "dc:help:disclosures",
        "slugs": "disclosures,terms-conditions"
      },
      {
        "pagename": "dc:cpo overview",
        "channel": "cpo overview",
        "hier": "cpo overview",
        "pagenamenovehicle": "dc:cpo overview",
        "slugs": "cpo-overview"
      },
      {
        "pagename": "dc:ford co pilot assist",
        "channel": "ford co pilot assist",
        "hier": "ford co pilot assist",
        "pagenamenovehicle": "dc:ford co pilot assist",
        "slugs": "ford-co-pilot,co-pilot-assist,ford-co-pilot-assist"
      },
      {
        "pagename": "dc:value your trade",
        "channel": "search inventory",
        "hier": "shopping tools:value your trade",
        "pagenamenovehicle": "dc:value your trade",
        "slugs": "trade-in-value,value-your-trade,trade-in-vehicle-appraisal,trade-in-appraisal"
      },
      {
        "pagename": "dc:test drive",
        "channel": "test drive",
        "hier": "shopping tools:test drive",
        "pagenamenovehicle": "dc:test drive",
        "slugs": "test-drive"
      },
      {
        "pagename": "dc:service:request appointment",
        "channel": "service and parts",
        "hier": "service and parts:request appointment",
        "pagenamenovehicle": "dc:service:request appointment",
        "slugs": "book-an-appointment,book-appointment,request-appointment,service-appointment,schedule-appointment,schedule-service"
      },
      {
        "pagename": "dc:service:service and parts",
        "channel": "service and parts",
        "hier": "service and parts",
        "pagenamenovehicle": "dc:service:service and parts",
        "slugs": "service,service-parts,service-department,parts-department"
      },
      {
        "pagename": "dc:service:order parts",
        "channel": "service and parts",
        "hier": "service and parts:order parts",
        "pagenamenovehicle": "dc:service:order parts",
        "slugs": "parts,order-parts"
      },
      {
        "pagename": "dc:service:quick lane",
        "channel": "service and parts",
        "hier": "service and parts:quick lane",
        "pagenamenovehicle": "dc:service:quick lane",
        "slugs": "quick-lane,quicklane"
      },
      {
        "pagename": "dc:service:accessories",
        "channel": "service and parts",
        "hier": "service and parts:accessories",
        "pagenamenovehicle": "dc:service:accessories",
        "slugs": "accessories"
      },
      {
        "pagename": "dc:service:extended warranty",
        "channel": "service and parts",
        "hier": "service and parts:extended warranty",
        "pagenamenovehicle": "dc:service:extended warranty",
        "slugs": "extended-warranty"
      },
      {
        "pagename": "dc:service:owner advantage rewards",
        "channel": "service and parts",
        "hier": "service and parts:owner advantage rewards",
        "pagenamenovehicle": "dc:service:owner advantage rewards",
        "slugs": "owner-advantage-rewards,advantage-rewards,owner-advantage"
      },
      {
        "pagename": "dc:service:fordpass",
        "channel": "service and parts",
        "hier": "service and parts:fordpass",
        "pagenamenovehicle": "dc:service:fordpass",
        "slugs": "fordpass"
      },
      {
        "pagename": "dc:ev ownership:contact us",
        "channel": "ev ownership",
        "hier": "ev ownership",
        "pagenamenovehicle": "dc:ev ownership:contact us",
        "slugs": "ev-ownership-contact-us"
      },
      {
        "pagename": "dc:ev lifestyle:contact us",
        "channel": "ev landing page",
        "hier": "ev lifestyle",
        "pagenamenovehicle": "dc:ev lifestyle:contact us",
        "slugs": "ev-lifestyle-contact-us"
      },
      {
        "pagename": "dc:ev lifestyle:test drive",
        "channel": "ev landing page",
        "hier": "ev lifestyle",
        "pagenamenovehicle": "dc:ev lifestyle:test drive",
        "slugs": "ev-lifestyle-test-drive"
      },
      {
        "pagename": "dc:ev vhp:test drive:thank you:<mach-e>",
        "channel": "ev vhp",
        "hier": "shopping tools:ev vhp:test drive:<mach-e>",
        "pagenamenovehicle": "dc:ev vhp:test drive:thank you",
        "slugs": "book-a-test-drive-mustang-mach-e-thank-you"
      },
      {
        "pagename": "dc:ev vhp:test drive:thank you:<F150 lightning>",
        "channel": "ev vhp",
        "hier": "shopping tools:ev vhp:test drive:<F150 lightning>",
        "pagenamenovehicle": "dc:ev vhp:test drive:thank you",
        "slugs": "book-a-test-drive-f-150-lightning-thank-you"
      },
      {
        "pagename": "dc:ev vhp:test drive",
        "channel": "ev vhp",
        "hier": "shopping tools:ev vhp:test drive",
        "pagenamenovehicle": "dc:ev vhp:test drive",
        "slugs": "book-a-test-drive-mustang-mach-e,book-a-test-drive-f-150-lightning"
      },
      {
        "pagename": "dc:ev charging:contact us",
        "channel": "ev landing page",
        "hier": "ev charging",
        "pagenamenovehicle": "dc:ev charging:contact us",
        "slugs": "ev-charging-contact-us"
      },
      {
        "pagename": "dc:ev vhp:contact us",
        "channel": "ev vhp",
        "hier": "shopping tools:ev vhp:contact us",
        "pagenamenovehicle": "dc:ev vhp:contact us",
        "slugs": "ev-vhp-contact-us"
      },
      {
        "pagename": "dc:about us",
        "channel": "about us",
        "hier": "about us",
        "pagenamenovehicle": "dc:about us",
        "slugs": "about-us"
      },
      {
        "pagename": "dc:about us:contact us",
        "channel": "about us",
        "hier": "about us:contact us",
        "pagenamenovehicle": "dc:about us:contact us",
        "slugs": "contact,contact-us"
      },
      {
        "pagename": "dc:about us:meet our staff",
        "channel": "about us",
        "hier": "about us:meet our staff",
        "pagenamenovehicle": "dc:about us:meet our staff",
        "slugs": "staff,team,our-staff,our-team,meet-our-staff,meet-our-team"
      },
      {
        "pagename": "dc:about us:community",
        "channel": "about us",
        "hier": "about us:community",
        "pagenamenovehicle": "dc:about us:community",
        "slugs": "community"
      },
      {
        "pagename": "dc:about us:careers",
        "channel": "about us",
        "hier": "about us:careers",
        "pagenamenovehicle": "dc:about us:careers",
        "slugs": "careers"
      },
      {
        "pagename": "dc:shopping tools:credit application",
        "channel": "shopping tools",
        "hier": "shopping tools",
        "pagenamenovehicle": "dc:shopping tools:credit application",
        "slugs": "credit-application,apply-credit,financing"
      },
      {
        "pagename": "dc:ev ownership:get updates",
        "channel": "ev ownership",
        "hier": "ev ownership",
        "pagenamenovehicle": "dc:ev ownership:get updates",
        "slugs": "ev-ownership-get-updates"
      },
      {
        "pagename": "dc:ev ownership",
        "channel": "ev ownership",
        "hier": "ev ownership",
        "pagenamenovehicle": "dc:ev ownership",
        "slugs": "ev-ownership"
      },
      {
        "pagename": "dc:ev charging",
        "channel": "ev landing page",
        "hier": "ev charging",
        "pagenamenovehicle": "dc:ev charging",
        "slugs": "ev-charging"
      },
      {
        "pagename": "dc:ev lifestyle",
        "channel": "ev landing page",
        "hier": "ev lifestyle",
        "pagenamenovehicle": "dc:ev lifestyle",
        "slugs": "ev-lifestyle"
      },
      {
        "pagename": "dc:ev vhp:ev mach-e",
        "channel": "ev vhp",
        "hier": "ev vhp",
        "pagenamenovehicle": "dc:ev vhp",
        "slugs": "ev-mach-e"
      },
      {
        "pagename": "dc:ev vhp:ev-lightning",
        "channel": "ev vhp",
        "hier": "ev vhp",
        "pagenamenovehicle": "dc:ev vhp",
        "slugs": "ev-lightning"
      }
    ],
    "formsrequestvls": [
      {
        "pagename": "dc:{new|used|cpo}:si:vls:vrmi:<nameplate>",
        "channel": "get quote",
        "hier": "shopping tools:get quote:<vehicle category>:<nameplate>",
        "pagenamenovehicle": "dc:{new|used|cpo}:si:vls:vrmi",
        "slugs": "request-information,request-more-information,get-quote,quick-quote"
      }
    ],
    "formsrequestvdp": [
      {
        "pagename": "dc:{new|used|cpo}:si:vehicle details:vrmi:<nameplate>",
        "channel": "get quote",
        "hier": "shopping tools:get quote:<vehicle category>:<nameplate>",
        "pagenamenovehicle": "dc:{new|used|cpo}:si:vehicle details:vrmi",
        "slugs": "request-information,request-more-information,get-quote,quick-quote"
      },
      {
        "pagename": "dc:{new|used|cpo}:si:vehicle details:test drive:<nameplate>",
        "channel": "test drive",
        "hier": "shopping tools:test drive:<vehicle category>:<nameplate>",
        "pagenamenovehicle": "dc:{new|used|cpo}:si:vehicle details:test drive",
        "slugs": "test-drive,book-a-test-drive"
      },
      {
        "pagename": "dc:{new|used|cpo}:si:vehicle details:value your trade:<nameplate>",
        "channel": "search inventory",
        "hier": "shopping tools:value your trade:<vehicle category>:<nameplate>",
        "pagenamenovehicle": "dc:{new|used|cpo}:si:vehicle details:value your trade",
        "slugs": "trade-in-appraisal,value-your-trade"
      }
    ]
  }
]
JSON;

function lbx_get_adobe_data_array() {
  static $data = null;
  if ($data === null) {
    $data = json_decode(LBX_ADOBE_JSON, true);
    if (!is_array($data)) $data = [];
  }
  return $data;
}

if (!function_exists('adobe_contains_value')) {
  function adobe_contains_value($text, $words) {
    $array = explode("-", strtolower($words));
    $total_words = count($array);
    $vehicle = array_map('strtolower', explode('-', $text));
    $total_coincidences = 0;
    foreach ($array as $item) {
      $total_i = count(array_filter($vehicle, function ($var) use ($item) {
        return strpos($var, $item) !== false;
      }));
      $total_p = count(array_filter($vehicle, function ($var) use ($item) {
        return strpos(str_replace("-", "", $var), str_replace("-", " ", $item)) !== false;
      }));
      if ($total_i > 0 || $total_p)
        $total_coincidences++;
    }
    return $total_words == $total_coincidences;
  }
}

function get_adobe_data_from_slug($slug) {
  $adobeData = lbx_get_adobe_data_array();
  if (!empty($adobeData) && !empty($adobeData[0]['pages'])) {
    $slug_lower = strtolower(trim($slug));

    // Primero buscar coincidencia EXACTA
    foreach ($adobeData[0]['pages'] as $aData) {
      $slugs = array_map('trim', explode(',', $aData['slugs'] ?? ''));
      foreach ($slugs as $aSlug) {
        if ($aSlug !== '' && strtolower($aSlug) === $slug_lower) {
          return $aData;
        }
      }
    }

    // Si no hay coincidencia exacta, buscar coincidencia por palabras
    // (solo si tienen el mismo número de segmentos, para no matchear ej. ev-vhp-contact-us-thank-you con ev-vhp-contact-us)
    $slug_parts = count(explode('-', $slug_lower));
    foreach ($adobeData[0]['pages'] as $aData) {
      $slugs = array_map('trim', explode(',', $aData['slugs'] ?? ''));
      foreach ($slugs as $aSlug) {
        if ($aSlug !== '' && count(explode('-', strtolower($aSlug))) === $slug_parts && adobe_contains_value($slug, $aSlug)) {
          return $aData;
        }
      }
    }
  }
  return null;
}

function get_adobe_forms_data_from_slug($slug, $veh = 'nonvehicle') {
  $adobeData = lbx_get_adobe_data_array();
  if (empty($adobeData)) return null;

  // Selección del bloque
  $key = in_array($veh, ['home-vrmi','vls','nonvehicle','vehicle'], true) ? $veh : 'nonvehicle';
  $items = $adobeData[0][$key] ?? [];
  $slug_lower = strtolower(trim($slug));

  // Primero coincidencia exacta
  foreach ($items as $aData) {
    $slugs = array_map('trim', explode(',', $aData['slugs'] ?? ''));
    foreach ($slugs as $aSlug) {
      if ($aSlug !== '' && strtolower($aSlug) === $slug_lower) {
        return $aData;
      }
    }
  }

  // Luego coincidencia por palabras
  foreach ($items as $aData) {
    $slugs = array_map('trim', explode(',', $aData['slugs'] ?? ''));
    foreach ($slugs as $aSlug) {
      if ($aSlug !== '' && adobe_contains_value($slug, $aSlug)) {
        return $aData;
      }
    }
  }
  return null;
}

/* GET OEM PROGRAM */
function get_oem_program()
{
    $oem_program = "leadbox";
    $lbSettings = get_leadbox_settings();
    if (
        isset($lbSettings) && !empty($lbSettings) && isset($lbSettings["oem_program"])
        && !empty($lbSettings["oem_program"]) && (strlen($lbSettings["oem_program"]) > 0)
    ) {
        $oem_program = strtolower($lbSettings["oem_program"]);
    }

    return $oem_program;
}

/* GET JLR ENVIRONMENT */
function get_jlr_environment()
{
  $environment = "staging";
  $lbSettings = get_leadbox_settings();
  if (
    isset($lbSettings) && !empty($lbSettings) && isset($lbSettings["jlr_version"])
    && !empty($lbSettings["jlr_version"]) && (strlen($lbSettings["jlr_version"]) > 0)
  ) {
    $environment = strtolower($lbSettings["jlr_version"]);
  }

  return $environment;
}

/* GET JLR TAGGING */
function show_jlr_tagging()
{
  $show = false;
  $lbSettings = get_leadbox_settings();
  if (
    isset($lbSettings) && !empty($lbSettings) && isset($lbSettings["jlr_option"])
    && !empty($lbSettings["jlr_option"]) && (strtolower($lbSettings["jlr_option"]) == "enabled")
  ) {
    $show = true;
  }

  return $show;
}

function jlr_contains_value($text, $words)
{
  $array = explode("-", strtolower($words));
  $total_words = count($array);
  $vehicle = array_map('strtolower', explode('-', $text));
  $total_coincidences = 0;
  foreach ($array as $item) {
    $total_i = count(array_filter($vehicle, function ($var) use ($item) {
      return strpos($var, $item) !== false;
    }));
    $total_p = count(array_filter($vehicle, function ($var) use ($item) {
      return strpos(str_replace("-", "", $var), str_replace("-", " ", $item)) !== false;
    }));
    if ($total_i > 0 || $total_p)
      $total_coincidences++;
  }

  if ($total_words == $total_coincidences) {
    return true;
  } else {
    return false;
  }
}

const LBX_JLR_JSON = <<<JSON
[
  {
    "forms": [
      {
        "formtype": "Get a Quote",
        "coincidences": "get-a-quick-quote"
      },
      {
        "formtype": "Test Drive",
        "coincidences": "test-drive, book-a-test-drive"
      },
      {
        "formtype": "Request More Info",
        "coincidences": "request-more-information, request-more-info,confirm-availability,check-availability"
      },
      {
        "formtype": "email a Friend",
        "coincidences": "email-a-friend"
      },
      {
        "formtype": "General Contact",
        "coincidences": "contact, contact-us"
      },
      {
        "formtype": "Service",
        "coincidences": "service"
      },
      {
        "formtype": "Parts",
        "coincidences": "parts, request-parts"
      },
      {
        "formtype": "Schedule Service",
        "coincidences": "schedule-service, service-appointment,book-an-appointment"
      },
      {
        "formtype": "Employment",
        "coincidences": "employment, job-opportunities, employment-opportunities"
      },
      {
        "formtype": "Trade In",
        "coincidences": "trade-in, trade-in-appraisal, trade-in-value"
      },
      {
        "formtype": "Finance",
        "coincidences": "finance,financing"
      },
      {
        "formtype": "Payment Estimator",
        "coincidences": "payment-estimator, payment-calculator"
      },
      {
        "formtype": "Specials",
        "coincidences": "specials"
      },
      {
        "formtype": "Vehicle Finder",
        "coincidences": "vehicle-finder"
      },
      {
        "formtype": "Dealer Custom",
        "coincidences": "dealer-custom"
      },
      {
        "formtype": "Make an Offer",
        "coincidences": "make-an-offer"
      },
      {
        "formtype": "Send to Mobile",
        "coincidences": "send-to-mobile"
      },
      {
        "formtype": "Other",
        "coincidences": "other"
      }
    ]
  }
]
JSON;

const LBX_JLR_PAGE_TYPES_JSON = <<<JSON
[
  {
    "pages": [
      {
        "pagename": "Home",
        "coincidences": "Home, homepage"
      },
      {
        "pagename": "Model Showroom",
        "coincidences": "model-showroom, showroom"
      },
      {
        "pagename": "Brochure",
        "coincidences": "Brochure"
      },
      {
        "pagename": "Trade In",
        "coincidences": "trade-in-value,trade-in-appraisal"
      },
      {
        "pagename": "Vehicle Listing",
        "coincidences": "new-inventory, used-inventory"
      },
      {
        "pagename": "Vehicle Details",
        "coincidences": "view"
      },
      {
        "pagename": "Test Drive",
        "coincidences": "schedule-a-test-drive, test-drive"
      },
      {
        "pagename": "Dealer Specials",
        "coincidences": "new-vehicle-specials, used-vehicle-specials, specials"
      },
      {
        "pagename": "OEM Incentives",
        "coincidences": "oem-incentives"
      },
      {
        "pagename": "Special Offers",
        "coincidences": "gm-special-offers"
      },
      {
        "pagename": "Service Specials",
        "coincidences": "service-specials"
      },
      {
        "pagename": "CPOV Program",
        "coincidences": "cpov-program"
      },
      {
        "pagename": "Finance",
        "coincidences": "finance, financing"
      },
      {
        "pagename": "Finance Prequalification",
        "coincidences": "finance-prequalification"
      },
      {
        "pagename": "Service",
        "coincidences": "service"
      },
      {
        "pagename": "Schedule Service",
        "coincidences": "schedule-service,book-an-appointment"
      },
      {
        "pagename": "Tire Store",
        "coincidences": "tire-store,tire-centre"
      },
      {
        "pagename": "Parts",
        "coincidences": "order-parts, parts"
      },
      {
        "pagename": "Accessories",
        "coincidences": "accessories"
      },
      {
        "pagename": "About Us",
        "coincidences": "about-us"
      },
      {
        "pagename": "Hours & Directions",
        "coincidences": "hours-and-directions"
      },
      {
        "pagename": "Contact Us",
        "coincidences": "contact-us"
      },
      {
        "pagename": "Custom Dealer Content",
        "coincidences": "custom-dealer-content"
      },
      {
        "pagename": "Fleet",
        "coincidences": "fleet-commercial"
      },
      {
        "pagename": "Other",
        "coincidences": "other"
      },
      {
        "pagename": "Blog",
        "coincidences": "blog"
      },
      {
        "pagename": "Business Elite",
        "coincidences": "business-elite"
      },
      {
        "pagename": "Onstar",
        "coincidences": "onstar"
      },
      {
        "pagename": "Service Home",
        "coincidences": "service-home"
      },
      {
        "pagename": "Parts Home",
        "coincidences": "parts-home"
      },
      {
        "pagename": "Parts Order Form",
        "coincidences": "order-parts"
      },
      {
        "pagename": "Parts Specials",
        "coincidences": "parts-specials, special-parts"
      },
      {
        "pagename": "Service Specials",
        "coincidences": "service-specials, special-service"
      },
      {
        "pagename": "Accessories Home",
        "coincidences": "accessories-home"
      },
      {
        "pagename": "DriverGear",
        "coincidences": "drivergear"
      },
      {
        "pagename": "Service Event",
        "coincidences": "service-event"
      },
      {
        "pagename": "Maintenance Menu",
        "coincidences": "maintenance-menu"
      },
      {
        "pagename": "VW Care Maintenance",
        "coincidences": "vw-care-maintenance"
      },
      {
        "pagename": "Service Xpress",
        "coincidences": "service-xpress"
      },
      {
        "pagename": "Service Credit Card",
        "coincidences": "service-credit-card"
      },
      {
        "pagename": "Competitive Advantage",
        "coincidences": "competitive-advantage"
      }
    ]
  }
]
JSON;

function lbx_get_jlr_data_array() {
  static $data = null;
  if ($data === null) {
    $data = json_decode(LBX_JLR_JSON, true);
    if (!is_array($data)) $data = [];
  }
  return $data;
}

function lbx_get_jlr_page_types_data_array() {
  static $data = null;
  if ($data === null) {
    $data = json_decode(LBX_JLR_PAGE_TYPES_JSON, true);
    if (!is_array($data)) $data = [];
  }
  return $data;
}

function get_jlr_data_from_slug($slug, $checkForm = false)
{
  if ($checkForm) {
    $jlrData = lbx_get_jlr_data_array();

    if (isset($jlrData)) {
      foreach ($jlrData[0]["forms"] as $jData) {
        $coincidences = explode(",", $jData["coincidences"]);
        foreach ($coincidences as $coincidence) {
          if (jlr_contains_value(trim($slug), trim($coincidence))) {
            return $jData;
          }
        }
      }
    }
    return ["formtype" => "Other"];
  } else {
    $jlrData = lbx_get_jlr_page_types_data_array();

    if (isset($jlrData)) {
      foreach ($jlrData[0]["pages"] as $jData) {
        $coincidences = explode(",", $jData["coincidences"]);
        foreach ($coincidences as $coincidence) {
          if (jlr_contains_value(trim($slug), trim($coincidence))) {
            return $jData;
          }
        }
      }
    }

    return ["pagename" => "Other"];
  }
}

/* GET FORD ADOBE ENVIRONMENT */
function get_ford_adobe_environment()
{
  $environment = "staging";
  $lbSettings = get_leadbox_settings();
  if (
    isset($lbSettings) && !empty($lbSettings) && isset($lbSettings["ford_adobe_version"])
    && !empty($lbSettings["ford_adobe_version"]) && (strlen($lbSettings["ford_adobe_version"]) > 0)
  ) {
    $environment = strtolower($lbSettings["ford_adobe_version"]);
  }

  return $environment;
}

/* GET GENERAL ADOBE VALUES */
function get_general_adobe_values($post, $from, $vehicle_id)
{
  // Manifest requests are erroring due to lack of get_post()
  $post = $post ?? get_post();
  if (is_null($post)) {
    return [
      'pagename' => null,
      'channel' => null,
      'hier' => null,
      'pagenamenovehicle' => null,
    ];
  }

  $slug = $post->post_name;
  $title = $post->post_title;
  $home = is_front_page() || is_home();
  $adobe_value = [];
  if (isset($vehicle_id))
    $data = get_vehicle_by_id($vehicle_id);
  else
    $data = [];

  if ($home || strtolower($slug) == "home") {
    $adobe_value["pagename"] = htmlspecialchars("dc:home", ENT_QUOTES);
    $adobe_value["channel"] = "home";
    $adobe_value["hier"] = "home";
    $adobe_value["pagenamenovehicle"] = htmlspecialchars("dc:home", ENT_QUOTES);
  } else {
    if ((isset($from) && !empty($from)) || (isset($data) && !empty($data))) {
      $adobe_value = get_adobe_forms_data_from_slug($slug, (isset($from) && strlen($from) > 0) ? 'vls' : ((isset($data) && count($data) > 0) ? 'vehicle' : 'nonvehicle'));
      // Páginas thank-you y otras de formulario están en nonvehicle; si no hubo match, intentar nonvehicle
      if (!isset($adobe_value) || empty($adobe_value)) {
        $adobe_value = get_adobe_forms_data_from_slug($slug, 'nonvehicle');
      }
    } else {
      $adobe_value = get_adobe_forms_data_from_slug($slug, 'nonvehicle');
      if (!isset($adobe_value) || empty($adobe_value)) {
        $adobe_value = get_adobe_data_from_slug($slug);
      }
    }

    if (!has_block('leadbox/inventory-block', $post) && !isset($adobe_value)) {
      $adobe_value["pagename"] = htmlspecialchars("dc:custom:" . strtolower($title), ENT_QUOTES);
      $adobe_value["channel"] = "custom";
      $adobe_value["hier"] = "custom";
      $adobe_value["pagenamenovehicle"] = htmlspecialchars("dc:custom:" . strtolower($title), ENT_QUOTES);
    }
  }

  return $adobe_value;
}

function get_leadbox_manufacturer()
{
  $lbsettings = get_option('leadbox-settings');
  if (isset($lbsettings) && !empty($lbsettings) && isset($lbsettings["manufacturer"]) && !empty($lbsettings["manufacturer"])) {
    return strtolower(trim($lbsettings["manufacturer"]));
  } else {
    return "";
  }
}

function getYoutubeEmbedUrl($url)
{
  $rx = '~^(?:https?://)?(?:www[.])?(?:youtube[.]com/watch[?]v=|youtu[.]be/)([^&]{11})~x';

  if (preg_match($rx, $url, $matches)) {
    $youtube_id = $matches[count($matches) - 1];
  }
  return 'https://www.youtube.com/embed/' . $youtube_id;
}

function vdp_key($car_id, $date) {
  return "vdp:{$car_id}:{$date}";
}

function vdp_record_view_transient($car_id) {
  $car_id = (int) $car_id;
  if ($car_id <= 0) return;

  $today = current_time('Y-m-d');
  $key = vdp_key($car_id, $today);

  $count = get_transient($key);
  if ($count === false) { $count = 0; }
  $count++;
  // guarda por 8 días para poder sumar últimos 7 con margen
  set_transient($key, $count, DAY_IN_SECONDS * 8);

  wp_cache_delete("vdp7d:$car_id", 'vdp');
}

function vdp_get_7d_count_transient($car_id) {
  $car_id = (int) $car_id;
  if ($car_id <= 0) return 0;

  $cached = wp_cache_get("vdp7d:$car_id", 'vdp');
  if ($cached !== false) {
    return (int)$cached;
  }

  $sum = 0;
  for ($i = 0; $i < 7; $i++) {
    $date = date('Y-m-d', strtotime(current_time('Y-m-d') . " -$i days"));
    $sum += (int) (get_transient(vdp_key($car_id, $date)) ?: 0);
  }

  wp_cache_set("vdp7d:$car_id", $sum, 'vdp', MINUTE_IN_SECONDS * 10);
  return $sum;
}

function setVdpCountCar($id) {
  vdp_record_view_transient($id);
}

function getVdpCountCar($id) {
  return vdp_get_7d_count_transient($id);
}


function isKinstaUrl()
{
  $actual_link = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on' ? "https" : "http") . "://$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]";
  if (strpos($actual_link, 'kinsta') !== false && strpos($actual_link, 'cloud') !== false) {
    //var_dump($actual_link);
    if (strpos($actual_link, 'leadboxegyptqa') !== false) {
      return false;
    } else
      return true;
  }
}

function get_upgrade_name($name)
{
  switch ($name) {
    case 'G-1':
      return 'One Owner';
      break;

    case 'G-2':
      return 'Clean Carproof';
      break;

    case 'G-3':
      return 'In Demand Color';
      break;

    case 'G-4':
      return 'Low Kms';
      break;

    case 'G-5':
      return 'New Brakes';
      break;

    case 'G-6':
      return 'New Tires';
      break;

    case 'G-7':
      return 'Oil Change';
      break;

    case 'G-8':
      return 'New Wiper Blades';
      break;

    case 'G-9':
      return 'New Air Filter';
      break;

    case 'G-10':
      return 'Mpi Certified';
      break;

    case 'G-11':
      return 'Vehicle Detailed';
      break;

    case 'G-12':
      return 'New Arrival';
      break;

    default:
      return '';
      break;
  }
}

function get_compare_add_url($lang = 'en')
{
  $view = 'recherche';
  if (strpos($lang, 'en') !== false) {
    $view = 'search';
  }
  //$vehicle = get_vehicle_by_id($id);
  return "/" . $view;
}

function get_local_line_up()
{
  $route = '/resources/config/line-up.json';
  $jsonPath = get_fileInGenius($route);
  if (file_exists($jsonPath . $route)) {
    return json_decode(file_get_contents($jsonPath . $route), true);
  } else {
    return null;
  }
}

function get_local_used_line_up()
{
  $route = '/resources/config/used-line-up.json';
  $jsonPath = get_fileInGenius($route);
  if (file_exists($jsonPath . $route)) {
    return json_decode(file_get_contents($jsonPath . $route), true);
  } else {
    return null;
  }
}

function enqueueIsolatedScript($name, $lib = null){
  $theme_version = 0;

  // Check if theme activated is child or parent
  if (get_stylesheet() !== get_template())
    $theme_version = wp_get_theme()->parent()->get('Version');
  else
    $theme_version = wp_get_theme()->get('Version');

  $wp_scripts = wp_scripts();

  if(! in_array("genius/isolated/{$name}", $wp_scripts->queue)) {
    // Removed complicated lookup
    $file = get_theme_file_uri("/public/scripts/isolated/{$name}.js");
    wp_register_script("genius/isolated/{$name}", $file, [], $theme_version);
    wp_enqueue_script("genius/isolated/{$name}", $lib, ['sage/vendor.js', 'sage/app.js'], null, true);
  }
}

function mileage_format($n)
{
  return (number_format(floatval($n), 0));
}

function createCarfaxBadge($vin, $accountNumber, $WebServiceToken)
{
  $badge = "";

  if (!$WebServiceToken)
    $WebServiceToken = 'BE/s9XcA33ZXLiTl/ak3oXSu+pvkuewrU18T6xZChc9v/JYbMyYfAB3a0algBvj+q80PGUAjsl9UAwHD4BJxuYmsLaxaP3UlQyOjiDfSmDA7Jq8OphhSoDSmxycFIK7RV5tl1HTie6tGM9R6HLQgbxTTz03chsVY4LpWM7reM1FsSA1y/pbMsVVDTj7wx/ZBuYGh+0TLhdbEZD+N+g7TQVUkU2kxONCZ5T2Gi+0u7wwP7m/h/mgQHIzDYYQAe8F4rydJficMnedRH+jRr+eTEsr1V1a9K6/an2MyZGAkyVkXNO4mU0EVNTYaSoqLeXdUvYXsslQ/2/wOs+XlEp+X4GD2xLfKKELpc2KK8YuGvWLqRUr8aVS8moQ/ff4tk0MFR9ookE3sJF15roh8hgkXBw==';

  $ch = curl_init();
  $lang = "EN";

  if (get_locale() == "fr_CA")
    $lang = "FR";

  $url = "https://badgingapi.carfax.ca/api/v2/badges/" . $vin . "?accountNumber=" . $accountNumber . "&language=" . $lang . "";

  curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
  curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
  curl_setopt($ch, CURLOPT_URL, $url);
  curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

  curl_setopt(
    $ch,
    CURLOPT_HTTPHEADER,
    array(
      'Accept: application/json',
      'WebServiceToken: ' . $WebServiceToken . ' '
    )
  );

  $resp = curl_exec($ch);

  if ($e = curl_error($ch)) {
    $e;
  } else {
    $decoded = json_decode($resp);

    if($decoded){
      if ($decoded->ResultCode == 1) {
        $badge = "<a href='" . $decoded->BadgesList[0]->VhrReportUrl . "' target='_blank'>
                                      <img class='pt-1 pb-1 m-auto' src='" . $decoded->BadgesList[0]->BadgesImageUrl . "'>
                              </a>";

        curl_close($ch);
        return $badge;
      }
    }
  }
}

function getGraphqlAuthToken()
{
  $endpoint = getGraphqlEndPoint();
  $request_body = wp_json_encode([
    'query' => '
          mutation LoginUser {
            login(
              input: {clientMutationId: "uniqueId", username: "content-reader", password: "6det@avt1$J3^NfdBL4FcgGL"}
            ) {
              authToken
            }
          }
        '
  ]);

  $response = wp_remote_request($endpoint, [
    'method' => 'POST',
    'timeout' => 50,
    'headers' => [
      'Content-Type' => 'application/json'
    ],
    'body' => $request_body
  ]);


  if (is_wp_error($response)) {
    throw new \Exception($response->get_error_message());
  }

  $decoded_response = json_decode($response['body'], true);
  $auth_token = $decoded_response['data']['login']['authToken'];

  return $auth_token;
}

function getGraphqlEndPoint() {
  $lbSettings = get_leadbox_settings();
  if (!isset($lbSettings['graphql_url']) || empty($lbSettings['graphql_url'])) {
    return 'https://minerva.stellate.sh/graphql';
  }else{
    return $lbSettings['graphql_url'];
  }
}

function get_adobe_vehicle_type($type)
{
  if (isset($type)) {
    if (isFrench()) {
      switch (strtolower($type)) {
        case 'voiture':
          return "car";
          break;
        case 'vus':
          return "suv";
          break;
        case 'camion':
          return "truck";
          break;
        case 'monospace':
          return "van";
          break;
        case 'utilitaire':
          return "commercial";
          break;
        default:
          return "car";
          break;
      }
    } else {
      if (strtolower(str_replace(' ', '', trim($type))) == "other") {
        return "car";
      } else {
        return strtolower(str_replace(' ', '', trim($type)));
      }

    }
  }

  //if there is not vehicle type set by default return car
  return "car";
}

function get_tax_from_province()
{
  $taxes = array(
    "AB" => 5,
    "BC" => 12,
    "MB" => 12,
    "NB" => 15,
    "NL" => 15,
    "NT" => 5,
    "NS" => 15,
    "NU" => 5,
    "ON" => 13,
    "PE" => 15,
    "QC" => 15,
    "SK" => 11,
    "YT" => 5
  );

  $contact = get_dealer_contact();

  if (isset($contact) && !empty($contact) && isset($contact["address_province"]) && !empty($contact["address_province"])) {
    if (isset($taxes[$contact["address_province"]]))
      return $taxes[$contact["address_province"]];
    else
      return 13;
  } else
    return 13;
}

function get_tax_label_province()
{
  $label = array(
    "AB" => 'GST',
    "BC" => 'GST + PST',
    "MB" => 'GST + PST',
    "NB" => 'HST',
    "NL" => 'HST',
    "NT" => 'GST',
    "NS" => 'HST',
    "NU" => 'GST',
    "ON" => 'HST',
    "PE" => 'HST',
    "QC" => 'GST + QST',
    "SK" => 'GST + PST',
    "YT" => 'GST'
  );

  $label_fr = array(
    "AB" => 'TPS',
    "BC" => 'TPS + TVP',
    "MB" => 'TPS + TVP',
    "NB" => 'TVH',
    "NL" => 'TVH',
    "NT" => 'TPS',
    "NS" => 'TVH',
    "NU" => 'TPS',
    "ON" => 'TVH',
    "PE" => 'TVH',
    "QC" => 'TPS + TVQ',
    "SK" => 'TPS + TVP',
    "YT" => 'TPS'
  );

  $contact = get_dealer_contact();

  if (isset($contact) && !empty($contact) && isset($contact["address_province"]) && !empty($contact["address_province"])) {
    $lang = get_locale();
    if ($lang == 'fr_CA'){
      if (isset($label_fr[$contact["address_province"]]))
        return $label_fr[$contact["address_province"]];
      else
        return 'TVH';
    }
    else{
      if (isset($label[$contact["address_province"]]))
        return $label[$contact["address_province"]];
      else
        return 'HST';
    }

  } else
    return 'HST';
}

function find_url($url = NULL)
{
  if (empty($url)) {
    return false;
  }
  $response = wp_remote_head($url, array('timeout' => 5));

  $accepted_response = array(200, 301, 302);
  if (!is_wp_error($response) && in_array(wp_remote_retrieve_response_code($response), $accepted_response)) {
    return true;
  } else {
    return false;
  }
}

/**
 * This function adds "async" and "defer" parameters to JavaScript resources.
 * Just add "async" or "defer" anywhere in the resource name
 * ("handle" attribute of the wp_register_script function).
 *
 * @param $tag
 * @param $handle
 *
 * @return mixed
 */
function add_async_defer_attributes_to_scripts($tag, $handle)
{
  // Search for the "async" value
  if (strpos($handle, "async")):
    $tag = str_replace(' src', ' async="async" src', $tag);
  endif;
  // Search for the "defer" value
  if (strpos($handle, "defer")):
    $tag = str_replace(' src', ' defer="defer" src', $tag);
  endif;
  return $tag;
}
add_filter('script_loader_tag', 'add_async_defer_attributes_to_scripts', 10, 2);


/**
 * Returns the finance amount based on dealer frequency.
 * @var int $price
 * @var float $rate
 * @var int $term
 *
 * @return int $financeTotal
 */

function getFinanceTotal($price = int, $rate = float, $term = int)
{
  if ($price != 0 && $rate != 0 && $term != 0) {
    $financeTotal = round(($price * ($rate / 1200) * pow(1 + ($rate / 1200), $term)) / (pow(1 + ($rate / 1200), $term) - 1) * 100) / 100;
    $financeTotal = round($financeTotal, 2);

    switch (get_leadbox_finance_settings()['finance_frequency']) {
      case 'Weekly':
        $financeTotal = round(($financeTotal * 12) / 52);
        break;
      case 'Bi-Weekly':
        $financeTotal = round(((($financeTotal * 12) / 52) * 2));
        break;
      case 'Monthly':
        $financeTotal = round($financeTotal);
        break;
    }
    return $financeTotal;
  }
  return null;
}

/**
 * Returns the lease amount based on dealer frequency.
 * @var int $price
 * @var int $term
 * @var float $rate
 * @var int $adjustment
 * @var int $residual
 *
 * @return int $leaseTotal
 */
function getLeaseTotal($price = int, $term = int, $rate = float, $residual = int)
{
  $moneyFactor = ($rate / 2400);
  $newResidual = $price * ($residual / 100);
  $depretiation = 0;
  if ($term > 0)
    $depretiation = ($price - ($price * ($residual / 100))) / $term;
  $financeFee = ($price + $newResidual) * $moneyFactor;
  $monthlyLease = $financeFee + $depretiation;

  switch (get_leadbox_finance_settings()['lease_frequency']) {
    case 'Weekly':
      $leaseTotal = round(($monthlyLease * 12) / 52);
      break;
    case 'Bi-Weekly':
      $leaseTotal = round((($monthlyLease * 12) / 26));
      break;
    case 'Monthly':
      $leaseTotal = round($monthlyLease);
      break;
  }
  return $leaseTotal;
}

/**
 * Returns the structure that a custom sitemap must have in order to be readable by Yoast.
 *
 * @param string $url
 *
 * @return string $output
 */

function create_custom_sitemap_url($url)
{
  $url = htmlspecialchars($url);

  $output = "\t<url>\n";
  $output .= "\t\t<loc>" . $url . "</loc>\n";
  $output .= '';
  $output .= "\t\t<lastmod>" . date('c', time()) . "</lastmod>\n";
  $output .= "\t</url>\n";

  return $output;
}

function cmp($a, $b)
{
  $keyA = ($a['model'] ?? '') . ($a['year'] ?? '');
  $keyB = ($b['model'] ?? '') . ($b['year'] ?? '');

  if ($keyA == $keyB) {
    return 0;
  }
  return ($keyA < $keyB) ? -1 : 1;
}

/**
 * Returns the first segment of URL.
 *
 *
 * @return string $output
*/

function check_url_first_segment() {
  $current_url = $_SERVER['REQUEST_URI'];
  $url_segments = explode('/', trim($current_url, '/'));
  if (isset($url_segments[0])) {
      return strtolower($url_segments[0]);
  } else {
      return "";
  }
}

function get_local_dealer_stores()
{
  $route = '/resources/config/dealer-stores.json';
  $jsonPath = get_fileInGenius($route);
  if (file_exists($jsonPath . $route)) {
    return json_decode(file_get_contents($jsonPath . $route), true);
  } else {
    return null;
  }
}

function get_dealer_stores($store) {
  $dealerStores = get_local_dealer_stores();
  if(isset($dealerStores) && !empty($dealerStores) && isset($dealerStores['stores']) && !empty($dealerStores['stores'])) {
    $dealerStores = $dealerStores['stores'];
    foreach ($dealerStores as $dealerStore) {
      if ($dealerStore['lblocation'] == $store) {
        return $dealerStore;
      }
    }
    return null;
  }
  else {
    return null;
  }

}

/**
 * Owning-site geo payload for the vehicle-card distance badge.
 *
 * Every vehicle on this site sits at the dealer (e.g. Derrick Dodge), so the
 * badge shows the dealer city plus how far the BUYER is from it. This exposes
 * the dealer's coordinates + city from Dealer Settings → Contact
 * (`dealer-settings-contact-options`); the buyer side (geolocation + haversine)
 * is computed client-side in spa-vehicle-card.vue.
 *
 * Returns null when the vehicle-card `show-location-distance` option is off, or
 * when there is neither coordinates nor a city to show — keeping the badge fully
 * opt-in. Consumed through the window.LBX_DEALER_LOCATION global injected in
 * head.blade.php.
 *
 * @return array{lat: ?float, lng: ?float, city: string, name: string, locations: ?array<string, array{city: string, lat: ?float, lng: ?float}>}|null
 */
function get_dealer_geo_payload() {
  $enabled = defined('GENIUS') && (
    (GENIUS['vehicle-card']['data']['show-location-distance'] ?? false)
    || (GENIUS['vdp-title']['data']['show-location-distance'] ?? false)
  );
  if (!$enabled) {
    return null;
  }

  $contact = get_dealer_contact();
  if (empty($contact)) {
    return null;
  }

  $latRaw = isset($contact['latitude']) ? lbx_normalize_coordinate($contact['latitude']) : '';
  $lngRaw = isset($contact['longitude']) ? lbx_normalize_coordinate($contact['longitude']) : '';
  $city   = isset($contact['address_city']) ? trim($contact['address_city']) : '';
  $name   = isset($contact['dealer_name']) ? trim($contact['dealer_name']) : '';

  // Per-store overrides for multi-location inventories: GENIUS['locations'] maps
  // a vehicle's `location` (store name from the feed) to its own city and,
  // optionally, coordinates. Entries can be "Store" => "City" or
  // "Store" => { city, lat, lng }. Vehicles whose location is not in the map
  // keep the owning-site city/coords above.
  $locations = [];
  $rawLocations = GENIUS['locations'] ?? [];
  if (is_array($rawLocations)) {
    foreach ($rawLocations as $store => $entry) {
      if (is_string($entry)) {
        $entry = ['city' => $entry];
      }
      if (!is_array($entry)) {
        continue;
      }
      $entryCity = isset($entry['city']) ? trim((string) $entry['city']) : '';
      $entryLat  = isset($entry['lat']) ? lbx_normalize_coordinate($entry['lat']) : '';
      $entryLng  = isset($entry['lng']) ? lbx_normalize_coordinate($entry['lng']) : '';
      if ($entryCity === '' && $entryLat === '' && $entryLng === '') {
        continue;
      }
      $locations[$store] = [
        'city' => $entryCity,
        'lat'  => $entryLat !== '' ? (float) $entryLat : null,
        'lng'  => $entryLng !== '' ? (float) $entryLng : null,
      ];
    }
  }

  // No coordinates, no city and no per-store map => nothing worth showing.
  if ($latRaw === '' && $lngRaw === '' && $city === '' && empty($locations)) {
    return null;
  }

  return [
    'lat'  => $latRaw !== '' ? (float) $latRaw : null,
    'lng'  => $lngRaw !== '' ? (float) $lngRaw : null,
    'city' => $city,
    'name' => $name,
    'locations' => !empty($locations) ? $locations : null,
    // Which surfaces show the badge — so each only prompts for geolocation when
    // its own badge is on (e.g. SRP off + VDP on => no prompt on the listing).
    'srp'  => (bool) (GENIUS['vehicle-card']['data']['show-location-distance'] ?? false),
    'vdp'  => (bool) (GENIUS['vdp-title']['data']['show-location-distance'] ?? false),
    // City-only mode: `show-location-distance` set to "city" shows the store
    // city but never prompts for geolocation nor renders a distance.
    'srpCityOnly' => strtolower((string) (GENIUS['vehicle-card']['data']['show-location-distance'] ?? '')) === 'city',
    'vdpCityOnly' => strtolower((string) (GENIUS['vdp-title']['data']['show-location-distance'] ?? '')) === 'city',
  ];
}


function is_store_open($hours) {
  try {
    $timezone = wp_timezone();
  } catch (Exception $e) {
    $timezone = new DateTimeZone('Canada/Eastern');
  }

  $now = new DateTime('now', $timezone);

  if (empty($hours) || !str_contains($hours, '-') || stripos($hours, 'closed') !== false) {
    return "Closed";
  }

  $split_hours = explode("-", $hours);

  $hours_start = DateTime::createFromFormat('g:i A', trim($split_hours[0]), $timezone);
  $hours_end = DateTime::createFromFormat('g:i A', trim($split_hours[1]), $timezone);

  if ($hours_start && $hours_end) {
    if ($hours_end < $hours_start) {
      $hours_end->modify('+1 day');
    }

    if ($now >= $hours_start && $now <= $hours_end) {
      return "Open";
    }
  }

  return "Closed";
}

function findStatusInInventory($status)
{
  $inventory = get_search_inventory();
  $count = 0;

  $vehicles = array_filter($inventory, function ($vehicle) use ($status, &$count) {
    if ($status == 'certified' && $vehicle['certified']) {
      $count++;
      return true;
    } else if ($status == 'salepending' && $vehicle['salepending']) {
      $count++;
      return true;
    } else if ($status == 'special' && $vehicle['special']) {
      $count++;
      return true;
    } else if ($status == 'new' && $vehicle['condition'] == 'New') {
      $count++;
      return true;
    } else if ($status == 'used' && $vehicle['condition'] == 'Used') {
      $count++;
      return true;
    }
    return false;
  });

  return $count;
}

function textSalePhone() {
  if (!isFrench()) {
    return 'Sales';
  } else {
    return 'Ventes';
  }
}
function textServicePhone() {
  if (!isFrench()) {
    return 'Service';
  } else {
    return 'Service';
  }
}
function textPartsPhone() {
  if (!isFrench()) {
    return 'Parts';
  } else {
    return 'Pièces';
  }
}

function is_current_time_in_range($timeRange, $currentTime) {
  $isFrench = function_exists('isFrench') && isFrench();

  // Considerar "Closed" o "Fermé" como cerrado
  if ($timeRange === 'Closed' || ($isFrench && $timeRange === 'Fermé')) {
      return false;
  }

  // Separar la hora de inicio y fin del rango, soportando diferentes tipos de guion
  $timeParts = preg_split('/\s*[-–—]\s*/', $timeRange);
  if (count($timeParts) < 2) return false; // Si no hay un rango válido, retorna falso

  [$start, $end] = $timeParts;

  // Convertir ambas a timestamps comparables
  $startTime = strtotime($start);
  $endTime = strtotime($end);
  $now = strtotime($currentTime);

  return ($now >= $startTime && $now <= $endTime);
}


// Función para agrupar días consecutivos con soporte para francés
function group_consecutive_days($days) {
  $grouped = [];
  $temp = [];

  // Determinar si es francés
  $isFrench = function_exists('isFrench') && isFrench();

  // Usar el orden correcto según el idioma
  $dayOrder = $isFrench
      ? ["Lundi", "Mardi", "Mercredi", "Jeudi", "Vendredi", "Samedi", "Dimanche"]
      : ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"];

  foreach ($dayOrder as $day) {
      if (in_array($day, $days)) {
          $temp[] = $day;
      } else {
          if (!empty($temp)) {
              $grouped[] = $temp;
              $temp = [];
          }
      }
  }

  if (!empty($temp)) {
      $grouped[] = $temp;
  }

  return $grouped;
}

// Función para agrupar horarios con soporte para francés
function group_hours($hours) {
    $groupedHours = [];

    // Definir los días en inglés y su equivalente en francés
    $dayOrder = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"];
    $dayOrderFr = ["Lundi", "Mardi", "Mercredi", "Jeudi", "Vendredi", "Samedi", "Dimanche"];

    // Determinar si se debe traducir
    $isFrench = function_exists('isFrench') && isFrench();
    $dayMap = array_combine($dayOrder, $isFrench ? $dayOrderFr : $dayOrder);

    foreach ($hours as $day => $time) {
        $translatedDay = $dayMap[$day] ?? $day; // Traducir días si es necesario
        $translatedTime = ($isFrench && $time === "Closed") ? "Fermé" : $time; // Traducir "Closed" a "Fermé"
        $groupedHours[$translatedTime][] = $translatedDay;
    }

    // Ordenar los días dentro de cada grupo
    foreach ($groupedHours as $time => &$days) {
        $daysOrder = $isFrench ? $dayOrderFr : $dayOrder;

        usort($days, function($a, $b) use ($daysOrder) {
            return array_search($a, $daysOrder) <=> array_search($b, $daysOrder);
        });
    }
    unset($days);

    return $groupedHours;
}


function get_meta_yoast_inventory() {
  // Ruta al archivo inventory.json
  $inventory_file = wp_get_upload_dir()['basedir'] . '/data/inventory.json';

  // Verificar si el archivo existe
  if (!file_exists($inventory_file)) {
      return []; // Retornar un array vacío si el archivo no existe
  }

  // Leer y decodificar el archivo JSON
  $inventory = json_decode(file_get_contents($inventory_file), true);
  if (json_last_error() !== JSON_ERROR_NONE || !isset($inventory['vehicles'])) {
      return [];
  }

  $urls = []; // Array para almacenar las URLs
  $current_language = get_locale();

  //* Recorrer los vehículos en el inventario
  foreach ($inventory['vehicles'] as $item) {
      // Obtener la URL en el idioma actual

      $slug = get_vdp_slug($item, $current_language);
      $useVin = GENIUS['vehicle-card']['data']['use-slug-vin'] ?? false;
      if ($useVin) {
        $slug = str_replace('-' . $item['id'], '-' . $item['vin'] . '-' . $item['id'], $slug);
      }
      $full_url = get_site_url() . $slug;
      array_push($urls, $full_url);

      //* Si Polylang está activo y el idioma actual no es francés, agregar la URL en francés
      if (function_exists('pll_default_language') && $current_language !== 'fr_FR') {
          $slug_fr = get_vdp_slug($item, 'fr');
          $full_url_fr = get_site_url() . $slug_fr;
          array_push($urls, $full_url_fr);
      }
  }

  return $urls; // Retornar el array de URLs
}

function generate_sitemap_xml() {
  // Obtener las URLs del inventario
  $urls = get_meta_yoast_inventory();

  // Crear el elemento raíz del XML
  $xml = new SimpleXMLElement('<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"/>');

  // Iterar sobre las URLs y añadirlas al XML
  foreach ($urls as $url) {
      $url_node = $xml->addChild('url');
      $url_node->addChild('loc', $url);
      $url_node->addChild('lastmod', date('Y-m-d')); // Fecha actual
      $url_node->addChild('changefreq', 'weekly');   // Frecuencia de cambio
      $url_node->addChild('priority', '0.7');       // Prioridad
  }

  // Devolver el XML como una cadena
  header('Content-Type: text/xml');
  echo $xml->asXML();
  exit;
}


function my_sitemap_rewrite_custom() {
  add_rewrite_rule('^inventory\.xml$', 'index.php?custom_xml_sitemap=true', 'top');
}
function custom_xml_sitemap_query_var($vars) {
  $vars[] = 'custom_xml_sitemap';
  return $vars;
}

function custom_xml_sitemap_request($wp) {
  if (isset($wp->query_vars['custom_xml_sitemap']) && $wp->query_vars['custom_xml_sitemap'] === 'true') {
      generate_sitemap_xml();
  }
}

function removeAccents($string)
{
  $table = array(
    'Š' => 'S',
    'š' => 's',
    'Đ' => 'Dj',
    'đ' => 'dj',
    'Ž' => 'Z',
    'ž' => 'z',
    'Č' => 'C',
    'č' => 'c',
    'Ć' => 'C',
    'ć' => 'c',
    'À' => 'A',
    'Á' => 'A',
    'Â' => 'A',
    'Ã' => 'A',
    'Ä' => 'A',
    'Å' => 'A',
    'Æ' => 'A',
    'Ç' => 'C',
    'È' => 'E',
    'É' => 'E',
    'Ê' => 'E',
    'Ë' => 'E',
    'Ì' => 'I',
    'Í' => 'I',
    'Î' => 'I',
    'Ï' => 'I',
    'Ñ' => 'N',
    'Ò' => 'O',
    'Ó' => 'O',
    'Ô' => 'O',
    'Õ' => 'O',
    'Ö' => 'O',
    'Ø' => 'O',
    'Ù' => 'U',
    'Ú' => 'U',
    'Û' => 'U',
    'Ü' => 'U',
    'Ý' => 'Y',
    'Þ' => 'B',
    'ß' => 'Ss',
    'à' => 'a',
    'á' => 'a',
    'â' => 'a',
    'ã' => 'a',
    'ä' => 'a',
    'å' => 'a',
    'æ' => 'a',
    'ç' => 'c',
    'è' => 'e',
    'é' => 'e',
    'ê' => 'e',
    'ë' => 'e',
    'ì' => 'i',
    'í' => 'i',
    'î' => 'i',
    'ï' => 'i',
    'ð' => 'o',
    'ñ' => 'n',
    'ò' => 'o',
    'ó' => 'o',
    'ô' => 'o',
    'õ' => 'o',
    'ö' => 'o',
    'ø' => 'o',
    'ù' => 'u',
    'ú' => 'u',
    'û' => 'u',
    'ý' => 'y',
    'ý' => 'y',
    'þ' => 'b',
    'ÿ' => 'y',
    'Ŕ' => 'R',
    'ŕ' => 'r',
  );

  return strtr($string, $table);
}

function get_lineup_totals_for_navigation($lineup, $condition)
{
    $inventory = get_search_inventory();
    $conditionLower = strtolower($condition);

    // Reglas especiales: nombre del lineup => función de matching
    $specialRules = [
        'f-150' => fn($v, $field) => preg_match("/f-150(?! lightning)/i", $v[$field] ?? ''),
        'bronco' => fn($v, $field) => ($v[$field] ?? '') === 'bronco',
        'f-150 lightning' => fn($v, $field) => ($v[$field] ?? '') === 'f-150 lightning',
        'transit' => fn($v, $field) => ($v[$field] ?? '') === 'transit',
        'transit electric' => fn($v, $field) => ($v[$field] ?? '') === 'e-transit',
        'shelby f-150' => fn($v, $field) => ($v['model'] ?? '') === 'f-150' && stripos($v['tags'] ?? '', 'shelby') !== false,
        'roush mustang' => fn($v, $field) => ($v['model'] ?? '') === 'mustang' && stripos($v['tags'] ?? '', 'roush') !== false,
        'roush f-150' => fn($v, $field) => ($v['model'] ?? '') === 'f-150' && stripos($v['tags'] ?? '', 'roush') !== false,
        'roush f-250' => fn($v, $field) => stripos($v['model'] ?? '', 'f-250') !== false && stripos($v['tags'] ?? '', 'roush') !== false,
        'bronco raptor' => fn($v, $field) => stripos($v['model'] ?? '', 'bronco') !== false && stripos($v['trim'] ?? '', 'raptor') !== false,
        'ranger raptor' => fn($v, $field) => stripos($v['model'] ?? '', 'ranger') !== false && stripos($v['trim'] ?? '', 'raptor') !== false,
        'f-150 raptor' => fn($v, $field) => stripos($v['model'] ?? '', 'f-150') !== false && stripos($v['trim'] ?? '', 'raptor') !== false,
    ];

    // Casos especiales que ignoran la condición
    $specialNoCondition = ['roush mustang', 'shelby f-150', 'roush f-150', 'roush f-250', 'bronco raptor', 'ranger raptor', 'f-150 raptor'];

    // Pre-normalizar vehículos una sola vez
    $normalizedInventory = [];
    foreach ($inventory as $vehicle) {
        if (!isset($vehicle['condition'])) continue;

        $normalizedInventory[] = [
            'original' => $vehicle,
            'condition' => strtolower($vehicle['condition']),
            'model' => strtolower($vehicle['model'] ?? ''),
            'trim' => strtolower($vehicle['trim'] ?? ''),
            'tags' => strtolower($vehicle['tags'] ?? ''),
        ];
    }

    foreach ($lineup as &$item) {
        $total = 0;
        $nameLower = strtolower($item['name'] ?? '');
        $field = $item['field'] ?? '';
        $regex = $item['regex'] ?? '';
        $specialRule = $specialRules[$nameLower] ?? null;
        $isSpecialNoCondition = in_array($nameLower, $specialNoCondition);

        foreach ($normalizedInventory as $nv) {
            $vehicle = $nv['original'];
            $matchesCondition = $nv['condition'] === $conditionLower;

            if (!$matchesCondition && !$isSpecialNoCondition) continue;

            if ($specialRule) {
                $vehicleLower = [
                    'model' => $nv['model'],
                    'trim' => $nv['trim'],
                    'tags' => $nv['tags'],
                    $field => strtolower($vehicle[$field] ?? ''),
                ];
                if ($specialRule($vehicleLower, $field)) {
                    $total++;
                }
            } elseif ($matchesCondition && $regex) {
                $fieldValue = strtolower($vehicle[$field] ?? '');
                if (preg_match($regex, $fieldValue)) {
                    $total++;
                }
            }
        }

        $item['total'] = $total;
    }

    return $lineup;
}

function prepare_grouped_hours($groupedHours)
{
    $isFrench = function_exists('isFrench') && isFrench();

    $dayOrder = $isFrench ? ['Lundi', 'Mardi', 'Mercredi', 'Jeudi', 'Vendredi', 'Samedi', 'Dimanche'] : ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday'];

    $entries = [];

    foreach ($groupedHours as $time => $days) {
        foreach (group_consecutive_days($days) as $group) {
            $entries[] = [
                'days' => $group,
                'time' => $time,
                'firstIndex' => array_search($group[0], $dayOrder),
            ];
        }
    }

    usort($entries, fn($a, $b) => $a['firstIndex'] <=> $b['firstIndex']);

    return $entries;
}

/**
 * Obtener ID de formulario Ninja Forms por nombre (cacheado en opciones)
 */
function lbx_remember_transient( $key, $callback, $expiration = HOUR_IN_SECONDS ) {
    $cached = get_transient( $key );
    if ( $cached !== false ) {
        return $cached;
    }
    $value = is_callable($callback) ? $callback() : null;
    set_transient( $key, $value, $expiration );
    return $value;
}

// Obtener todos los formularios [id => título]
function _lbx_get_all_forms() {
    if ( ! function_exists('Ninja_Forms') ) return [];
    $forms = Ninja_Forms()->form()->get_forms();
    return collect($forms)
        ->mapWithKeys(fn($form) => [(int) $form->get_id() => (string) $form->get_setting('title')])
        ->toArray();
}

function lbx_get_all_forms() {
    return lbx_remember_transient('lbx_all_ninja_forms', '_lbx_get_all_forms', DAY_IN_SECONDS);
}

// Normalizar nombres
function lbx_normalize_form_name( $name ) {
    $name = strtolower( remove_accents( (string) $name ) );
    $name = str_replace('-', ' ', $name);
    $name = preg_replace('/[^\p{L}\p{N}\s]+/u', ' ', $name);
    $name = preg_replace('/\s+/u', ' ', $name);
    return trim($name);
}

// Mapa normalizado => ID (cacheado)
function lbx_get_forms_name_map() {
    return lbx_remember_transient('lbx_nf_name_map', function () {
        $forms = lbx_get_all_forms(); // [id => title]
        $map = [];
        foreach ($forms as $id => $title) {
            $norm = lbx_normalize_form_name($title);
            // Si hay duplicados, conserva el primero o define tu política
            if (!isset($map[$norm])) $map[$norm] = (int) $id;
        }
        return $map;
    }, DAY_IN_SECONDS);
}

// Lookup por nombre
function lbx_get_form_id_by_name( $form_name ) {
    if ( empty($form_name) ) return false;
    $norm = lbx_normalize_form_name($form_name);
    $map  = lbx_get_forms_name_map();
    return $map[$norm] ?? false;
}

function toLeadboxImageUrl($src, $size = '400') {
    if (!$src) {
        return null;
    }

    if (strpos($src, 'vehicleimages.leadboxhq.com') !== false) {
        return preg_replace('/^http:/i', 'https:', $src);
    }

    $pattern = '/https?:\/\/[^\/]*blob\.core\.windows\.net\/([^\/]+)\/vehicles\/([^\/]+)\/pictures\/([a-f0-9-]+)(?:-[A-Z]+)?(?:\.\w+)?$/i';
    if (preg_match($pattern, $src, $matches)) {
        $dealer = $matches[1];
        $vehicleId = $matches[2];
        $imageId = $matches[3];

        return "https://vehicleimages.leadboxhq.com/v1/{$dealer}/{$vehicleId}/{$imageId}-{$size}.jpg";
    }

    return $src;
}

// Invalidación cuando se guarda/actualiza un form
add_action('ninja_forms_save_form', function( $form_id ) {
    // Recalcula la lista y el mapa en caliente
    $all  = _lbx_get_all_forms();
    set_transient('lbx_all_ninja_forms', $all, DAY_IN_SECONDS);

    $map = [];
    foreach ($all as $id => $title) {
        $norm = lbx_normalize_form_name($title);
        if (!isset($map[$norm])) $map[$norm] = (int) $id;
    }
    set_transient('lbx_nf_name_map', $map, DAY_IN_SECONDS);
}, 9999, 1);

/**
 * ============================================================================
 * LEADBOX DATALAYER — Helpers (LBT-1395)
 * ============================================================================
 * Server-side support for window.dataLayer push of standardized lbx_* events.
 * The JS side reads window.LBX_CONTEXT injected in head.blade.php.
 */

/**
 * Master switch. All lbx_* tracking is skipped when this returns false.
 */
function is_lbx_datalayer_enabled()
{
    $s = get_option('leadbox-settings');
    return !empty($s['enable_lbx_datalayer'])
        && strtolower($s['enable_lbx_datalayer']) === 'enabled';
}

/**
 * Canonical Leadbox account identifier for this dealer.
 *
 * Single source of truth: if Ops defines a different canonical field later
 * (e.g. a constant, an API call, jlr_dealer_code), change ONLY this function.
 */
function get_lbx_account_id()
{
    $s = get_option('leadbox-settings');
    return !empty($s['leadbox_id']) ? $s['leadbox_id'] : null;
}

/**
 * Language code for the current request. Returns 'en' or 'fr'.
 */
function get_lbx_language()
{
    $locale = strtolower((string) get_locale());
    return strpos($locale, 'fr') === 0 ? 'fr' : 'en';
}

/**
 * Current page type per LBT-1395 spec (server-side detection).
 * Returns one of: homepage, vdp, srp, specials, contact, directions,
 * service, service_appointment, service_specials, parts, finance,
 * credit_application, trade, careers, about, blog, thank_you, other.
 *
 * Detection priority:
 *   1. vdp_string query var          (canonical VDP signal)
 *   2. Front page / blog home        (homepage)
 *   3. Known page slugs              (matches this theme's inventory, contact, etc.)
 *   4. Template filename pattern     (strpos over get_page_template_slug)
 *   5. Post type / archive fallbacks
 *   6. other
 */
function get_lbx_page_type()
{
    if (!empty(get_query_var('vdp_string'))) {
        return 'vdp';
    }
    if (is_front_page() || is_home()) {
        return 'homepage';
    }

    // --- Priority 3: match by WP page slug (most reliable in this theme) ---
    $slugMap = [
        'srp' => [
            'new-inventory', 'used-inventory',
            'inventaire-neufs', 'inventaire-doccasion',
        ],
        'contact'             => ['contact-us', 'contact', 'nous-joindre'],
        'directions'          => ['directions', 'hours-and-directions', 'heures-et-directions'],
        'specials'            => ['specials', 'special-offers', 'offers', 'promotions'],
        'service'             => ['service', 'service-department'],
        'service_appointment' => ['service-appointment', 'schedule-service', 'schedule-an-appointment', 'book-service', 'prendre-rendez-vous'],
        'service_specials'    => ['service-specials', 'service-coupons'],
        'parts'               => ['parts', 'pieces'],
        'finance'             => ['finance', 'financement'],
        'credit_application'  => ['credit-application', 'apply-for-credit', 'demande-de-credit'],
        'trade'               => ['trade-in', 'trade', 'evaluation', 'value-my-trade'],
        'build_and_price'     => ['build-and-price', 'build-price', 'configurer', 'configurez'],
        'careers'             => ['careers', 'carrieres', 'jobs'],
        'about'               => ['about-us', 'about', 'a-propos'],
        'thank_you'           => ['thank-you', 'thankyou', 'merci'],
    ];
    foreach ($slugMap as $type => $slugs) {
        if (is_page($slugs)) {
            return $type;
        }
    }

    // --- Priority 4: template filename pattern match ---
    $template = strtolower((string) get_page_template_slug());
    if ($template !== '') {
        if (strpos($template, 'srp') !== false) return 'srp';
        if (strpos($template, 'vdp') !== false
            || strpos($template, 'template-model') !== false
            || strpos($template, 'template-full-model') !== false
            || strpos($template, 'template-product') !== false) return 'vdp';
        if (strpos($template, 'homepage') !== false)          return 'homepage';
        if (strpos($template, 'service-appointment') !== false) return 'service_appointment';
        if (strpos($template, 'service-specials') !== false)   return 'service_specials';
        if (strpos($template, 'service') !== false)            return 'service';
        if (strpos($template, 'credit') !== false)             return 'credit_application';
        if (strpos($template, 'finance') !== false)            return 'finance';
        // Tester finding 5 (LBT-1395): build-and-price is a configurator, not
        // a trade-in tool. Ops approved a new 'build_and_price' page_type as a
        // Leadbox extension to the universal spec. Coordinate deploy with the
        // GTM container update so reporting doesn't blink.
        if (strpos($template, 'build-and-price') !== false) return 'build_and_price';
        if (strpos($template, 'trade') !== false) return 'trade';
        if (strpos($template, 'special-offers') !== false
            || strpos($template, 'offers') !== false
            || strpos($template, 'promotion') !== false)       return 'specials';
        if (strpos($template, 'contact') !== false)            return 'contact';
        if (strpos($template, 'directions') !== false)         return 'directions';
        if (strpos($template, 'parts') !== false)              return 'parts';
        if (strpos($template, 'careers') !== false)            return 'careers';
        if (strpos($template, 'about') !== false)              return 'about';
        if (strpos($template, 'thankyou') !== false
            || strpos($template, 'thank-you') !== false)       return 'thank_you';
        if (strpos($template, 'blog') !== false)               return 'blog';
    }

    // --- Priority 5: post type / archive fallbacks ---
    if (is_singular('post') || is_category() || is_tag() || is_archive()) {
        return 'blog';
    }

    return 'other';
}

/**
 * Best-effort department of the page the user came from, derived from the
 * HTTP referrer. Used so a thank_you page can "inherit from previous page"
 * per the spec. Only same-host referrers are trusted; returns null when the
 * referrer is missing, off-site, or doesn't map to a known department.
 */
function lbx_department_from_referer()
{
    $ref = isset($_SERVER['HTTP_REFERER']) ? (string) $_SERVER['HTTP_REFERER'] : '';
    if ($ref === '') {
        return null;
    }

    // Only trust same-host referrers so an external link can't spoof it.
    $refHost = strtolower((string) parse_url($ref, PHP_URL_HOST));
    $ownHost = strtolower((string) parse_url(home_url(), PHP_URL_HOST));
    if ($refHost !== '' && $ownHost !== '' && $refHost !== $ownHost) {
        return null;
    }

    $path = strtolower((string) parse_url($ref, PHP_URL_PATH));
    if ($path === '') {
        return null;
    }

    $rules = [
        'service' => ['/service', '/book-service', '/service-appointment', '/prendre-rendez-vous', '/rendez-vous'],
        'parts'   => ['/parts', '/pieces'],
        'finance' => ['/finance', '/financement', '/credit', '/demande-de-credit'],
        'sales'   => ['/new-inventory', '/used-inventory', '/inventaire', '/inventory', '/vehicle', '/vdp', '/trade', '/value-my-trade', '/build-and-price', '/specials', '/promotions'],
    ];
    foreach ($rules as $dept => $needles) {
        foreach ($needles as $needle) {
            if (strpos($path, $needle) !== false) {
                return $dept;
            }
        }
    }

    return null;
}

/**
 * Department inferred from page type. Used as default for lbx_page_view.
 */
function get_lbx_department_for_page_type($pageType)
{
    $map = [
        'homepage'            => 'general',
        'vdp'                 => 'sales',
        'srp'                 => 'sales',
        'specials'            => 'sales',
        'trade'               => 'sales',
        'contact'             => 'general',
        'directions'          => 'general',
        'service'             => 'service',
        'service_appointment' => 'service',
        'service_specials'    => 'service',
        'parts'               => 'parts',
        'finance'             => 'finance',
        'credit_application'  => 'finance',
        'careers'             => 'general',
        'about'               => 'general',
        'blog'                => 'general',
        'thank_you'           => 'general',
        'other'               => 'general',
    ];
    $dept = isset($map[$pageType]) ? $map[$pageType] : 'general';

    // thank_you "inherits from previous page" per the spec: derive the
    // department from the referring page when we can, else keep 'general'.
    if ($pageType === 'thank_you') {
        $inherited = lbx_department_from_referer();
        if ($inherited) {
            return $inherited;
        }
    }

    return $dept;
}

/**
 * Normalize a vehicle data array (from get_vehicle_by_id) into the shape
 * the dataLayer spec expects. Values are lowercased where string,
 * numeric where numeric, and null when unavailable.
 *
 * Field sources (from the per-vehicle {id}.json in uploads/data/):
 *   - condition     : 'condition' + 'certified' (used+certified → 'certified')
 *   - bodystyle     : 'bodystyle'
 *   - fuel_type     : 'fueltype'
 *   - mileage       : 'mileage'
 *   - msrp          : 'msrp' (left as-is even when 0, per user preference)
 *   - price         : 'price' (fallback 'saleprice')
 *   - discount_price: 'specialprice' if > 0, else null
 *   - incentive     : 'promocode' (no structured incentive name in feed)
 *   - location      : 'location'
 *   - status        : derived from incoming/salepending/reserved/ininventory
 *   - photo_count   : 'numberofpics' (authoritative; falls back to count(pictures))
 *   - days_in_inv   : 'age'
 *   - payment_*     : not in the JSON feed — populated client-side by calculator
 *
 * Returns null if the input is empty (non-VDP page).
 */
function get_lbx_vehicle_context($data)
{
    if (empty($data) || !is_array($data)) {
        return null;
    }

    $lc = function ($v) {
        if ($v === null || $v === '') return null;
        return strtolower(trim((string) $v));
    };
    $num = function ($v) {
        if ($v === null || $v === '' || !is_numeric($v)) return null;
        return $v + 0;
    };
    $positiveNum = function ($v) {
        if ($v === null || $v === '' || !is_numeric($v)) return null;
        $n = $v + 0;
        return $n > 0 ? $n : null;
    };

    // Condition: used+certified collapses to 'certified' per spec.
    $condition = $lc($data['condition'] ?? null);
    if ($condition === 'used' && !empty($data['certified'])) {
        $condition = 'certified';
    }

    // Inventory status: derive from the flags present in the feed.
    $status = null;
    if (!empty($data['salepending']) || !empty($data['reserved'])) {
        $status = 'sold';
    } elseif (!empty($data['incoming'])) {
        $status = 'in-transit';
    } elseif (array_key_exists('ininventory', $data) && $data['ininventory'] === false) {
        $status = 'on-order';
    } elseif (array_key_exists('ininventory', $data) && $data['ininventory'] === true) {
        $status = 'in-stock';
    } else {
        // ininventory is null/missing: if we have a stocknumber and onweb is true,
        // treat it as in-stock. Otherwise null.
        if (!empty($data['stocknumber']) && !empty($data['onweb'])) {
            $status = 'in-stock';
        }
    }

    // Photo count: 'numberofpics' is the authoritative feed value; fall back
    // to counting 'pictures' if that isn't present.
    $photoCount = null;
    if (isset($data['numberofpics']) && is_numeric($data['numberofpics'])) {
        $photoCount = (int) $data['numberofpics'];
    } elseif (isset($data['pictures']) && is_array($data['pictures'])) {
        $photoCount = count($data['pictures']);
    }

    // Discount price: the feed exposes 'specialprice' (0 means no special).
    $discountPrice = $positiveNum($data['specialprice'] ?? null);

    return [
        'vehicle_vin'               => $lc($data['vin'] ?? null),
        'vehicle_stock_number'      => $lc($data['stocknumber'] ?? null),
        'vehicle_condition'         => $condition,
        'vehicle_make'              => $lc($data['make'] ?? null),
        'vehicle_model'             => $lc($data['model'] ?? null),
        'vehicle_year'              => $num($data['year'] ?? null),
        'vehicle_trim'              => $lc($data['trim'] ?? null),
        'vehicle_bodystyle'         => $lc($data['bodystyle'] ?? null),
        'vehicle_fuel_type'         => $lc($data['fueltype'] ?? ($data['fuel'] ?? null)),
        'vehicle_mileage'           => $num($data['mileage'] ?? null),
        'vehicle_msrp'              => $num($data['msrp'] ?? null),
        'vehicle_price'             => $num($data['price'] ?? ($data['saleprice'] ?? null)),
        'vehicle_discount_price'    => $discountPrice,
        'vehicle_incentive_name'    => $lc($data['promocode'] ?? null),
        'vehicle_payment_monthly'   => null,
        'vehicle_payment_type'      => null,
        'vehicle_location'          => $lc($data['location'] ?? null),
        'vehicle_status'            => $status,
        'vehicle_photo_count'       => $photoCount,
        'vehicle_days_in_inventory' => $num($data['age'] ?? null),
    ];
}

/**
 * Build the full LBX_CONTEXT payload injected into window in head.blade.php.
 * Returns null when tracking is disabled so callers can skip the <script> block.
 */
function get_lbx_context_payload($vehicleData = null)
{
    if (!is_lbx_datalayer_enabled()) {
        return null;
    }

    $pageType = get_lbx_page_type();
    $location = get_lbx_dealer_location();

    return [
        'leadbox_id'       => get_lbx_account_id(),
        'page_type'        => $pageType,
        'department'       => get_lbx_department_for_page_type($pageType),
        'language'         => get_lbx_language(),
        'vehicle'          => get_lbx_vehicle_context($vehicleData),
        // Tester finding 9 (LBT-1395 round 2): make dealer name and full
        // address available as page-global fallback for lbx_directions_click,
        // so anchors that don't carry per-click data-lbx-location-* still
        // emit usable values instead of null / leaked template tokens.
        'location_name'    => $location['name'],
        'location_address' => $location['address'],
    ];
}

/**
 * Single dealer location for the dataLayer. Returns null fields when the
 * dealer settings are empty, which signals to the JS to keep the field null
 * rather than fall back to anchor textContent (where it would pick up
 * unfilled template placeholders like "*address_line_1*").
 */
function get_lbx_dealer_location()
{
    $c = get_dealer_contact();
    if (!is_array($c)) {
        return ['name' => null, 'address' => null];
    }
    $name = !empty($c['dealer_name']) ? trim($c['dealer_name']) : null;
    $parts = [];
    foreach (['address_line_1', 'address_line_2', 'address_city', 'address_province', 'address_postal_code'] as $k) {
        if (!empty($c[$k]) && strpos($c[$k], '*') !== 0) {
            $parts[] = trim($c[$k]);
        }
    }
    return [
        'name'    => $name,
        'address' => $parts ? implode(', ', $parts) : null,
    ];
}


Home - Capital GMC Buick Regina

No data

Welcome to Capital GMC BUICK – REGINA

Thank you for choosing Capital GMC Buick | Regina, your premier certified Buick and GMC dealership proudly serving drivers in Regina and the surrounding communities. Whether you’re searching for a brand-new Buick or GMC vehicle or a meticulously inspected pre-owned model, we have a diverse selection to match your needs and lifestyle.

Beyond our impressive inventory, we offer a seamless and stress-free financing experience through our well-connected finance centre, where our team of experts is dedicated to securing the best loan or lease options for you, quickly, transparently, and hassle-free.

But our commitment to you doesn’t stop at the sale. Our state-of-the-art service centre is staffed with skilled Buick and GMC technicians who use the latest equipment and genuine OEM parts to keep your vehicle running at its best. From routine maintenance to complex repairs, we’ve got you covered.

Experience top-tier customer service, quality vehicles, and expert care, all in one place. Visit Capital GMC Buick | Regina today or call us at 306-205-8072 with any questions. We’re here to help!

Ask a Question