<?php
require_once __DIR__ . "/_commons.php";

$pdo = pdo_m();
$GF  = get_global_filters();
if (!$GF['has_any']) { echo '<div class="warn">Sin filtros aplicados.</div>'; return; }

/* ===================== RANGO / PARAMS BASE ===================== */
[$from,$to]   = build_range($GF['range'] ?? 'month', $GF['fromUi'] ?? '', $GF['toUi'] ?? '');
$paramsBase   = [':site'=>$GF['site'], ':from'=>$from, ':to'=>$to];

/* ===================== HELPERS ===================== */
function fmt_dur($s){
  $s=max(0,(int)$s); $h=intdiv($s,3600); $s-=$h*3600; $m=intdiv($s,60); $s-=$m*60;
  if($h>0) return sprintf("%dh %02dm %02ds",$h,$m,$s);
  if($m>0) return sprintf("%dm %02ds",$m,$s);
  return sprintf("%ds",$s);
}
/** Ruta limpia (sin host/query/hash). Interna: /ruta; externa: //host/ruta */
function clean_route($u,$siteHost='feelthevibe.fit'){
  if(!$u) return '';
  $p=@parse_url($u); if(!is_array($p)) return '';
  $host=strtolower($p['host']??''); $path=$p['path']??'/';
  $path=rawurldecode($path); $path=preg_replace('~//+~','/',$path);
  $path=preg_replace('~/index\.php$~i','/',$path);
  if($path!=='/' && substr($path,-1)==='/'){ $path=rtrim($path,'/'); }
  $isInternal=false;
  if($host===''||!$siteHost){ $isInternal=true; }
  else { $re='~(^|\.)'.preg_quote($siteHost,'~').'$~i'; $isInternal=(bool)preg_match($re,$host); }
  return $isInternal ? ($path?:'/') : ('//'.$host.($path?:'/'));
}
function utm_text($url){
  if(!$url) return '';
  $parts=@parse_url($url); if(empty($parts['query'])) return '';
  parse_str($parts['query'],$q);
  $keys=['utm_source','utm_medium','utm_campaign','utm_content','utm_term'];
  $pairs=[]; foreach($keys as $k){ if(!empty($q[$k])) $pairs[]="$k=".$q[$k]; }
  return $pairs ? implode(' · ',$pairs) : '';
}
function route_tag($route){
  $MAP=[
    '~^/(es/)?vibe-landing-page$~i'=>'Landing',
    '~^/(es/)?checkout$~i'=>'Checkout',
    '~^/vibes/vibes-formulario\.php$~i'=>'Formulario',
  ];
  foreach($MAP as $re=>$label){ if(preg_match($re,$route)) return $label; }
  return '';
}
/** Cache rápido para columnas de LVA (compatibilidad de esquemas) */
function lva_has_col($col){
  static $cols=null;
  if($cols===null){
    try{ $st=pdo_m()->query("SHOW COLUMNS FROM matomo_log_link_visit_action");
      $cols=[]; foreach($st->fetchAll() as $r){ $cols[strtolower($r['Field'])]=true; }
    }catch(Throwable $e){ $cols=[]; }
  }
  return isset($cols[strtolower($col)]);
}

/* ===================== FILTROS GLOBALES (ALINEADOS) ===================== */
/* Filtro de entrada canónico (mismo que el resto de widgets) */
$entryCond   = entry_condition_sql();           // "(ain.name LIKE :url1 OR ain.name LIKE :url2 OR ain.name LIKE '%utm_%')"
$paramsEntry = $paramsBase + allowed_url_params();

/* Campaña/Fuente (g_src) */
list($campWhere,$campParams) = campaign_source_condition($GF,'v');

/* Si es Directo, excluir UTM en la URL de ENTRADA (para cuadrar con selector/cards) */
list($nonCampGuard,) = non_campaign_guard_sql($GF,'ain',false);

/* Búsqueda avanzada (idvisit, idvisitor HEX, URL de entrada) — aquí SÍ aplica */
list($advWhere,$advParams/*,$needAin*/) = build_advanced_where($GF,'v','ain');

/* ===================== FETCH DE VISITAS (con fallback) ===================== */
function fetch_visits($useEntry=true){
  global $pdo,$paramsBase,$paramsEntry,$entryCond,$campWhere,$campParams,$advWhere,$advParams,$nonCampGuard;

  $where = "WHERE v.idsite = :site
              AND v.visit_last_action_time BETWEEN :from AND :to
              ".($useEntry ? " AND $entryCond " : "")."
              $campWhere
              $nonCampGuard
              $advWhere";

  $sql = "
    SELECT
      v.idvisit,
      HEX(v.idvisitor) AS visitor,
      DATE_FORMAT(v.visit_first_action_time,'%Y-%m-%d %H:%i:%s') AS start_at,
      DATE_FORMAT(v.visit_last_action_time ,'%Y-%m-%d %H:%i:%s') AS end_at,
      TIMESTAMPDIFF(SECOND, v.visit_first_action_time, v.visit_last_action_time) AS dur_secs,
      (SELECT COUNT(*) FROM matomo_log_link_visit_action lva2 WHERE lva2.idvisit = v.idvisit) AS actions_cnt,
      CASE v.referer_type
        WHEN 1 THEN 'Directo'
        WHEN 2 THEN CONCAT('Búsqueda: ', COALESCE(v.referer_name,''))
        WHEN 3 THEN CONCAT('Referencia: ', COALESCE(v.referer_name,''))
        WHEN 6 THEN CONCAT('Campaña: ', COALESCE(v.referer_name,''))
        ELSE 'Desconocido'
      END AS source,
      v.config_browser_name AS br,
      v.config_os          AS os,
      v.config_device_type AS dt,
      v.location_country   AS cc,
      v.location_region    AS rr,
      v.location_city      AS city,
      ain.name             AS entry_url
    FROM matomo_log_visit v
    LEFT JOIN matomo_log_action ain ON ain.idaction = v.visit_entry_idaction_url
    $where
    ORDER BY v.visit_last_action_time DESC
    LIMIT 200
  ";
  try{
    $params = ($useEntry ? $paramsEntry : $paramsBase) + $campParams + $advParams;
    $st=$pdo->prepare($sql); $st->execute($params);
    return $st->fetchAll() ?: [];
  }catch(Throwable $e){
    return [];
  }
}

$rows = fetch_visits(true);
$warnExpanded = false;
if(!$rows){
  $rows = fetch_visits(false); // fallback sin filtro de entrada (para no bloquear tablero)
  if($rows){ $warnExpanded = true; }
}

/* ===================== AGRUPAR POR USUARIO (HEX) ===================== */
$byVisitor = [];
foreach($rows as $r){ $byVisitor[$r['visitor']][] = $r; }

/* ===================== TIMELINE (acciones + eventos) ===================== */
function fetch_path($idvisit,$siteId){
  $pdo = pdo_m();
  $hasEvName = lva_has_col('idaction_event_name');

  $selectEventName = $hasEvName ? ", nam.name AS ev_name" : ", NULL AS ev_name";
  $joinEventName   = $hasEvName ? "LEFT JOIN matomo_log_action nam ON nam.idaction = lva.idaction_event_name" : "";

  $sql = "
    SELECT
      DATE_FORMAT(lva.server_time,'%H:%i:%s') AS t,
      url.name   AS url_name,
      title.name AS page_title,
      cat.name   AS ev_cat,
      act.name   AS ev_act
      $selectEventName,
      url.type   AS url_type
    FROM matomo_log_link_visit_action lva
    JOIN matomo_log_visit v ON v.idvisit = lva.idvisit AND v.idsite = :site
    LEFT JOIN matomo_log_action url   ON url.idaction   = lva.idaction_url
    LEFT JOIN matomo_log_action title ON title.idaction = lva.idaction_name
    LEFT JOIN matomo_log_action cat   ON cat.idaction   = lva.idaction_event_category
    LEFT JOIN matomo_log_action act   ON act.idaction   = lva.idaction_event_action
    $joinEventName
    WHERE lva.idvisit = :idv
    ORDER BY lva.server_time ASC
  ";
  try{
    $st=$pdo->prepare($sql); $st->execute([':idv'=>$idvisit,':site'=>$siteId]);
    $rows=$st->fetchAll() ?: [];
  }catch(Throwable $e){
    return ['__error__'=>$e->getMessage()];
  }

  $out=[];
  foreach($rows as $r){
    $isEvent = ($r['ev_cat']!==null || $r['ev_act']!==null || $r['ev_name']!==null);
    if($isEvent){
      $type='event';
      $parts=array_filter([$r['ev_cat'],$r['ev_act'],$r['ev_name']]);
      $route=trim(implode(' › ',$parts)) ?: '(evento)';
      $tag='';
    }else{
      $t=(int)($r['url_type']??0);
      $href=$r['url_name'] ?? '';
      $route=$href ? clean_route($href) : ($r['page_title'] ?? '(sin título)');
      $tag=$href ? route_tag($route) : '';
      if($t===3) $type='outlink';
      elseif($t===2) $type='download';
      else $type='pageview';
    }
    $out[]=['t'=>$r['t']?:'','type'=>$type,'route'=>$route,'tag'=>$tag];
  }
  return $out;
}
?>
<style>
.usx-group{background:#f8fafc;font-weight:600;}
.usx-mono{font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,"Liberation Mono",monospace;}
.usx-muted{color:#6b7280;}
.usx-panel{background:#fcfcfc;}
.usx-ol{margin:0;padding-left:18px;line-height:1.45;}
.usx-ol li{margin:2px 0;}
.usx-tag{display:inline-block;font-size:12px;line-height:1;padding:2px 6px;border-radius:9999px;background:#eef2ff;color:#3730a3;margin-left:6px;}
.usx-utm{font-size:12px;margin-top:2px;}
.usx-toggle{padding:4px 8px;font-size:12px}
.is-hidden{display:none !important;}
</style>

<?php if($warnExpanded){ ?>
  <div class="warn" style="margin-bottom:8px">
    No hubo resultados con el filtro de entrada por landing/UTM. Se muestran visitas sin ese filtro para no bloquear el tablero.
  </div>
<?php } ?>

<div class="filters" style="gap:8px">
  <label><b>Fuente:</b></label>
  <select id="us_source">
    <option value="">Todas</option>
    <?php $srcs=[]; foreach($rows as $r){ $srcs[$r['source']]=true; }
    foreach(array_keys($srcs) as $s): ?>
      <option value="<?= e($s) ?>"><?= e($s) ?></option>
    <?php endforeach; ?>
  </select>
  <label><b>ID usuario (HEX):</b></label>
  <input id="us_vid" placeholder="Buscar..." style="padding:6px">
</div>

<div class="table-scroll">
  <table class="simple" id="us_table">
    <thead>
      <tr>
        <th style="width:160px">Inicio</th>
        <th>Usuario</th>
        <th>Fuente</th>
        <th>Entrada (ruta)</th>
        <th>Equipo</th>
        <th>Ubicación</th>
        <th style="width:110px">Duración</th>
        <th style="width:90px">Acciones</th>
        <th style="width:130px">Recorrido</th>
      </tr>
    </thead>
    <tbody>
    <?php if(!$rows){ ?>
      <tr><td colspan="9"><span class="muted">Sin datos</span></td></tr>
    <?php } else {
      $byVisitor=[]; foreach($rows as $r){ $byVisitor[$r['visitor']][]=$r; }
      foreach($byVisitor as $visitorHex=>$visits): ?>
        <tr class="usx-group" data-group="<?= e($visitorHex) ?>">
          <td colspan="9">Usuario (HEX): <span class="usx-mono"><?= e($visitorHex) ?></span>
            <span class="usx-muted"> · <?= count($visits) ?> visita(s)</span>
          </td>
        </tr>
        <?php foreach($visits as $r):
          $vid=(int)$r['idvisit']; $n=(int)($r['actions_cnt']??0); $dur=fmt_dur($r['dur_secs']??0);
          $entryRoute=clean_route($r['entry_url']); $entryUtm=utm_text($r['entry_url']); $entryTag=route_tag($entryRoute);
          $path=fetch_path($vid,(int)$GF['site']); $rowId='tl_'.$vid; ?>
          <tr class="usx-visit" data-source="<?= e($r['source']) ?>" data-visitor="<?= e($visitorHex) ?>">
            <td><?= e($r['start_at']) ?></td>
            <td class="usx-mono"><?= e($visitorHex) ?></td>
            <td><?= e($r['source']) ?></td>
            <td>
              <span class="usx-mono"><?= e($entryRoute ?: '-') ?></span>
              <?php if($entryTag){ ?><span class="usx-tag"><?= e($entryTag) ?></span><?php } ?>
              <?php if($entryUtm){ ?><div class="usx-muted usx-utm"><?= e($entryUtm) ?></div><?php } ?>
            </td>
            <td><?= e(browser_human($r['br']).' · '.os_human($r['os']).' · '.device_human($r['dt'])) ?></td>
            <td><?= e(strtoupper($r['cc']).' '.$r['rr'].' '.$r['city']) ?></td>
            <td><?= e($dur) ?></td>
            <td><?= (int)$n ?></td>
            <td><button class="usx-toggle" data-target="<?= e($rowId) ?>">Ver recorrido (<?= (int)$n ?>)</button></td>
          </tr>
          <tr id="<?= e($rowId) ?>" class="usx-panel-row is-hidden">
            <td colspan="9" class="usx-panel">
              <?php if(is_array($path) && isset($path['__error__'])){
                echo '<span class="muted">No se pudo cargar el recorrido. El tablero continúa funcionando.</span>';
              } elseif(!$path){
                echo '<span class="muted">Sin acciones registradas</span>';
              } else {
                echo '<ol class="usx-ol">';
                foreach($path as $p){
                  $tag=$p['tag'] ? '<span class="usx-tag">'.e($p['tag']).'</span>' : '';
                  echo '<li><span class="usx-muted">'.e($p['t']).'</span> — <b>'.e($p['type']).'</b>: <span class="usx-mono">'.e($p['route']).'</span> '.$tag.'</li>';
                }
                echo '</ol>';
              } ?>
            </td>
          </tr>
        <?php endforeach; ?>
      <?php endforeach; ?>
    <?php } ?>
    </tbody>
  </table>
</div>

<script>
(function(){
  const srcSel=document.getElementById('us_source');
  const idInp=document.getElementById('us_vid');

  document.addEventListener('click',(ev)=>{
    const btn=ev.target.closest('.usx-toggle'); if(!btn) return;
    const id=btn.getAttribute('data-target'); const row=document.getElementById(id);
    if(row){ row.classList.toggle('is-hidden'); }
  });

  function apply(){
    const s=srcSel ? srcSel.value : '';
    const q=(idInp && idInp.value ? idInp.value.trim().toLowerCase() : '');
    const rows=document.querySelectorAll('#us_table tbody tr.usx-visit');
    rows.forEach(tr=>{
      const src=tr.getAttribute('data-source')||'';
      const v=(tr.getAttribute('data-visitor')||'').toLowerCase();
      const show=(!s||src===s)&&(!q||v.includes(q));
      tr.style.display=show?'':'none';
      const btn=tr.querySelector('.usx-toggle');
      const tgt=btn?document.getElementById(btn.getAttribute('data-target')):null;
      if(tgt && !show){ tgt.classList.add('is-hidden'); }
    });
    const headers=document.querySelectorAll('#us_table tbody tr.usx-group');
    headers.forEach(h=>{
      let visible=false, nxt=h.nextElementSibling;
      while(nxt && !nxt.classList.contains('usx-group')){
        if(nxt.classList.contains('usx-visit') && nxt.style.display!=='none'){ visible=true; break; }
        nxt=nxt.nextElementSibling;
      }
      h.style.display=visible?'':'none';
    });
  }
  if(srcSel) srcSel.addEventListener('change',apply);
  if(idInp)  idInp.addEventListener('input',apply);
})();
</script>
