<?php
declare(strict_types=1);

/**
 * DISLAB - Hizmet Kataloğu Yönetimi (FULL)
 * - SOAP Senkronizasyon (sync_all)
 * - Arama / Listeleme (fetch_list) -> Desktop TABLE + Mobile CARDS (FIXED)
 * - Çoklu seçim: Sil / Aktif-Pasif / Seçilenleri yeniden sync
 * - Tekli düzenleme (modal save)
 * - Waitscreen (overlay)
 */

if (session_status() === PHP_SESSION_NONE) { session_start(); }

/* ---------------------------------------------------------
   0) Helpers
------------------------------------------------------------ */
if (!function_exists('h')) {
  function h(?string $s): string { return htmlspecialchars((string)($s ?? ''), ENT_QUOTES, 'UTF-8'); }
}
function xmlv(?string $s): string {
  return htmlspecialchars((string)($s ?? ''), ENT_XML1 | ENT_COMPAT, 'UTF-8');
}
function json_out(array $arr): void {
  while (ob_get_level()) { ob_end_clean(); }
  header('Content-Type: application/json; charset=utf-8');
  echo json_encode($arr, JSON_UNESCAPED_UNICODE);
  exit;
}

/* ---------------------------------------------------------
   1) DB Obj Bul
------------------------------------------------------------ */
global $db, $conn, $pdo;
$db_obj = is_object($db) ? $db : (is_object($conn) ? $conn : $pdo);
if (!$db_obj) {
  $db_path = realpath(__DIR__ . '/../core/db.php');
  if ($db_path && file_exists($db_path)) { require_once $db_path; }
  $db_obj = is_object($db) ? $db : (is_object($conn) ? $conn : $pdo);
}
if (!$db_obj) { die("DB bağlantısı bulunamadı."); }

/* ---------------------------------------------------------
   2) Kolon Var mı? (cache)
------------------------------------------------------------ */
$__col_cache = [];
function has_col(PDO $pdo, string $table, string $col): bool {
  global $__col_cache;
  $key = $table . ':' . $col;
  if (isset($__col_cache[$key])) return $__col_cache[$key];

  $sql = "SELECT COUNT(*)
          FROM INFORMATION_SCHEMA.COLUMNS
          WHERE TABLE_SCHEMA = DATABASE()
            AND TABLE_NAME = ?
            AND COLUMN_NAME = ?";
  $st = $pdo->prepare($sql);
  $st->execute([$table, $col]);
  $__col_cache[$key] = ((int)$st->fetchColumn() > 0);
  return $__col_cache[$key];
}

/* ---------------------------------------------------------
   3) Aktif Konfig
------------------------------------------------------------ */
$conf = $db_obj->query("SELECT * FROM dislab_tanimlari WHERE is_active = 1 LIMIT 1")->fetch(PDO::FETCH_ASSOC) ?: null;

/* ---------------------------------------------------------
   4) SOAP: HizmetListesiGetir
------------------------------------------------------------ */
function dislab_fetch_catalog(PDO $pdo, array $conf): array {
  if (!$conf || empty($conf['ws_url'])) {
    throw new Exception("Aktif dışlab tanımı bulunamadı (dislab_tanimlari).");
  }

  // Not: sende pass_enc var. Eğer şifre encrypted ise buraya decrypt entegre edersin.
  $pass = (string)($conf['pass_enc'] ?? '');

  $xml_payload = '<?xml version="1.0" encoding="utf-8"?>
  <soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                 xmlns:xsd="http://www.w3.org/2001/XMLSchema"
                 xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
    <soap:Body>
      <HizmetListesiGetir xmlns="http://tenay.com.tr/">
        <kurumbilgileri>
          <WebUserKurumId>0</WebUserKurumId>
          <KullaniciAdi>'.xmlv((string)$conf['username']).'</KullaniciAdi>
          <Sifre>'.xmlv($pass).'</Sifre>
          <Kodu>'.xmlv((string)$conf['kurum_kodu']).'</Kodu>
          <KurumKodu>'.xmlv((string)$conf['kurum_kodu']).'</KurumKodu>
        </kurumbilgileri>
      </HizmetListesiGetir>
    </soap:Body>
  </soap:Envelope>';

  $ch = curl_init((string)$conf['ws_url']);
  curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_POST => true,
    CURLOPT_POSTFIELDS => $xml_payload,
    CURLOPT_HTTPHEADER => [
      'Content-Type: text/xml; charset=utf-8',
      'SOAPAction: "http://tenay.com.tr/HizmetListesiGetir"'
    ],
    CURLOPT_CONNECTTIMEOUT => 15,
    CURLOPT_TIMEOUT => 90,
  ]);
  $response = curl_exec($ch);
  $err = curl_error($ch);
  $http = (int)curl_getinfo($ch, CURLINFO_HTTP_CODE);
  curl_close($ch);

  if ($response === false || $http >= 400) {
    throw new Exception("SOAP çağrısı başarısız. HTTP=$http Hata=$err");
  }

  $clean_xml = str_ireplace(['SOAP-ENV:', 'SOAP:', 'diffgr:', 'msdata:'], '', (string)$response);
  $xml = @simplexml_load_string($clean_xml);
  if (!$xml) throw new Exception("SOAP XML parse edilemedi.");

  $items = $xml->xpath('//*[local-name()="Detay"]');
  if (!$items) return [];

  $out = [];
  foreach ($items as $item) {
    $code = trim((string)$item->Kodu);
    if ($code === '') continue;

    $out[$code] = [
      'dislab_id'     => (string)$item->Id,
      'dislab_kodu'   => $code,
      'dislab_adi'    => (string)$item->Adi,
      'sut_kodu'      => (string)$item->SutKodu,
      'ornek_tur_id'  => (string)$item->OrnekTurId,
      'ornek_tur_adi' => (string)$item->OrnekTurAdi,
      'kap_id'        => (string)$item->KapId,
      'kap_adi'       => (string)$item->KapAdi,
    ];
  }
  return $out;
}

/* ---------------------------------------------------------
   5) AJAX Actions
------------------------------------------------------------ */
if (isset($_GET['action'])) {
  try {
    $action = (string)$_GET['action'];

    $raw = file_get_contents('php://input');
    $payload = $raw ? json_decode($raw, true) : [];
    if (!is_array($payload)) $payload = [];

    // --- SYNC ALL ---
    if ($action === 'sync_all') {
      $catalog = dislab_fetch_catalog($db_obj, (array)$conf);

      $stats = ['added' => 0, 'updated' => 0, 'total_from_ws' => count($catalog)];

      $has_last_sync = has_col($db_obj, 'dislab_test_listesi', 'last_sync');
      $has_test_tipi = has_col($db_obj, 'dislab_test_listesi', 'test_tipi');
      $has_parent_id = has_col($db_obj, 'dislab_test_listesi', 'parent_id');

      $db_obj->beginTransaction();

      $check = $db_obj->prepare("SELECT id FROM dislab_test_listesi WHERE dislab_kodu = ? LIMIT 1");

      $setParts = [
        "dislab_id = ?",
        "dislab_adi = ?",
        "sut_kodu = ?",
        "ornek_tur_id = ?",
        "ornek_tur_adi = ?",
        "kap_id = ?",
        "kap_adi = ?",
      ];
      if ($has_test_tipi) $setParts[] = "test_tipi = COALESCE(test_tipi, 'Ana Test')";
      if ($has_parent_id) $setParts[] = "parent_id = COALESCE(parent_id, 0)";
      if ($has_last_sync) $setParts[] = "last_sync = NOW()";

      $up = $db_obj->prepare("UPDATE dislab_test_listesi SET ".implode(", ", $setParts)." WHERE dislab_kodu = ?");

      $cols = ["dislab_id","dislab_kodu","dislab_adi","sut_kodu","ornek_tur_id","ornek_tur_adi","kap_id","kap_adi","is_active"];
      $vals = ["?","?","?","?","?","?","?","?","1"];
      if ($has_test_tipi) { $cols[] = "test_tipi"; $vals[] = "'Ana Test'"; }
      if ($has_parent_id) { $cols[] = "parent_id"; $vals[] = "0"; }
      if ($has_last_sync) { $cols[] = "last_sync"; $vals[] = "NOW()"; }

      $ins = $db_obj->prepare("INSERT INTO dislab_test_listesi (".implode(",", $cols).") VALUES (".implode(",", $vals).")");

      foreach ($catalog as $code => $row) {
        $check->execute([$code]);
        $exists = $check->fetch(PDO::FETCH_ASSOC);

        if ($exists) {
          $up->execute([
            $row['dislab_id'],
            $row['dislab_adi'],
            $row['sut_kodu'],
            $row['ornek_tur_id'],
            $row['ornek_tur_adi'],
            $row['kap_id'],
            $row['kap_adi'],
            $code
          ]);
          $stats['updated']++;
        } else {
          $ins->execute([
            $row['dislab_id'],
            $row['dislab_kodu'],
            $row['dislab_adi'],
            $row['sut_kodu'],
            $row['ornek_tur_id'],
            $row['ornek_tur_adi'],
            $row['kap_id'],
            $row['kap_adi'],
          ]);
          $stats['added']++;
        }
      }

      $db_obj->commit();
      json_out(['success' => true, 'stats' => $stats]);
    }

    // --- FETCH LIST (TABLE + CARDS) ---
    if ($action === 'fetch_list') {
      $q = trim((string)($_GET['q'] ?? ''));
      $only = (string)($_GET['only'] ?? 'all'); // all|active|passive
      $limit = (int)($_GET['limit'] ?? 120);
      $limit = max(20, min(200, $limit));

      $where = " WHERE 1=1 ";
      $params = [];

      // ✅ HY093 FIX: aynı named param'ı tekrar kullanmıyoruz
      if ($q !== '') {
        $where .= " AND (dislab_adi LIKE :q1 OR dislab_kodu LIKE :q2 OR sut_kodu LIKE :q3) ";
        $params[':q1'] = "%{$q}%";
        $params[':q2'] = "%{$q}%";
        $params[':q3'] = "%{$q}%";
      }

      if ($only === 'active') $where .= " AND is_active = 1 ";
      if ($only === 'passive') $where .= " AND is_active = 0 ";

      $has_last_sync = has_col($db_obj,'dislab_test_listesi','last_sync');

      $sql = "SELECT id, dislab_id, dislab_kodu, dislab_adi, sut_kodu, ornek_tur_id, ornek_tur_adi, kap_id, kap_adi, is_active"
           . ($has_last_sync ? ", last_sync" : "")
           . " FROM dislab_test_listesi {$where}
              ORDER BY is_active DESC, dislab_adi ASC
              LIMIT {$limit}";

      $stmt = $db_obj->prepare($sql);
      foreach ($params as $k => $v) $stmt->bindValue($k, $v);
      $stmt->execute();
      $tests = $stmt->fetchAll(PDO::FETCH_ASSOC);

      $total = (int)$db_obj->query("SELECT COUNT(*) FROM dislab_test_listesi")->fetchColumn();
      $active = (int)$db_obj->query("SELECT COUNT(*) FROM dislab_test_listesi WHERE is_active=1")->fetchColumn();

      /* ---- Desktop Table HTML ---- */
      ob_start();
      if (!$tests) {
        echo '<tr><td colspan="7" class="text-center py-5 text-muted">Kayıt bulunamadı.</td></tr>';
      } else {
        foreach ($tests as $t) {
          $id = (int)$t['id'];
          $isActive = ((int)$t['is_active'] === 1);
          $last = isset($t['last_sync']) ? (string)$t['last_sync'] : '';
          ?>
          <tr>
            <td class="text-center ps-3">
              <input class="form-check-input rowCheck" type="checkbox" value="<?= $id ?>">
            </td>

            <td class="ps-2">
              <div class="fw-semibold"><?= h($t['dislab_adi']) ?></div>
              <div class="text-muted small">
                <span class="me-2">ID: <?= h((string)$t['dislab_id']) ?></span>
                <?php if ($last): ?>
                  <span class="badge text-bg-light border">Son Sync: <?= h($last) ?></span>
                <?php endif; ?>
              </div>
            </td>

            <td class="text-center fw-semibold"><?= h($t['dislab_kodu']) ?></td>

            <td class="text-center">
              <div class="small fw-semibold"><?= h($t['ornek_tur_adi']) ?> <span class="text-muted">(<?= h((string)$t['ornek_tur_id']) ?>)</span></div>
              <div class="small text-muted"><?= h($t['kap_adi']) ?> <span class="text-muted">(<?= h((string)$t['kap_id']) ?>)</span></div>
            </td>

            <td class="text-center fw-semibold text-primary"><?= h((string)$t['sut_kodu']) ?></td>

            <td class="text-center">
              <?php if ($isActive): ?>
                <span class="badge rounded-pill text-bg-success px-3 py-2">AKTİF</span>
              <?php else: ?>
                <span class="badge rounded-pill text-bg-secondary px-3 py-2">PASİF</span>
              <?php endif; ?>
            </td>

            <td class="text-end pe-3">
              <button
                class="btn btn-sm btn-outline-primary me-1 btnEdit"
                data-id="<?= $id ?>"
                data-dislab_adi="<?= h((string)$t['dislab_adi']) ?>"
                data-dislab_kodu="<?= h((string)$t['dislab_kodu']) ?>"
                data-sut_kodu="<?= h((string)$t['sut_kodu']) ?>"
                data-ornek_tur_id="<?= h((string)$t['ornek_tur_id']) ?>"
                data-ornek_tur_adi="<?= h((string)$t['ornek_tur_adi']) ?>"
                data-kap_id="<?= h((string)$t['kap_id']) ?>"
                data-kap_adi="<?= h((string)$t['kap_adi']) ?>"
                data-is_active="<?= (int)$t['is_active'] ?>"
              >
                <i class="bi bi-pencil-square me-1"></i>Düzenle
              </button>

              <button class="btn btn-sm btn-outline-danger btnSingleDelete" data-id="<?= $id ?>">
                <i class="bi bi-trash3 me-1"></i>Sil
              </button>
            </td>
          </tr>
          <?php
        }
      }
      $html_table = ob_get_clean();

      /* ---- Mobile Cards HTML (FIXED LAYOUT) ---- */
      ob_start();
      if (!$tests) {
        echo '<div class="text-center py-5 text-muted">Kayıt bulunamadı.</div>';
      } else {
        foreach ($tests as $t) {
          $id = (int)$t['id'];
          $isActive = ((int)$t['is_active'] === 1);
          $last = isset($t['last_sync']) ? (string)$t['last_sync'] : '';
          ?>
          <div class="card m-card mb-3">
            <div class="card-body p-3">

              <div class="m-head">
                <input class="form-check-input rowCheck mt-1" type="checkbox" value="<?= $id ?>" aria-label="Seç">

                <div class="m-text">
                  <div class="m-title"><?= h($t['dislab_adi']) ?></div>

                  <div class="m-meta">
                    Kod: <b><?= h($t['dislab_kodu']) ?></b>
                    <?php if (!empty($t['sut_kodu'])): ?>
                      • SUT: <b class="text-primary"><?= h((string)$t['sut_kodu']) ?></b>
                    <?php endif; ?>
                  </div>

                  <?php if ($last): ?>
                    <div class="mt-2">
                      <span class="badge text-bg-light border">Son Sync: <?= h($last) ?></span>
                    </div>
                  <?php endif; ?>
                </div>

                <span class="badge m-pill <?= $isActive ? 'text-bg-success' : 'text-bg-secondary' ?>">
                  <?= $isActive ? 'AKTİF' : 'PASİF' ?>
                </span>
              </div>

              <div class="mt-3 m-kv">
                <div><b>Örnek:</b> <?= h($t['ornek_tur_adi']) ?> <span class="text-muted">(<?= h((string)$t['ornek_tur_id']) ?>)</span></div>
                <div><b>Kap:</b> <?= h($t['kap_adi']) ?> <span class="text-muted">(<?= h((string)$t['kap_id']) ?>)</span></div>
              </div>

              <div class="mt-3 m-actions">
                <button
                  class="btn btn-outline-primary btnEdit"
                  data-id="<?= $id ?>"
                  data-dislab_adi="<?= h((string)$t['dislab_adi']) ?>"
                  data-dislab_kodu="<?= h((string)$t['dislab_kodu']) ?>"
                  data-sut_kodu="<?= h((string)$t['sut_kodu']) ?>"
                  data-ornek_tur_id="<?= h((string)$t['ornek_tur_id']) ?>"
                  data-ornek_tur_adi="<?= h((string)$t['ornek_tur_adi']) ?>"
                  data-kap_id="<?= h((string)$t['kap_id']) ?>"
                  data-kap_adi="<?= h((string)$t['kap_adi']) ?>"
                  data-is_active="<?= (int)$t['is_active'] ?>"
                >
                  <i class="bi bi-pencil-square me-1"></i>Düzenle
                </button>

                <button class="btn btn-outline-danger btnSingleDelete" data-id="<?= $id ?>">
                  <i class="bi bi-trash3 me-1"></i>Sil
                </button>
              </div>

            </div>
          </div>
          <?php
        }
      }
      $html_cards = ob_get_clean();

      json_out([
        'success' => true,
        'html_table' => $html_table,
        'html_cards' => $html_cards,
        'summary' => ['total' => $total, 'active' => $active, 'shown' => count($tests)]
      ]);
    }

    // --- BULK DELETE ---
    if ($action === 'bulk_delete') {
      if ($_SERVER['REQUEST_METHOD'] !== 'POST') json_out(['success'=>false,'error'=>'POST gerekli.']);

      $ids = $payload['ids'] ?? [];
      if (!is_array($ids) || !$ids) json_out(['success'=>false,'error'=>'ID listesi boş.']);

      $ids = array_values(array_unique(array_map('intval', $ids)));
      $ids = array_filter($ids, fn($x) => $x > 0);
      if (!$ids) json_out(['success'=>false,'error'=>'Geçerli ID yok.']);

      $ph = implode(',', array_fill(0, count($ids), '?'));
      $st = $db_obj->prepare("DELETE FROM dislab_test_listesi WHERE id IN ($ph)");
      $st->execute($ids);

      json_out(['success'=>true,'deleted'=>(int)$st->rowCount()]);
    }

    // --- BULK ACTIVE/PASSIVE ---
    if ($action === 'bulk_set_active') {
      if ($_SERVER['REQUEST_METHOD'] !== 'POST') json_out(['success'=>false,'error'=>'POST gerekli.']);

      $ids = $payload['ids'] ?? [];
      $state = isset($payload['state']) ? (int)$payload['state'] : 1;

      $ids = is_array($ids) ? $ids : [];
      $ids = array_values(array_unique(array_map('intval', $ids)));
      $ids = array_filter($ids, fn($x) => $x > 0);
      if (!$ids) json_out(['success'=>false,'error'=>'Geçerli ID yok.']);

      $state = $state ? 1 : 0;

      $ph = implode(',', array_fill(0, count($ids), '?'));
      $st = $db_obj->prepare("UPDATE dislab_test_listesi SET is_active = ? WHERE id IN ($ph)");
      $st->execute(array_merge([$state], $ids));

      json_out(['success'=>true,'updated'=>(int)$st->rowCount(), 'state'=>$state]);
    }

    // --- UPDATE ONE (modal save) ---
    if ($action === 'update_one') {
      if ($_SERVER['REQUEST_METHOD'] !== 'POST') json_out(['success'=>false,'error'=>'POST gerekli.']);

      $id = (int)($payload['id'] ?? 0);
      if ($id <= 0) json_out(['success'=>false,'error'=>'ID geçersiz.']);

      $dislab_adi = trim((string)($payload['dislab_adi'] ?? ''));
      $sut_kodu = trim((string)($payload['sut_kodu'] ?? ''));
      $ornek_tur_adi = trim((string)($payload['ornek_tur_adi'] ?? ''));
      $ornek_tur_id = trim((string)($payload['ornek_tur_id'] ?? ''));
      $kap_adi = trim((string)($payload['kap_adi'] ?? ''));
      $kap_id = trim((string)($payload['kap_id'] ?? ''));
      $is_active = (int)($payload['is_active'] ?? 1) ? 1 : 0;

      $set = [
        "dislab_adi = ?",
        "sut_kodu = ?",
        "ornek_tur_adi = ?",
        "ornek_tur_id = ?",
        "kap_adi = ?",
        "kap_id = ?",
        "is_active = ?",
      ];

      $st = $db_obj->prepare("UPDATE dislab_test_listesi SET ".implode(", ", $set)." WHERE id = ? LIMIT 1");
      $st->execute([$dislab_adi,$sut_kodu,$ornek_tur_adi,$ornek_tur_id,$kap_adi,$kap_id,$is_active,$id]);

      json_out(['success'=>true, 'updated'=>(int)$st->rowCount()]);
    }

    // --- RESYNC SELECTED (WS -> only selected rows) ---
    if ($action === 'resync_selected') {
      if ($_SERVER['REQUEST_METHOD'] !== 'POST') json_out(['success'=>false,'error'=>'POST gerekli.']);

      $ids = $payload['ids'] ?? [];
      $ids = is_array($ids) ? $ids : [];
      $ids = array_values(array_unique(array_map('intval', $ids)));
      $ids = array_filter($ids, fn($x) => $x > 0);
      if (!$ids) json_out(['success'=>false,'error'=>'Geçerli ID yok.']);

      $ph = implode(',', array_fill(0, count($ids), '?'));
      $st = $db_obj->prepare("SELECT id, dislab_kodu FROM dislab_test_listesi WHERE id IN ($ph)");
      $st->execute($ids);
      $rows = $st->fetchAll(PDO::FETCH_ASSOC);

      if (!$rows) json_out(['success'=>false,'error'=>'Seçili kayıtlar bulunamadı.']);

      $codes = [];
      foreach ($rows as $r) $codes[] = (string)$r['dislab_kodu'];

      $catalog = dislab_fetch_catalog($db_obj, (array)$conf);

      $has_last_sync = has_col($db_obj,'dislab_test_listesi','last_sync');

      $setParts = [
        "dislab_id = ?",
        "dislab_adi = ?",
        "sut_kodu = ?",
        "ornek_tur_id = ?",
        "ornek_tur_adi = ?",
        "kap_id = ?",
        "kap_adi = ?",
      ];
      if ($has_last_sync) $setParts[] = "last_sync = NOW()";

      $up = $db_obj->prepare("UPDATE dislab_test_listesi SET ".implode(", ", $setParts)." WHERE dislab_kodu = ?");

      $updated = 0;
      $not_found = 0;

      $db_obj->beginTransaction();
      foreach ($codes as $code) {
        if (!isset($catalog[$code])) { $not_found++; continue; }
        $row = $catalog[$code];

        $up->execute([
          $row['dislab_id'],
          $row['dislab_adi'],
          $row['sut_kodu'],
          $row['ornek_tur_id'],
          $row['ornek_tur_adi'],
          $row['kap_id'],
          $row['kap_adi'],
          $code
        ]);
        $updated += (int)$up->rowCount();
      }
      $db_obj->commit();

      json_out(['success'=>true, 'updated'=>$updated, 'not_found_in_ws'=>$not_found]);
    }

    json_out(['success'=>false,'error'=>'Bilinmeyen action.']);
  } catch (Throwable $e) {
    if ($db_obj instanceof PDO && $db_obj->inTransaction()) $db_obj->rollBack();
    json_out(['success'=>false,'error'=>$e->getMessage()]);
  }
}

/* ---------------------------------------------------------
   6) Sayfa (UI)
------------------------------------------------------------ */
$total = (int)$db_obj->query("SELECT COUNT(*) FROM dislab_test_listesi")->fetchColumn();
$active = (int)$db_obj->query("SELECT COUNT(*) FROM dislab_test_listesi WHERE is_active=1")->fetchColumn();
?>
<!doctype html>
<html lang="tr">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Dışlab Hizmet Kataloğu</title>

  <link href="https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:wght@400;600;700;800&display=swap" rel="stylesheet">
  <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
  <link href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.css" rel="stylesheet">

  <style>
    :root{
      --bg:#f6f8fc;
      --card:#ffffff;
      --text:#0f172a;
      --muted:#64748b;
      --line:#e5e7eb;
      --pri:#4361ee;
      --pri2:#3a56d4;
    }
    body{ font-family:'Plus Jakarta Sans',system-ui,-apple-system,Segoe UI,Roboto,Arial; background:var(--bg); color:var(--text); }
    .wrap{ padding:18px; }
    .hero{
      background: linear-gradient(135deg, rgba(67,97,238,.10), rgba(67,97,238,.04));
      border:1px solid rgba(67,97,238,.18);
      border-radius:16px;
      padding:16px;
    }
    .cardx{
      background:var(--card);
      border:1px solid var(--line);
      border-radius:16px;
      box-shadow: 0 6px 18px rgba(15,23,42,.06);
      overflow:hidden;
    }
    .search{
      border:2px solid #dbe2ee;
      border-radius:12px;
      padding:12px 44px 12px 44px;
      width:100%;
      outline:none;
      transition:.15s;
      background:#fff;
    }
    .search:focus{ border-color: var(--pri); box-shadow: 0 0 0 .2rem rgba(67,97,238,.10); }
    .btn-pri{
      background:var(--pri);
      border-color:var(--pri);
      font-weight:800;
      border-radius:12px;
      padding:10px 14px;
    }
    .btn-pri:hover{ background:var(--pri2); border-color:var(--pri2); }
    .toolbar{
      display:flex;
      gap:10px;
      flex-wrap:wrap;
      align-items:center;
      justify-content:space-between;
    }
    .chip{
      display:inline-flex;
      align-items:center;
      gap:8px;
      border:1px solid var(--line);
      background:#fff;
      border-radius:999px;
      padding:8px 12px;
      color:var(--muted);
      font-weight:700;
      font-size:13px;
    }
    .chip b{ color:var(--text); }
    .table thead th{
      background:#f8fafc;
      color:#64748b;
      font-size:12px;
      letter-spacing:.04em;
      text-transform:uppercase;
      border-bottom:1px solid var(--line);
      padding:12px;
    }
    .table tbody td{ border-bottom:1px solid #eef2f7; padding:12px; vertical-align:middle; }
    .muted{ color:var(--muted); }
    #overlay{
      position:fixed; inset:0;
      display:none;
      align-items:center; justify-content:center;
      background:rgba(255,255,255,.88);
      z-index:9999;
      backdrop-filter: blur(3px);
    }
    .ov-card{
      width:min(520px, 92vw);
      background:#fff;
      border:1px solid var(--line);
      border-radius:16px;
      padding:18px;
      box-shadow:0 18px 60px rgba(15,23,42,.18);
    }
    .ov-title{ font-weight:900; font-size:18px; }
    .ov-sub{ color:var(--muted); margin-top:4px; }
    .countSelected{ font-weight:900; color:var(--pri); }
    @media (max-width: 768px){
      .toolbar{ gap:12px; }
      #btnSync{ width:100%; }
    }

    /* -------------------------------------------------
       MOBILE CARD FIX (SAÇMA TAŞMA BİTTİ)
    -------------------------------------------------- */
    .m-card{
      border-radius:16px;
      border:1px solid var(--line);
      overflow: visible;
    }
    .m-head{
      display:flex;
      align-items:flex-start;
      gap:12px;
    }
    .m-head .m-text{
      flex:1 1 auto;
      min-width:0; /* taşmayı bitiren ana sihir */
    }
    .m-title{
      font-weight:900;
      font-size:16px;
      line-height:1.2;
      margin-bottom:4px;

      display:-webkit-box;
      -webkit-line-clamp:2;
      -webkit-box-orient:vertical;
      overflow:hidden;
    }
    .m-meta{ font-size:13px; color:#6b7280; }
    .m-pill{
      flex:0 0 auto;
      white-space:nowrap;
      border-radius:999px;
      padding:8px 12px;
    }
    .m-kv{ font-size:13px; color:#6b7280; }
    .m-kv b{ color:#0f172a; }
    .m-actions{
      display:grid;
      grid-template-columns: 1fr 1fr;
      gap:10px;
    }
    .m-actions .btn{
      width:100%;
      border-radius:12px;
      padding:10px 12px;
      font-weight:800;
    }
  </style>
</head>

<body>
<div id="overlay">
  <div class="ov-card">
    <div class="d-flex align-items-center gap-3">
      <div class="spinner-border" role="status" aria-hidden="true"></div>
      <div>
        <div class="ov-title" id="ovTitle">Yükleniyor…</div>
        <div class="ov-sub" id="ovSub">Lütfen bekleyin.</div>
      </div>
    </div>
    <div class="progress mt-3" style="height:10px;">
      <div class="progress-bar progress-bar-striped progress-bar-animated" style="width:100%"></div>
    </div>
  </div>
</div>

<div class="wrap container-fluid">

  <div class="hero mb-3">
    <div class="toolbar">
      <div>
        <div class="fw-black fs-4" style="font-weight:900;">Hizmet Kataloğu Yönetimi</div>
        <div class="muted">Arama, çoklu işlem, düzenleme ve senkronizasyon tek ekranda.</div>
        <div class="mt-2 d-flex gap-2 flex-wrap">
          <span class="chip"><i class="bi bi-database-check"></i> Toplam: <b id="sumTotal"><?= (int)$total ?></b></span>
          <span class="chip"><i class="bi bi-check-circle"></i> Aktif: <b id="sumActive"><?= (int)$active ?></b></span>
          <span class="chip"><i class="bi bi-list-check"></i> Seçili: <b class="countSelected" id="selCount">0</b></span>
        </div>
      </div>

      <div class="d-flex gap-2 flex-wrap justify-content-end">
        <button class="btn btn-pri text-white" id="btnSync">
          <i class="bi bi-arrow-repeat me-1"></i> Kataloğu Güncelle (WS)
        </button>
      </div>
    </div>
  </div>

  <div class="cardx">
    <div class="p-3 border-bottom" style="background:#fbfcff;">
      <div class="row g-2 align-items-center">
        <div class="col-lg-6">
          <div class="position-relative">
            <i class="bi bi-search position-absolute top-50 translate-middle-y ms-3 muted fs-5"></i>
            <input type="text" id="searchInput" class="search" placeholder="Hemen ara: Test adı, Kod veya SUT kodu...">
          </div>
        </div>
        <div class="col-lg-6 d-flex gap-2 justify-content-lg-end flex-wrap">
          <select id="onlySelect" class="form-select" style="max-width:220px; border-radius:12px;">
            <option value="all">Tümü</option>
            <option value="active">Sadece Aktif</option>
            <option value="passive">Sadece Pasif</option>
          </select>

          <button class="btn btn-outline-secondary" id="btnRefresh" style="border-radius:12px;">
            <i class="bi bi-arrow-clockwise me-1"></i> Yenile
          </button>

          <button class="btn btn-outline-primary" id="btnResyncSelected" disabled style="border-radius:12px;">
            <i class="bi bi-cloud-download me-1"></i> Seçileni Yeniden Sync
          </button>

          <button class="btn btn-outline-success" id="btnSetActive" disabled style="border-radius:12px;">
            <i class="bi bi-check2-circle me-1"></i> Aktif Yap
          </button>

          <button class="btn btn-outline-warning" id="btnSetPassive" disabled style="border-radius:12px;">
            <i class="bi bi-slash-circle me-1"></i> Pasif Yap
          </button>

          <button class="btn btn-outline-danger" id="btnDeleteSelected" disabled style="border-radius:12px;">
            <i class="bi bi-trash3 me-1"></i> Seçileni Sil
          </button>
        </div>
      </div>
    </div>

    <!-- DESKTOP TABLE -->
    <div class="table-responsive d-none d-md-block">
      <table class="table align-middle mb-0">
        <thead>
          <tr>
            <th class="text-center" style="width:44px;">
              <input class="form-check-input" id="checkAll" type="checkbox">
            </th>
            <th>Test</th>
            <th class="text-center" style="width:140px;">Kod</th>
            <th class="text-center" style="width:260px;">Örnek / Kap</th>
            <th class="text-center" style="width:140px;">SUT</th>
            <th class="text-center" style="width:120px;">Durum</th>
            <th class="text-end" style="width:240px;">İşlemler</th>
          </tr>
        </thead>
        <tbody id="tableBody">
          <tr><td colspan="7" class="text-center py-5 muted">Veriler yükleniyor…</td></tr>
        </tbody>
      </table>
    </div>

    <!-- MOBILE CARDS -->
    <div class="d-md-none p-3" id="cardBody">
      <div class="text-center py-5 muted">Veriler yükleniyor…</div>
    </div>

  </div>
</div>

<!-- Edit Modal -->
<div class="modal fade" id="editModal" tabindex="-1" aria-hidden="true">
  <div class="modal-dialog modal-lg modal-dialog-centered">
    <div class="modal-content" style="border-radius:16px;">
      <div class="modal-header">
        <h5 class="modal-title fw-bold"><i class="bi bi-pencil-square me-2"></i>Test Düzenle</h5>
        <button type="button" class="btn-close" data-bs-dismiss="modal"></button>
      </div>

      <div class="modal-body">
        <input type="hidden" id="e_id">

        <div class="row g-3">
          <div class="col-md-8">
            <label class="form-label small muted">Test Adı</label>
            <input type="text" class="form-control" id="e_dislab_adi" style="border-radius:12px;">
          </div>
          <div class="col-md-4">
            <label class="form-label small muted">Durum</label>
            <select class="form-select" id="e_is_active" style="border-radius:12px;">
              <option value="1">Aktif</option>
              <option value="0">Pasif</option>
            </select>
          </div>

          <div class="col-md-4">
            <label class="form-label small muted">SUT Kodu</label>
            <input type="text" class="form-control" id="e_sut_kodu" style="border-radius:12px;">
          </div>
          <div class="col-md-4">
            <label class="form-label small muted">Örnek Tür ID</label>
            <input type="text" class="form-control" id="e_ornek_tur_id" style="border-radius:12px;">
          </div>
          <div class="col-md-4">
            <label class="form-label small muted">Kap ID</label>
            <input type="text" class="form-control" id="e_kap_id" style="border-radius:12px;">
          </div>

          <div class="col-md-6">
            <label class="form-label small muted">Örnek Tür Adı</label>
            <input type="text" class="form-control" id="e_ornek_tur_adi" style="border-radius:12px;">
          </div>
          <div class="col-md-6">
            <label class="form-label small muted">Kap Adı</label>
            <input type="text" class="form-control" id="e_kap_adi" style="border-radius:12px;">
          </div>

          <div class="col-12">
            <div class="alert alert-info mb-0" style="border-radius:14px;">
              <i class="bi bi-info-circle me-2"></i>
              Bu düzenleme lokal katalog içindir. “Yeniden Sync” yaparsan web servisten gelen değerler tekrar üzerine yazılabilir.
            </div>
          </div>
        </div>
      </div>

      <div class="modal-footer">
        <button class="btn btn-outline-secondary" data-bs-dismiss="modal" style="border-radius:12px;">Vazgeç</button>
        <button class="btn btn-pri text-white" id="btnSaveEdit">
          <i class="bi bi-check2 me-1"></i> Kaydet
        </button>
      </div>
    </div>
  </div>
</div>

<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
<script>
  // dashboard.php içinde include ediyorsan burayı kendi yoluna göre ayarla:
  const apiPath = 'modules/dislab-sync.php';

  const overlay = document.getElementById('overlay');
  const ovTitle = document.getElementById('ovTitle');
  const ovSub = document.getElementById('ovSub');

  const tableBody = document.getElementById('tableBody');
  const cardBody  = document.getElementById('cardBody');

  const searchInput = document.getElementById('searchInput');
  const onlySelect = document.getElementById('onlySelect');
  const checkAll = document.getElementById('checkAll');

  const btnDeleteSelected = document.getElementById('btnDeleteSelected');
  const btnSetActive = document.getElementById('btnSetActive');
  const btnSetPassive = document.getElementById('btnSetPassive');
  const btnResyncSelected = document.getElementById('btnResyncSelected');

  const sumTotal = document.getElementById('sumTotal');
  const sumActive = document.getElementById('sumActive');
  const selCount = document.getElementById('selCount');

  const editModalEl = document.getElementById('editModal');
  const editModal = new bootstrap.Modal(editModalEl);

  let selected = new Set();
  let tmr = null;

  function showOverlay(title, sub){
    ovTitle.textContent = title || 'Yükleniyor…';
    ovSub.textContent = sub || 'Lütfen bekleyin.';
    overlay.style.display = 'flex';
  }
  function hideOverlay(){ overlay.style.display = 'none'; }

  function getSelectedIds(){ return Array.from(selected); }

  function updateToolbar(){
    const n = selected.size;
    selCount.textContent = n;
    const en = n > 0;
    btnDeleteSelected.disabled = !en;
    btnSetActive.disabled = !en;
    btnSetPassive.disabled = !en;
    btnResyncSelected.disabled = !en;
  }

  function debounceLoad(){
    if (tmr) clearTimeout(tmr);
    tmr = setTimeout(loadTable, 220);
  }

  function syncCheckAllState(){
    const checks = Array.from(tableBody.querySelectorAll('.rowCheck'));
    if (!checks.length){ checkAll.checked = false; checkAll.indeterminate = false; return; }
    const checkedCount = checks.filter(x => x.checked).length;
    checkAll.checked = checkedCount === checks.length;
    checkAll.indeterminate = checkedCount > 0 && checkedCount < checks.length;
  }

  async function postJSON(action, body){
    const res = await fetch(apiPath + '?action=' + action, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify(body || {})
    });
    return await res.json();
  }

  function applySelectedCheckboxes(){
    [tableBody, cardBody].forEach(container => {
      container.querySelectorAll('.rowCheck').forEach(ch => {
        const id = parseInt(ch.value, 10);
        ch.checked = selected.has(id);
      });
    });
    syncCheckAllState();
    updateToolbar();
  }

  function loadTable(){
    const q = searchInput.value || '';
    const only = onlySelect.value || 'all';

    showOverlay('Liste yükleniyor…', 'Kayıtlar filtreleniyor ve ekrana hazırlanıyor.');
    fetch(apiPath + '?action=fetch_list&only=' + encodeURIComponent(only) + '&q=' + encodeURIComponent(q) + '&limit=120')
      .then(r => r.json())
      .then(d => {
        if(!d.success) throw new Error(d.error || 'Liste alınamadı');

        tableBody.innerHTML = d.html_table || '<tr><td colspan="7" class="text-center py-5 text-muted">Boş.</td></tr>';
        cardBody.innerHTML  = d.html_cards || '<div class="text-center py-5 text-muted">Boş.</div>';

        if (d.summary){
          sumTotal.textContent = d.summary.total ?? sumTotal.textContent;
          sumActive.textContent = d.summary.active ?? sumActive.textContent;
        }

        applySelectedCheckboxes();
      })
      .catch(err => {
        console.error(err);
        tableBody.innerHTML = '<tr><td colspan="7" class="text-center py-5 text-danger">Listeleme hatası: ' + (err.message || err) + '</td></tr>';
        cardBody.innerHTML  = '<div class="text-center py-5 text-danger">Listeleme hatası: ' + (err.message || err) + '</div>';
      })
      .finally(hideOverlay);
  }

  searchInput.addEventListener('input', debounceLoad);
  onlySelect.addEventListener('change', () => {
    selected.clear();
    updateToolbar();
    checkAll.checked=false; checkAll.indeterminate=false;
    loadTable();
  });
  document.getElementById('btnRefresh').addEventListener('click', () => loadTable());

  // Select all (desktop)
  checkAll.addEventListener('change', () => {
    const want = checkAll.checked;
    tableBody.querySelectorAll('.rowCheck').forEach(ch => {
      ch.checked = want;
      const id = parseInt(ch.value, 10);
      if (want) selected.add(id); else selected.delete(id);
    });
    // karttaki checkboxları da eşitle
    document.querySelectorAll('#cardBody .rowCheck').forEach(ch => {
      const id = parseInt(ch.value, 10);
      ch.checked = selected.has(id);
    });
    syncCheckAllState();
    updateToolbar();
  });

  // checkbox change (both)
  function handleCheckChange(e){
    if (!e.target.classList.contains('rowCheck')) return;
    const id = parseInt(e.target.value, 10);
    if (e.target.checked) selected.add(id); else selected.delete(id);

    // aynı id'li checkboxları her iki tarafta eşitle
    document.querySelectorAll('.rowCheck[value="'+id+'"]').forEach(x => { x.checked = e.target.checked; });

    syncCheckAllState();
    updateToolbar();
  }
  tableBody.addEventListener('change', handleCheckChange);
  cardBody.addEventListener('change', handleCheckChange);

  // edit/delete click handler (both)
  async function handleRowButtons(e){
    const btnEdit = e.target.closest('.btnEdit');
    const btnDel  = e.target.closest('.btnSingleDelete');

    if (btnEdit){
      document.getElementById('e_id').value = btnEdit.dataset.id || '';
      document.getElementById('e_dislab_adi').value = btnEdit.dataset.dislab_adi || '';
      document.getElementById('e_sut_kodu').value = btnEdit.dataset.sut_kodu || '';
      document.getElementById('e_ornek_tur_id').value = btnEdit.dataset.ornek_tur_id || '';
      document.getElementById('e_ornek_tur_adi').value = btnEdit.dataset.ornek_tur_adi || '';
      document.getElementById('e_kap_id').value = btnEdit.dataset.kap_id || '';
      document.getElementById('e_kap_adi').value = btnEdit.dataset.kap_adi || '';
      document.getElementById('e_is_active').value = btnEdit.dataset.is_active || '1';
      editModal.show();
      return;
    }

    if (btnDel){
      const id = parseInt(btnDel.dataset.id, 10);
      if (!confirm('Bu kaydı silmek istiyor musun?')) return;

      showOverlay('Siliniyor…', 'Seçili kayıt veritabanından kaldırılıyor.');
      try{
        const d = await postJSON('bulk_delete', { ids:[id] });
        if(!d.success) throw new Error(d.error || 'Silme başarısız');
        selected.delete(id);
        updateToolbar();
        loadTable();
      }catch(err){
        alert('Hata: ' + (err.message || err));
      }finally{
        hideOverlay();
      }
    }
  }
  tableBody.addEventListener('click', handleRowButtons);
  cardBody.addEventListener('click', handleRowButtons);

  // Save edit
  document.getElementById('btnSaveEdit').addEventListener('click', async () => {
    const body = {
      id: parseInt(document.getElementById('e_id').value, 10),
      dislab_adi: document.getElementById('e_dislab_adi').value,
      sut_kodu: document.getElementById('e_sut_kodu').value,
      ornek_tur_id: document.getElementById('e_ornek_tur_id').value,
      ornek_tur_adi: document.getElementById('e_ornek_tur_adi').value,
      kap_id: document.getElementById('e_kap_id').value,
      kap_adi: document.getElementById('e_kap_adi').value,
      is_active: parseInt(document.getElementById('e_is_active').value, 10)
    };

    showOverlay('Kaydediliyor…', 'Değişiklikler veritabanına yazılıyor.');
    try{
      const d = await postJSON('update_one', body);
      if(!d.success) throw new Error(d.error || 'Kaydetme başarısız');
      editModal.hide();
      loadTable();
    }catch(err){
      alert('Hata: ' + (err.message || err));
    }finally{
      hideOverlay();
    }
  });

  // Bulk actions
  btnDeleteSelected.addEventListener('click', async () => {
    const ids = getSelectedIds();
    if(!ids.length) return;
    if(!confirm(ids.length + ' kayıt silinecek. Emin misin?')) return;

    showOverlay('Toplu silme…', 'Seçilen kayıtlar kaldırılıyor.');
    try{
      const d = await postJSON('bulk_delete', { ids });
      if(!d.success) throw new Error(d.error || 'Silme başarısız');
      selected.clear();
      updateToolbar();
      loadTable();
    }catch(err){
      alert('Hata: ' + (err.message || err));
    }finally{
      hideOverlay();
    }
  });

  btnSetActive.addEventListener('click', async () => {
    const ids = getSelectedIds();
    if(!ids.length) return;

    showOverlay('Güncelleniyor…', 'Seçilen kayıtlar AKTİF yapılıyor.');
    try{
      const d = await postJSON('bulk_set_active', { ids, state:1 });
      if(!d.success) throw new Error(d.error || 'İşlem başarısız');
      selected.clear();
      updateToolbar();
      loadTable();
    }catch(err){
      alert('Hata: ' + (err.message || err));
    }finally{
      hideOverlay();
    }
  });

  btnSetPassive.addEventListener('click', async () => {
    const ids = getSelectedIds();
    if(!ids.length) return;

    showOverlay('Güncelleniyor…', 'Seçilen kayıtlar PASİF yapılıyor.');
    try{
      const d = await postJSON('bulk_set_active', { ids, state:0 });
      if(!d.success) throw new Error(d.error || 'İşlem başarısız');
      selected.clear();
      updateToolbar();
      loadTable();
    }catch(err){
      alert('Hata: ' + (err.message || err));
    }finally{
      hideOverlay();
    }
  });

  btnResyncSelected.addEventListener('click', async () => {
    const ids = getSelectedIds();
    if(!ids.length) return;

    showOverlay('Web servisten veri alınıyor…', 'Seçilen kayıtlar güncelleniyor (WS).');
    try{
      const d = await postJSON('resync_selected', { ids });
      if(!d.success) throw new Error(d.error || 'Resync başarısız');

      selected.clear();
      updateToolbar();
      alert('Güncellendi: ' + d.updated + '\nWS’de bulunamayan: ' + d.not_found_in_ws);
      loadTable();
    }catch(err){
      alert('Hata: ' + (err.message || err));
    }finally{
      hideOverlay();
    }
  });

  // Sync All
  document.getElementById('btnSync').addEventListener('click', async () => {
    showOverlay('Web servisten veri alınıyor…', 'Katalog indiriliyor ve veritabanına işleniyor.');
    fetch(apiPath + '?action=sync_all')
      .then(r => r.json())
      .then(d => {
        if(!d.success) throw new Error(d.error || 'Senkronizasyon başarısız');
        alert(
          'WS Toplam: ' + d.stats.total_from_ws +
          '\nEklendi: ' + d.stats.added +
          '\nGüncellendi: ' + d.stats.updated
        );
        selected.clear();
        updateToolbar();
        loadTable();
      })
      .catch(err => alert('Hata: ' + (err.message || err)))
      .finally(hideOverlay);
  });

  document.addEventListener('DOMContentLoaded', () => {
    updateToolbar();
    loadTable();
  });
</script>
</body>
</html>
