<?php
// reparacion.php — SGO · Programación de Reparaciones (Select2 múltiple + buscador en modal, sin severidad ni badges)
declare(strict_types=1);
session_start();
if (!isset($_SESSION['ingreso']) || $_SESSION['ingreso'] !== 'YES') {
  header("Location: ../../views/index.php"); exit();
}
require_once __DIR__ . '/conex.php';
?>
<!doctype html>
<html lang="es">
<head>
  <meta charset="utf-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1" />
  <title>SGO · Programación de Reparaciones</title>

  <!-- CSS -->
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css">
  <link rel="stylesheet" href="https://cdn.datatables.net/1.13.8/css/dataTables.bootstrap5.min.css">
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.2/css/all.min.css">
  <link href="https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/css/select2.min.css" rel="stylesheet" />
  <style>
    body{ font-size:.95rem; }
    .table thead th { white-space: nowrap; }
    .w-220{ width:220px; }
    .spinner-xxs{ width:1rem;height:1rem;border-width:.15rem; }
    .select2-container{ width:100% !important; }
    .select2-results__option{ font-size:.9rem; }
    .select2-selection--multiple .select2-selection__choice{
      font-size:.8rem; padding:0 .35rem;
    }
    /* Solo dentro del modal de novedades */
    #modalNovedades .select2-container {
      width: auto !important;     /* clave: que NO sea 100% */
      min-width: 160px;           /* para que no quede demasiado pequeño */
      max-width: 220px;           /* coincide con tu .w-220 de la columna */
    }
    
    /* Altura compacta */
    #modalNovedades .select2-selection--multiple .select2-selection__choice {
      margin-top: 2px;
    }

  </style>
</head>
<body>
<div class="container-fluid">
  <div class="row">
    <?php include 'partials/menu.php'; ?>
    <main class="col-md-9 ms-sm-auto col-lg-10 px-2">
      <?php include 'partials/topbar.php'; ?>

      <div class="d-flex justify-content-between align-items-center mt-2 mb-2">
        <h6 class="mb-0">Programación de Reparaciones</h6>
      </div>

      <div class="card shadow-sm">
        <div class="card-body p-2">
          <div class="table-responsive">
            <table id="asigna" class="table table-hover table-sm w-100">
              <thead class="table-light">
                <tr>
                  <th>Marca</th>
                  <th>Modelo</th>
                  <th>Chasis</th>
                  <th>Color</th>
                  <th>FECHA DE PROGRAMACIÓN</th>
                  <th class="text-center">Novedades</th>
                </tr>
              </thead>
              <tbody><!-- dinámico --></tbody>
            </table>
          </div>
        </div>
      </div>

    </main>
  </div>
</div>

<!-- Modal: Novedades por chasis -->
<div class="modal fade" id="modalNovedades" tabindex="-1" aria-hidden="true">
  <div class="modal-dialog modal-xl modal-dialog-centered">
    <div class="modal-content">
      <div class="modal-header py-2">
        <h6 class="modal-title">
          <i class="fa-solid fa-clipboard-check me-2"></i>
          Novedades de tarja · <span id="nv-chasis" class="text-muted"></span>
        </h6>
        <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Cerrar"></button>
      </div>

      <div class="modal-body">
        <div id="nv-loader" class="text-center my-3" style="display:none;">
          <div class="spinner-border" role="status" aria-hidden="true"></div>
          <div class="small mt-2">Cargando novedades…</div>
        </div>

        <div id="nv-empty" class="alert alert-info py-2" style="display:none;">
          No se encontraron novedades para este chasis.
        </div>
        <div id="nv-error" class="alert alert-danger py-2" style="display:none;"></div>

        <!-- Buscador local -->
        <div id="nv-searchbar" class="mb-2" style="display:none;">
          <div class="input-group input-group-sm">
            <span class="input-group-text"><i class="fa-solid fa-magnifying-glass"></i></span>
            <input id="nv-filter" type="search" class="form-control"
                   placeholder="Filtrar por zona, parte, novedad, observación o medida…" autocomplete="off">
            <button class="btn btn-outline-secondary" type="button" id="nv-clear">Limpiar</button>
          </div>
        </div>

        <div class="table-responsive" id="nv-wrap" style="display:none;">
          <table class="table table-sm align-middle">
            <thead class="table-light">
              <tr>
                <th style="width:260px;">Zona / Sección / Parte</th>
                <th>Novedad</th>
                <th>Medida</th>
                <th>Observación</th>
                <th>Foto</th>
                <th class="w-220">Tipos Reparación</th>
              </tr>
            </thead>
            <tbody id="nv-tbody"></tbody>
          </table>
        </div>
      </div>

      <div class="modal-footer py-2">
        <button type="button" class="btn btn-outline-secondary btn-sm" data-bs-dismiss="modal">Cerrar</button>
      </div>
    </div>
  </div>
</div>

<!-- JS -->
<script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
<script src="https://cdn.datatables.net/1.13.8/js/jquery.dataTables.min.js"></script>
<script src="https://cdn.datatables.net/1.13.8/js/dataTables.bootstrap5.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/js/select2.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/js/i18n/es.js"></script>

<script>
  // API base
  const API_BASE = new URL('api/', window.location.href).href;
  const api  = p => new URL(p, API_BASE).href;
  const esc  = s => String(s ?? '').replace(/[&<>"']/g, m => ({'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#39;'}[m]));
  // Estructura: [{id, tipo, id_taller, taller}]
  let TIPO_REP_OPTS = [];
  // Mapa por taller: { id_taller: { taller, items:[...] } }
  let TIPOS_POR_TALLER = {};

  $(function(){
    $('#asigna').DataTable({
      ajax: { url: api('reparaciones_list_min.php'), dataSrc: 'data' },
      columns: [
        { data: 'marca' },
        { data: 'modelo' },
        { data: 'chasis' },
        { data: 'color' },
        { data: 'fecha_programada' },
        { data: null, orderable:false, searchable:false, className:'text-center',
          render: (row)=> `
            <button class="btn btn-outline-primary btn-sm"
                    title="Ver novedades de inspección"
                    onclick="verNovedades('${(row.chasis||'').replace(/'/g,"\\'")}')">
              <i class="fa-solid fa-list-check me-1"></i> Ver
            </button>`
        }
      ],
      order: [[4,'desc']],
      pageLength: 25,
      language: { url: 'https://cdn.datatables.net/plug-ins/1.13.8/i18n/es-ES.json' }
    });
  });

  // Cargar catálogo (posible filtro por taller más adelante)
  async function cargarTipos(id_taller = null){
    if (TIPO_REP_OPTS.length && id_taller === null) return TIPO_REP_OPTS;

    const url = new URL(api('tipo_reparacion_list.php'));
    if (id_taller) url.searchParams.set('id_taller', String(id_taller));

    const r = await fetch(url, { cache: 'no-store' });
    const raw = await r.text();
    if (!r.ok) throw new Error(raw);
    let j = null; try { j = JSON.parse(raw) } catch { throw new Error('Respuesta no-JSON al cargar tipos'); }
    const arr = (j?.success && Array.isArray(j.data)) ? j.data : [];

    if (id_taller) {
      // Si se pidió un taller específico, no tocamos la cache global
      return arr;
    }

    TIPO_REP_OPTS = arr;

    // Construir mapa por taller
    TIPOS_POR_TALLER = {};
    for (const it of TIPO_REP_OPTS){
      const tid = String(it.id_taller ?? 0);
      if (!TIPOS_POR_TALLER[tid]) TIPOS_POR_TALLER[tid] = { taller: it.taller || 'Sin taller', items: [] };
      TIPOS_POR_TALLER[tid].items.push(it);
    }
    return TIPO_REP_OPTS;
  }

  // Render Select2 agrupado por Taller
  function renderSelectTipos(incident_id, selectedIds){
    const sel = document.createElement('select');
    sel.className = 'form-select form-select-sm js-tipo-select';
    sel.setAttribute('multiple', 'multiple');
    sel.dataset.incidentId = incident_id;
    sel.style.width = 'auto';

    const selectedSet = new Set((selectedIds || []).map(String));

    // Agrupar por taller usando <optgroup>
    const tallerIds = Object.keys(TIPOS_POR_TALLER);
    if (tallerIds.length) {
      for (const tid of tallerIds){
        const grupo = TIPOS_POR_TALLER[tid];
        const og = document.createElement('optgroup');
        og.label = grupo.taller || 'Sin taller';
        for (const opt of grupo.items){
          const o = document.createElement('option');
          o.value = String(opt.id);
          o.textContent = opt.tipo;
          if (selectedSet.has(String(opt.id))) o.selected = true;
          og.appendChild(o);
        }
        sel.appendChild(og);
      }
    } else {
      // Respaldo plano si no llegó catálogo agrupado
      for (const opt of TIPO_REP_OPTS){
        const o = document.createElement('option');
        o.value = String(opt.id);
        o.textContent = opt.tipo + (opt.taller ? ` — ${opt.taller}` : '');
        if (selectedSet.has(String(opt.id))) o.selected = true;
        sel.appendChild(o);
      }
    }

    queueMicrotask(() => {
      const $sel = $(sel);
      $sel.select2({
        language: 'es',
        placeholder: 'Seleccione tipos…',
        allowClear: true,
        width: 'style',
        closeOnSelect: false,
        dropdownAutoWidth: true,
        dropdownParent: $('#modalNovedades'),
        // Formatear el grupo visualmente
        templateResult: function (data) { return data.text; },
        templateSelection: function (data) { return data.text; }
      });

      let t=null;
      $sel.on('change', () => {
        clearTimeout(t);
        t = setTimeout(async () => {
          const vals = $sel.val() || [];
          await guardarTipos(Number(sel.dataset.incidentId), vals, sel);
        }, 250);
      });
    });

    return sel;
  }

  async function guardarTipos(incident_id, tipos_ids, selEl){
    if (!Number.isInteger(incident_id) || incident_id <= 0) {
      alert('incident_id requerido'); return;
    }
    const spinner = document.createElement('div');
    spinner.className = 'spinner-border spinner-xxs text-secondary ms-2';
    spinner.role = 'status'; spinner.style.verticalAlign='middle';
    selEl.parentElement?.appendChild(spinner);
    try{
      const r = await fetch(api('incidente_tipos_guardar.php'), {
        method:'POST',
        headers:{'Content-Type':'application/json'},
        body: JSON.stringify({ incident_id, tipos_ids }),
        cache: 'no-store'
      });
      const raw = await r.text();
      if (!r.ok) throw new Error(`HTTP ${r.status} ${r.statusText} — ${raw.slice(0,200)}${raw.length>200?'…':''}`);
      const ct = (r.headers.get('content-type')||'').toLowerCase();
      if (!ct.includes('application/json')) { console.error(raw); throw new Error('La API devolvió HTML/no-JSON.'); }
      let j; try { j = JSON.parse(raw); } catch { console.error(raw); throw new Error('JSON inválido.'); }
      if (j.success !== true) throw new Error(j.message || j.sql_error || 'No se pudo guardar los tipos');
    }catch(e){
      alert(e.message);
    }finally{
      spinner.remove();
    }
  }

  function debounce(fn, ms){ var t; return function(){ var a=arguments; clearTimeout(t); t=setTimeout(function(){ fn.apply(null,a); }, ms); }; }
  function applyNvFilter(){
    var inp = document.getElementById('nv-filter');
    var q = (inp && inp.value ? inp.value : '').trim().toLowerCase();
    var tbody = document.getElementById('nv-tbody');
    if (!tbody) return;
    for (var i=0;i<tbody.rows.length;i++){
      var tr = tbody.rows[i];
      var text = tr.innerText.toLowerCase();
      tr.style.display = (!q || text.indexOf(q) !== -1) ? '' : 'none';
    }
  }
  var debApplyNvFilter = debounce(applyNvFilter, 300);

  async function verNovedades(chasis){
    document.getElementById('nv-chasis').textContent = chasis;
    document.getElementById('nv-loader').style.display  = 'block';
    document.getElementById('nv-error').style.display   = 'none';
    document.getElementById('nv-empty').style.display   = 'none';
    document.getElementById('nv-wrap').style.display    = 'none';
    document.getElementById('nv-searchbar').style.display = 'none';
    document.getElementById('nv-tbody').innerHTML = '';
    var inpInit = document.getElementById('nv-filter'); if (inpInit) inpInit.value='';

    new bootstrap.Modal(document.getElementById('modalNovedades')).show();

    try {
      // Carga catálogo (agrupado por taller)
      await cargarTipos();

      const r = await fetch(api('novedades_tarja.php'), {
        method:'POST',
        headers:{'Content-Type':'application/json'},
        body: JSON.stringify({ chasis }),
        cache: 'no-store'
      });
      const raw = await r.text();
      if (!r.ok) throw new Error(`Error ${r.status} ${r.statusText} — ${raw.slice(0,200)}${raw.length>200?'…':''}`);

      let j = null; try { j = JSON.parse(raw); } catch(e) {
        console.error('[novedades_tarja] Respuesta no-JSON:', raw);
        throw new Error('La API respondió un contenido no-JSON (ver consola).');
      }
      if (j.success !== true) throw new Error((j.message||j.sql_error||'No se pudo obtener novedades'));

      const rows = Array.isArray(j.data) ? j.data : [];
      document.getElementById('nv-loader').style.display = 'none';

      if (!rows.length) { document.getElementById('nv-empty').style.display = 'block'; return; }

      const tbody = document.getElementById('nv-tbody');

      for (const it of rows) {
        const medida =
          (it.medida_tomada ? esc(it.medida_tomada) : '—') +
          (it.nombre_medida_catalogo ? ` <small class="text-muted">(${esc(it.nombre_medida_catalogo)})</small>` : '');

        const zs = [it.detallezona, it.seccion, it.detalleparte].filter(Boolean).map(esc).join(' / ');

        const tr = document.createElement('tr');
        tr.innerHTML = `
          <td>${zs || '—'}</td>
          <td>${esc(it.detallenovedad||'')}</td>
          <td>${medida}</td>
          <td>${esc(it.observacion||'')}</td>
          <td>${it.foto ? `<a href="${esc(it.foto)}" target="_blank">Ver</a>` : '—'}</td>
          <td></td>
        `;
        tbody.appendChild(tr);

        const idInc = Number(it.incident_id ?? it.idincidente ?? it.id_incidente ?? 0);
        if (!Number.isInteger(idInc) || idInc <= 0) {
          tr.children[5].innerHTML = '<span class="text-muted">Sin ID de incidente</span>';
          continue;
        }

        const selectedIds = (it.tipos_reparacion_ids || []).map(String);
        const sel = renderSelectTipos(idInc, selectedIds);
        tr.children[5].appendChild(sel);
      }

      document.getElementById('nv-wrap').style.display = 'block';
      document.getElementById('nv-searchbar').style.display = 'block';

      var inpEl   = document.getElementById('nv-filter');
      var clearEl = document.getElementById('nv-clear');
      if (inpEl) { inpEl.removeEventListener('input', debApplyNvFilter); inpEl.addEventListener('input', debApplyNvFilter); }
      if (clearEl) { clearEl.onclick = function(){ if (inpEl) inpEl.value=''; applyNvFilter(); }; }
      applyNvFilter();

    } catch (e) {
      document.getElementById('nv-loader').style.display = 'none';
      const box = document.getElementById('nv-error');
      box.textContent = e.message;
      box.style.display = 'block';
    }
  }
  window.verNovedades = verNovedades;

  document.getElementById('modalNovedades')
    .addEventListener('hidden.bs.modal', function(){
      $('#modalNovedades .js-tipo-select').each(function(){
        try { $(this).select2('destroy'); } catch(e){}
      });
      var inp = document.getElementById('nv-filter');
      if (inp) inp.value = '';
      applyNvFilter();
    });
</script>
</body>
</html>