<?php
declare(strict_types=1);

/* ---------------------------------------------------------
   1) AJAX MOTORU (STANDALONE) - ASLA BOZMA
------------------------------------------------------------ */
if (isset($_GET['action']) || isset($_POST['action'])) {
    while (ob_get_level()) { ob_end_clean(); }

    ini_set('display_errors', '0');
    ini_set('html_errors', '0');
    error_reporting(E_ALL);

    header('Content-Type: application/json; charset=utf-8');

    register_shutdown_function(function() {
        $err = error_get_last();
        if ($err && in_array($err['type'], [E_ERROR, E_PARSE, E_CORE_ERROR, E_COMPILE_ERROR], true)) {
            while (ob_get_level()) { ob_end_clean(); }
            http_response_code(500);
            header('Content-Type: application/json; charset=utf-8');
            echo json_encode([
                'success' => false,
                'error' => 'Fatal: ' . ($err['message'] ?? 'bilinmeyen hata')
            ], JSON_UNESCAPED_UNICODE);
        }
    });

    set_error_handler(function($severity, $message, $file, $line){
        throw new ErrorException($message, 0, $severity, $file, $line);
    });

    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 (file_exists($db_path)) { require_once $db_path; }
        $db_obj = is_object($db) ? $db : (is_object($conn) ? $conn : $pdo);
    }

    try {
        $q = $db_obj->query("SELECT * FROM external_laboratories WHERE status = 'active' LIMIT 1");
        $conf = $q->fetch(PDO::FETCH_ASSOC);

        if (!$conf) {
            echo json_encode(['success' => false, 'error' => 'Dışlab ayarı bulunamadı (external_laboratories).'], JSON_UNESCAPED_UNICODE);
            exit;
        }

        $pass = (string)($conf['api_password'] ?? ($conf['pass_enc'] ?? ''));
        if (isset($conf['pass_enc'])) {
            if (function_exists('crypto_decrypt')) $pass = (string)crypto_decrypt((string)$conf['pass_enc']);
            else if (function_exists('decrypt'))  $pass = (string)decrypt((string)$conf['pass_enc']);
        }

        $defaultWs = 'http://entegrasyon.biolabltd.com.tr:1080/v5/tenayservice.asmx';
        $wsUrl = trim((string)($conf['api_url'] ?? '')) ?: $defaultWs;
        $username = (string)($conf['username'] ?? '');
        $kurumKodu = (string)($conf['api_key'] ?? '');
        
        // Action kontrol
        $action = (string)($_GET['action'] ?? $_POST['action'] ?? '');

        // --- Helpers: XML/Encoding normalize (SOAP envelope / inner <Xml> / direct HastaSorguCevap)
        $nl_to_utf8 = static function(string $s): string {
            // UTF-8 BOM temizle
            $s = preg_replace('/^\xEF\xBB\xBF/', '', $s);
            if (function_exists('mb_check_encoding') && !mb_check_encoding($s, 'UTF-8')) {
                // TR servisleri bazen ISO-8859-9 / Windows-1254 dönebiliyor
                $s = mb_convert_encoding($s, 'UTF-8', 'UTF-8,ISO-8859-9,Windows-1254,ISO-8859-1');
            }
            return $s;
        };

        $nl_parse_hasta_root = static function(string $raw) use ($nl_to_utf8): ?SimpleXMLElement {
            libxml_use_internal_errors(true);
            libxml_clear_errors();
            
            $raw = trim($nl_to_utf8($raw));

            if (empty($raw)) return null;

            // Eğer XML declaration yoksa ekle
            if (strpos($raw, '<?xml') === false) {
                $raw = '<?xml version="1.0" encoding="utf-8"?>' . $raw;
            }

            // Önce DOMDocument ile yükle (SOAP envelope'ı namespace-aware parse eder)
            $dom = new DOMDocument();
            if (!$dom->loadXML($raw)) {
                libxml_clear_errors();
                return null;
            }

            // DOMXPath ile namespace-aware sorgu yap
            $xpath = new DOMXPath($dom);
            $xpath->registerNamespace('soap', 'http://schemas.xmlsoap.org/soap/envelope/');
            $xpath->registerNamespace('tn', 'http://tenay.com.tr/');

            // HastaSonucSorgulaOrnekNoResult veya HastaSonucSorgulaReferansResult ara
            $resultNodes = $xpath->query('//soap:Body/tn:HastaSonucSorgulaOrnekNoResponse/tn:HastaSonucSorgulaOrnekNoResult');
            
            if ($resultNodes->length === 0) {
                $resultNodes = $xpath->query('//soap:Body/tn:HastaSonucSorgulaReferansResponse/tn:HastaSonucSorgulaReferansResult');
            }

            if ($resultNodes->length === 0) {
                libxml_clear_errors();
                return null;
            }

            // Result node'u SimpleXML'e dönüştür
            $resultNode = $resultNodes->item(0);
            $xml = simplexml_import_dom($resultNode);
            
            libxml_clear_errors();
            return $xml;
        };

        if ($action === 'kaydet') {
            // Hasta kaydetme işlemi
            $input = json_decode(file_get_contents('php://input'), true);
            
            if (!$input) {
                echo json_encode(['success' => false, 'error' => 'Geçersiz JSON'], JSON_UNESCAPED_UNICODE);
                exit;
            }
            
            if (!class_exists('SoapClient')) {
                echo json_encode(['success' => false, 'error' => 'SOAP eklentisi yok'], JSON_UNESCAPED_UNICODE);
                exit;
            }
            
            try {
                $client = new SoapClient($wsUrl . "?WSDL", [
                    'trace' => 1,
                    'soap_version' => SOAP_1_2,
                    'exceptions' => true,
                    'cache_wsdl' => WSDL_CACHE_NONE,
                    'connection_timeout' => 15,
                ]);
            } catch (Throwable $e) {
                echo json_encode(['success' => false, 'error' => 'WSDL: ' . $e->getMessage()], JSON_UNESCAPED_UNICODE);
                exit;
            }
            
            // Test nesneleri oluştur ve haritalama yap
            $tetkikler = [];
            if (isset($input['tests']) && is_array($input['tests'])) {
                $gelisTarihi = isset($input['gelis_tarihi']) ? 
                    (new DateTime($input['gelis_tarihi']))->format('Y-m-d\TH:i:s\Z') : 
                    (new DateTime())->format('Y-m-d\TH:i:s\Z');
                
                foreach ($input['tests'] as $test) {
                    $localCode = $test['code'] ?? '';
                    $externalCode = $localCode;
                    
                    // Haritalama: DISLAB-B1098 → B1098
                    if (strpos($localCode, 'DISLAB-') === 0) {
                        $externalCode = substr($localCode, 7); // "DISLAB-" prefix'ini kaldır
                    }
                    // Veya haritalama tablosundan sor: local code'dan external service code'u bul
                    else {
                        $mapStmt = $db_obj->prepare('
                            SELECT s.service_code 
                            FROM external_lab_service_mappings m
                            LEFT JOIN external_lab_services s ON m.external_lab_service_id = s.id
                            WHERE m.local_test_code = :code LIMIT 1
                        ');
                        $mapStmt->execute([':code' => $localCode]);
                        $mapping = $mapStmt->fetch(PDO::FETCH_ASSOC);
                        if ($mapping && $mapping['service_code']) {
                            $externalCode = $mapping['service_code'];
                        }
                    }
                    
                    $tetkikler[] = [
                        'LogId' => 0,
                        'Adi' => $test['name'] ?? $test['code'] ?? '',
                        'Kodu' => $externalCode,  // Haritalanmış external code
                        'Barkod' => 0,
                        'KapId' => 0,
                        'AlindigiTarih' => $gelisTarihi
                    ];
                }
            }
            // Eski format (test_codes) uyumluluğu
            elseif (isset($input['test_codes']) && is_array($input['test_codes'])) {
                $gelisTarihi = isset($input['gelis_tarihi']) ? 
                    (new DateTime($input['gelis_tarihi']))->format('Y-m-d\TH:i:s\Z') : 
                    (new DateTime())->format('Y-m-d\TH:i:s\Z');
                
                foreach ($input['test_codes'] as $code) {
                    $tetkikler[] = [
                        'LogId' => 0,
                        'Adi' => $code,
                        'Kodu' => $code,
                        'Barkod' => 0,
                        'KapId' => 0,
                        'AlindigiTarih' => $gelisTarihi
                    ];
                }
            }
            
            // Doğum tarihi formatla
            $dogumTarihi = $input['birth_date'] ? 
                (new DateTime($input['birth_date']))->format('Y-m-d\TH:i:s\Z') : 
                '1990-01-01T00:00:00Z';
            
            $gelisTarihi = isset($input['gelis_tarihi']) ? 
                (new DateTime($input['gelis_tarihi']))->format('Y-m-d\TH:i:s\Z') : 
                (new DateTime())->format('Y-m-d\TH:i:s\Z');
            
            // SOAP parametreleri
            $params = [
                'order' => [
                    'Adi' => (string)($input['first_name'] ?? ''),
                    'Soyadi' => (string)($input['last_name'] ?? ''),
                    'KimlikNo' => (string)($input['national_id'] ?? ''),
                    'OrnekNo' => 0,
                    'BabaAdi' => '',
                    'AnneAdi' => '',
                    'DogumTarihi' => $dogumTarihi,
                    'Cinsiyeti' => in_array($input['gender'] ?? 'Erkek', ['Erkek', 'Kadın']) ? $input['gender'] : 'Erkek',
                    'DosyaNo' => (string)($input['dosya_no'] ?? (string)($input['patient_id'] ?? '')),
                    'KurumBilgileri' => [
                        'WebUserKurumId' => 0,
                        'KullaniciAdi' => (string)($conf['username'] ?? ''),
                        'Sifre' => $pass,
                        'Kodu' => $kurumKodu
                    ],
                    'Gelis' => [
                        'ReferansNo' => 0,
                        'OrnekNo' => 0,
                        'Tarih' => $gelisTarihi,
                        'GelisTipi' => (string)($input['gelis_tipi'] ?? 'DiyalizGiris'),
                        'Tetkikler' => $tetkikler
                    ]
                ]
            ];
            
            try {
                $result = $client->HastaKaydet($params);
                
                if (!$result || !isset($result->HastaKaydetResult->ReferansId)) {
                    throw new Exception('Referans ID alınamadı');
                }
                
                $referansId = (int)$result->HastaKaydetResult->ReferansId;
                
                // Gelen SOAP response'ı XML'e çevir
                $responseXml = '';
                try {
                    $responseXml = $client->__getLastResponse();
                } catch (Throwable $e) {
                    $responseXml = 'XML alınamadı: ' . $e->getMessage();
                }
                
                // Kayıtı veritabanına kaydet
                $stmt = $db_obj->prepare('
                    INSERT INTO dislab_records 
                    (patient_id, first_name, last_name, national_id, dosya_no, referans_id, gelis_tarihi, gelis_tipi, status, response_xml)
                    VALUES (:pid, :fname, :lname, :nid, :dosya, :ref, :tarih, :gtipi, "sent", :xml)
                ');
                
                $stmt->execute([
                    ':pid' => (int)($input['patient_id'] ?? 0),
                    ':fname' => (string)($input['first_name'] ?? ''),
                    ':lname' => (string)($input['last_name'] ?? ''),
                    ':nid' => (string)($input['national_id'] ?? ''),
                    ':dosya' => (string)($input['dosya_no'] ?? ''),
                    ':ref' => $referansId,
                    ':tarih' => $gelisTarihi,
                    ':gtipi' => (string)($input['gelis_tipi'] ?? ''),
                    ':xml' => $responseXml
                ]);
                
                $recordId = $db_obj->lastInsertId();
                
                // Testleri kaydet
                $testStmt = $db_obj->prepare('
                    INSERT INTO dislab_records_tests (record_id, test_code, test_name)
                    VALUES (:rid, :code, :name)
                ');
                
                // Yeni format: tests array'i {code, name} objeleri içeriyor
                if (isset($input['tests']) && is_array($input['tests'])) {
                    foreach ($input['tests'] as $test) {
                        $testStmt->execute([
                            ':rid' => $recordId,
                            ':code' => $test['code'] ?? '',
                            ':name' => $test['name'] ?? ''
                        ]);
                    }
                }
                // Eski format uyumluluğu: test_codes array'i
                elseif (isset($input['test_codes']) && is_array($input['test_codes'])) {
                    foreach ($input['test_codes'] as $code) {
                        $testStmt->execute([
                            ':rid' => $recordId,
                            ':code' => $code,
                            ':name' => $code
                        ]);
                    }
                }
                
                echo json_encode([
                    'success' => true,
                    'referans_id' => $referansId,
                    'record_id' => $recordId,
                    'message' => 'Hasta başarıyla dışlab\'a gönderildi'
                ], JSON_UNESCAPED_UNICODE);
                exit;
                
            } catch (Throwable $e) {
                // Hata durumunda kayıt oluştur
                $errorStmt = $db_obj->prepare('
                    INSERT INTO dislab_records 
                    (patient_id, first_name, last_name, national_id, dosya_no, status, error_message)
                    VALUES (:pid, :fname, :lname, :nid, :dosya, "error", :err)
                ');
                
                $errorStmt->execute([
                    ':pid' => (int)($input['patient_id'] ?? 0),
                    ':fname' => (string)($input['first_name'] ?? ''),
                    ':lname' => (string)($input['last_name'] ?? ''),
                    ':nid' => (string)($input['national_id'] ?? ''),
                    ':dosya' => (string)($input['dosya_no'] ?? ''),
                    ':err' => $e->getMessage()
                ]);
                
                echo json_encode([
                    'success' => false,
                    'error' => 'Dışlab hatası: ' . $e->getMessage()
                ], JSON_UNESCAPED_UNICODE);
                exit;
            }
        }

        if ($action === 'fetch') {

            $start = (string)($_GET['start'] ?? '');
            $end   = (string)($_GET['end'] ?? '');
            $status = (string)($_GET['status'] ?? 'Rapor');

            if ($start === '' || $end === '') {
                echo json_encode(['success' => false, 'error' => 'Başlangıç/Bitiş tarihi zorunlu.'], JSON_UNESCAPED_UNICODE);
                exit;
            }

            if (!class_exists('SoapClient')) {
                echo json_encode(['success' => false, 'error' => 'Sunucuda SOAP eklentisi yok (SoapClient bulunamadı).'], JSON_UNESCAPED_UNICODE);
                exit;
            }

            try {
                $client = new SoapClient($wsUrl . "?WSDL", [
                    'trace' => 1,
                    'soap_version' => SOAP_1_2,
                    'exceptions' => true,
                    'cache_wsdl' => WSDL_CACHE_NONE,
                    'connection_timeout' => 15,
                ]);
            } catch (Throwable $e) {
                echo json_encode(['success' => false, 'error' => 'WSDL açılamadı: ' . $e->getMessage()], JSON_UNESCAPED_UNICODE);
                exit;
            }

            $params = [
                'query' => [
                    'KurumBilgileri' => [
                        'WebUserKurumId' => 0,
                        'KullaniciAdi'   => (string)($conf['username'] ?? ''),
                        'Sifre'          => $pass,
                        'Kodu'           => $kurumKodu,
                        'KurumKodu'      => ''
                    ],
                    'DoktorBilgileri' => ['KimlikNo' => 0, 'Adi' => '', 'Soyadi' => ''],
                    'Bas' => (new DateTime($start))->format('Y-m-d\TH:i:s'),
                    'Son' => (new DateTime($end))->format('Y-m-d\TH:i:s'),
                    'KayitDurumu' => $status
                ]
            ];

            try {
                $res = $client->HastaListesiGetir($params);
            } catch (Throwable $e) {
                echo json_encode(['success' => false, 'error' => 'Servis hatası (HastaListesiGetir): ' . $e->getMessage()], JSON_UNESCAPED_UNICODE);
                exit;
            }

            $list = [];
            if (isset($res->HastaListesi->Liste->HastaDetay)) {
                $data = $res->HastaListesi->Liste->HastaDetay;
                $list = is_array($data) ? $data : [$data];
            }

            ob_start();

            if (empty($list)) {
                echo '<div class="nl-empty">
                        <div class="nl-empty-icon"><i class="bi bi-inbox"></i></div>
                        <div class="nl-empty-title">Kayıt bulunamadı</div>
                        <div class="nl-empty-sub">Tarih aralığını veya durumu değiştirip tekrar deneyin.</div>
                      </div>';
            } else {
                echo '<div class="mb-3 d-flex gap-2 align-items-center">
                        <input type="checkbox" class="form-check-input" id="selectAll" onchange="toggleSelectAll(this)">
                        <label class="form-check-label fw-bold" for="selectAll">Tümünü Seç</label>
                        <button class="btn btn-success btn-sm ms-auto" onclick="bulkSaveLocal()" id="bulkSaveBtn" disabled>
                            <i class="bi bi-download me-1"></i> Seçilileri Kaydet (<span id="selectedCount">0</span>)
                        </button>
                        <button class="btn btn-danger btn-sm" onclick="bulkDownloadPDF()" id="bulkPdfBtn" disabled>
                            <i class="bi bi-file-pdf me-1"></i> Seçilileri PDF İndir (<span id="selectedPdfCount">0</span>)
                        </button>
                      </div>';
                echo '<div class="nl-head-row d-none d-lg-grid">
                        <div style="width:50px;"><input type="checkbox" class="form-check-input" id="headerCheck" onchange="toggleSelectAll(this)"></div>
                        <div>HASTA</div>
                        <div>ÖRNEK NO</div>
                        <div>TARİH</div>
                        <div class="text-lg-center">DURUM</div>
                        <div class="text-end">İŞLEM</div>
                      </div>';

                foreach ($list as $p) {
                    $adi   = (string)($p->Adi ?? '');
                    $soyad = (string)($p->Soyadi ?? '');
                    $full  = trim($adi . ' ' . $soyad);
                    $tc    = (string)($p->KimlikNo ?? '-');
                    $ornekNo = (string)($p->OrnekNo ?? (string)($p->ReferansKodu ?? '-'));
                    $tarih = (string)($p->Tarih ?? '-');
                    $durum = (string)($p->KayitDurumu ?? 'Default');

                    $st = mb_strtolower(trim($durum));
                    $st = str_replace(['ı','İ',' '], ['i','i',''], $st);

                    $patientKey = mb_strtolower($full ?: '');
                    $refKey   = mb_strtolower($ornekNo ?: '');
                    ?>
                    <div class="nl-data-row shadow-sm border mb-3"
                         data-patient="<?= htmlspecialchars($patientKey, ENT_QUOTES, 'UTF-8') ?>"
                        data-ornekno="<?= htmlspecialchars($refKey, ENT_QUOTES, 'UTF-8') ?>">
                        
                        <div class="nl-col" style="width:50px;">
                            <input type="checkbox" class="form-check-input row-checkbox" 
                                   data-ornek-no="<?= htmlspecialchars($ornekNo) ?>" 
                                   data-patient-name="<?= htmlspecialchars($full) ?>" 
                                   onchange="updateBulkButtons()">
                        </div>

                        <div class="nl-col patient-box">
                            <div class="nl-avatar shadow-sm"><?= htmlspecialchars(mb_substr($adi ?: 'H', 0, 1)) ?></div>
                            <div class="nl-info">
                                <div class="nl-name text-dark fw-bold"><?= htmlspecialchars($full ?: '-') ?></div>
                                <div class="nl-sub text-muted small">TC: <?= htmlspecialchars($tc) ?></div>
                            </div>
                        </div>

                        <div class="nl-col barcode-box">
                            <div class="nl-label d-lg-none">ÖRNEK NO</div>
                            <div class="nl-barcode-badge shadow-sm font-monospace"><?= htmlspecialchars($ornekNo) ?></div>
                        </div>

                        <div class="nl-col date-box">
                            <div class="nl-label d-lg-none">TARİH</div>
                            <div class="small fw-semibold text-secondary"><?= htmlspecialchars($tarih) ?></div>
                        </div>

                        <div class="nl-col status-box text-lg-center">
                            <div class="nl-label d-lg-none">DURUM</div>
                            <span class="nl-status-pill st-<?= htmlspecialchars($st ?: 'default') ?>">
                                <?= htmlspecialchars($durum ?: '-') ?>
                            </span>
                        </div>

                        <div class="nl-col action-box text-end">
                            <div class="d-flex flex-wrap gap-2 justify-content-end">
                                <button class="btn btn-primary rounded-3 fw-bold btn-sm py-2 px-3"
                                        type="button"
                                        onclick="fetchDetail('<?= htmlspecialchars($ornekNo) ?>', '<?= htmlspecialchars($full) ?>')">
                                    <i class="bi bi-search me-1"></i> Sonuçları İncele
                                </button>
                                <button class="btn btn-success rounded-3 fw-bold btn-sm py-2 px-3"
                                        type="button"
                                        onclick="saveLocal(this,'<?= htmlspecialchars($ornekNo) ?>')">
                                    <i class="bi bi-download me-1"></i> Lokale Kaydet
                                </button>
                                <button class="btn btn-danger rounded-3 fw-bold btn-sm py-2 px-3"
                                        type="button"
                                        onclick="getReport('<?= htmlspecialchars($ornekNo) ?>')">
                                    <i class="bi bi-file-pdf me-1"></i> PDF İndir
                                </button>
                            </div>
                        </div>
                    </div>
                    <?php
                }
            }

            $html = ob_get_clean();
            echo json_encode(['success' => true, 'html' => $html, 'count' => count($list)], JSON_UNESCAPED_UNICODE);
            exit;
        }

        if ($action === 'sorgu_sonuc') {
            // Referans ID ile sonuçları sorgula - SOAP XML'i doğrudan gönder
            $referansId = (string)($_GET['referans_id'] ?? $_POST['referans_id'] ?? '');
            
            if (!$referansId) {
                echo json_encode(['success' => false, 'error' => 'Referans ID gerekli'], JSON_UNESCAPED_UNICODE);
                exit;
            }
            
            try {
                // SOAP XML'ini oluştur
                $soapXml = <<<XML
<?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>
    <HastaSonucSorgulaReferans xmlns="http://tenay.com.tr/">
      <order>
        <KurumBilgileri>
          <KullaniciAdi>$username</KullaniciAdi>
          <Sifre>$pass</Sifre>
          <Kodu>$kurumKodu</Kodu>
          <KurumKodu></KurumKodu>
        </KurumBilgileri>
        <DoktorBilgileri>
          <KimlikNo>0</KimlikNo>
          <Adi></Adi>
          <Soyadi></Soyadi>
        </DoktorBilgileri>
        <ReferanId>$referansId</ReferanId>
        <OrnekNo></OrnekNo>
        <DosyaNo></DosyaNo>
        <Rapor>true</Rapor>
      </order>
    </HastaSonucSorgulaReferans>
  </soap:Body>
</soap:Envelope>
XML;

                // cURL ile SOAP request'ini gönder
                $ch = curl_init();
                curl_setopt($ch, CURLOPT_URL, $wsUrl);
                curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
                curl_setopt($ch, CURLOPT_TIMEOUT, 30);
                curl_setopt($ch, CURLOPT_POST, true);
                curl_setopt($ch, CURLOPT_POSTFIELDS, $soapXml);
                curl_setopt($ch, CURLOPT_HTTPHEADER, [
                    'Content-Type: text/xml; charset=utf-8',
                    'Content-Length: ' . strlen($soapXml),
                    'SOAPAction: "http://tenay.com.tr/HastaSonucSorgulaReferans"'
                ]);
                curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
                curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
                
                $response = curl_exec($ch);
                $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
                $curlError = curl_error($ch);
                curl_close($ch);
                
                if ($curlError) {
                    echo json_encode(['success' => false, 'error' => 'İstek hatası: ' . $curlError], JSON_UNESCAPED_UNICODE);
                    exit;
                }
                
                if ($httpCode !== 200) {
                    echo json_encode(['success' => false, 'error' => "HTTP $httpCode: " . substr($response, 0, 100)], JSON_UNESCAPED_UNICODE);
                    exit;
                }
                
                // XML yanıtı parse et
                $xml = simplexml_load_string($response);
                if (!$xml) {
                    echo json_encode(['success' => false, 'error' => 'Geçersiz XML yanıtı'], JSON_UNESCAPED_UNICODE);
                    exit;
                }
                
                // Namespace'leri tanımla
                $namespaces = $xml->getNamespaces(true);
                $soap = $xml->children('http://schemas.xmlsoap.org/soap/envelope/');
                $body = $soap->Body;
                
                // OrnekNo'yu response'ten al
                $ornekNo = '';
                foreach ($body->children() as $response) {
                    foreach ($response->children() as $result) {
                        if ($result->getName() === 'HastaSonucSorgulaReferansResult') {
                            $ornekNo = (string)($result->OrnekNo ?? '');
                            break 2;
                        }
                    }
                }
                
                // Response'ı parse et
                $sonuclar = [];
                foreach ($body->children() as $response) {
                    foreach ($response->children() as $result) {
                        if ($result->getName() === 'SonucDetay' || strpos($result->getName(), 'Sonuc') !== false) {
                            $sonuclar[] = $result;
                        }
                    }
                }
                
                // Sonuçları format et
                $formatted = [];
                foreach ($sonuclar as $sonuc) {
                    $formatted[] = [
                        'TetkiAdi' => (string)($sonuc->TetkiAdi ?? ''),
                        'TetkiKodu' => (string)($sonuc->TetkiKodu ?? ''),
                        'Sonuc' => (string)($sonuc->Sonuc ?? ''),
                        'BirimAdi' => (string)($sonuc->BirimAdi ?? ''),
                        'Birim' => (string)($sonuc->Birim ?? ''),
                        'RefMin' => (string)($sonuc->ReferansMin ?? $sonuc->RefMin ?? ''),
                        'RefMax' => (string)($sonuc->ReferansMax ?? $sonuc->RefMax ?? ''),
                        'Durum' => (string)($sonuc->Durum ?? '')
                    ];
                }
                
                echo json_encode(['success' => true, 'data' => $formatted, 'ornek_no' => $ornekNo], JSON_UNESCAPED_UNICODE);
                exit;
            } catch (Throwable $e) {
                echo json_encode(['success' => false, 'error' => 'Hata: ' . $e->getMessage()], JSON_UNESCAPED_UNICODE);
                exit;
            }
        }

        if ($action === 'kaydet_hasta_sonuc') {
            // Dışlabdan gelen hasta sonuçlarını lokale kaydet
            $ornekNo = (string)($_POST['ornek_no'] ?? $_GET['ornek_no'] ?? '');
            $referanId = (string)($_POST['referan_id'] ?? $_GET['referan_id'] ?? '');
            
            if (!$ornekNo) {
                echo json_encode(['success' => false, 'error' => 'Örnek No gerekli'], JSON_UNESCAPED_UNICODE);
                exit;
            }
            
            try {
                // HastaSonucSorgula metodunu çağır
                $soapXml = <<<XML
<?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>
    <HastaSonucSorgula xmlns="http://tenay.com.tr/">
      <order>
        <KurumBilgileri>
          <KullaniciAdi>$username</KullaniciAdi>
          <Sifre>$pass</Sifre>
          <Kodu>$kurumKodu</Kodu>
          <KurumKodu></KurumKodu>
        </KurumBilgileri>
        <DoktorBilgileri>
          <KimlikNo>0</KimlikNo>
          <Adi></Adi>
          <Soyadi></Soyadi>
        </DoktorBilgileri>
        <ReferanId>$referanId</ReferanId>
        <OrnekNo>$ornekNo</OrnekNo>
        <DosyaNo></DosyaNo>
        <Rapor>true</Rapor>
      </order>
    </HastaSonucSorgula>
  </soap:Body>
</soap:Envelope>
XML;

                // cURL ile SOAP request'ini gönder
                $ch = curl_init();
                curl_setopt($ch, CURLOPT_URL, $wsUrl);
                curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
                curl_setopt($ch, CURLOPT_TIMEOUT, 30);
                curl_setopt($ch, CURLOPT_POST, true);
                curl_setopt($ch, CURLOPT_POSTFIELDS, $soapXml);
                curl_setopt($ch, CURLOPT_HTTPHEADER, [
                    'Content-Type: text/xml; charset=utf-8',
                    'Content-Length: ' . strlen($soapXml),
                    'SOAPAction: "http://tenay.com.tr/HastaSonucSorgula"'
                ]);
                curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
                curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
                
                $response = curl_exec($ch);
                $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
                $curlError = curl_error($ch);
                curl_close($ch);
                
                if ($curlError) {
                    echo json_encode(['success' => false, 'error' => 'İstek hatası: ' . $curlError], JSON_UNESCAPED_UNICODE);
                    exit;
                }
                
                if ($httpCode !== 200) {
                    echo json_encode(['success' => false, 'error' => "HTTP $httpCode"], JSON_UNESCAPED_UNICODE);
                    exit;
                }
                
                // XML yanıtı parse et
                $xml = simplexml_load_string($response);
                if (!$xml) {
                    echo json_encode(['success' => false, 'error' => 'Geçersiz XML yanıtı'], JSON_UNESCAPED_UNICODE);
                    exit;
                }
                
                // Namespace'lerle işle
                $soap = $xml->children('http://schemas.xmlsoap.org/soap/envelope/');
                $body = $soap->Body;
                
                $result = null;
                foreach ($body->children() as $child) {
                    if ($child->getName() === 'HastaSonucSorgulaResponse') {
                        $result = $child->HastaSonucSorgulaResult;
                        break;
                    }
                }
                
                if (!$result) {
                    echo json_encode(['success' => false, 'error' => 'Sonuç bulunamadı'], JSON_UNESCAPED_UNICODE);
                    exit;
                }
                
                // Hasta bilgilerini ayıkla
                $hastaBilgileri = $result->HastaBilgileri;
                $tc = (string)($hastaBilgileri->KimlikNo ?? '');
                $adi = (string)($hastaBilgileri->Adi ?? '');
                $soyadi = (string)($hastaBilgileri->Soyadi ?? '');
                $dogumTarihi = (string)($hastaBilgileri->DogumTarihi ?? '');
                $cinsiyeti = (string)($hastaBilgileri->Cinsiyeti ?? 'Bilinmeyen');
                
                // TC duplicate kontrol
                if ($tc) {
                    $checkStmt = $db_obj->prepare('SELECT id FROM patients WHERE national_id = :tc LIMIT 1');
                    $checkStmt->execute([':tc' => $tc]);
                    if ($checkStmt->rowCount() > 0) {
                        echo json_encode(['success' => false, 'error' => "TC numması zaten sistemde kayıtlı ($tc)"], JSON_UNESCAPED_UNICODE);
                        exit;
                    }
                }
                
                // Hastayı kaydet
                $insertStmt = $db_obj->prepare('
                    INSERT INTO patients (
                        first_name, last_name, national_id, birth_date, gender, status
                    ) VALUES (
                        :first_name, :last_name, :national_id, :birth_date, :gender, :status
                    )
                ');
                
                $insertStmt->execute([
                    ':first_name' => $adi,
                    ':last_name' => $soyadi,
                    ':national_id' => $tc,
                    ':birth_date' => $dogumTarihi ? substr($dogumTarihi, 0, 10) : null,
                    ':gender' => $cinsiyeti === 'Kadin' ? 'Kadın' : 'Erkek',
                    ':status' => 'active'
                ]);
                
                $patientId = $db_obj->lastInsertId();
                
                // Test sonuçlarını kaydet
                $tetkikler = $result->Tetkikler->TetkikSonuc;
                if ($tetkikler && !is_array($tetkikler)) {
                    $tetkikler = [$tetkikler];
                }
                
                $testCount = 0;
                if ($tetkikler) {
                    foreach ($tetkikler as $test) {
                        $testCode = (string)($test->Kodu ?? '');
                        $testAdi = (string)($test->Adi ?? '');
                        $sonuc = (string)($test->Sonuc ?? '');
                        $refMin = (string)($test->ReferansMin ?? '');
                        $refMax = (string)($test->ReferansMax ?? '');
                        $birim = (string)($test->Birim ?? '');
                        
                        // Test tanımını kaydet (eğer yoksa)
                        $testCheckStmt = $db_obj->prepare('SELECT id FROM local_test_definitions WHERE code = :code LIMIT 1');
                        $testCheckStmt->execute([':code' => $testCode]);
                        
                        if ($testCheckStmt->rowCount() === 0) {
                            $testInsertStmt = $db_obj->prepare('
                                INSERT INTO local_test_definitions (code, name, category, min_ref, max_ref, unit, is_active)
                                VALUES (:code, :name, :cat, :min_ref, :max_ref, :unit, 1)
                            ');
                            $testInsertStmt->execute([
                                ':code' => $testCode,
                                ':name' => $testAdi,
                                ':cat' => 'Dışlab',
                                ':min_ref' => $refMin ?: null,
                                ':max_ref' => $refMax ?: null,
                                ':unit' => $birim ?: null
                            ]);
                        }
                        
                        // Test sonucunu kaydet
                        $resultStmt = $db_obj->prepare('
                            INSERT INTO patient_test_results (
                                patient_id, test_code, test_name, result_value, reference_min, reference_max, unit, status
                            ) VALUES (
                                :patient_id, :test_code, :test_name, :result_value, :ref_min, :ref_max, :unit, :status
                            )
                        ');
                        
                        $resultStmt->execute([
                            ':patient_id' => $patientId,
                            ':test_code' => $testCode,
                            ':test_name' => $testAdi,
                            ':result_value' => $sonuc,
                            ':ref_min' => $refMin ?: null,
                            ':ref_max' => $refMax ?: null,
                            ':unit' => $birim ?: null,
                            ':status' => 'completed'
                        ]);
                        
                        $testCount++;
                    }
                }
                
                // Rapor64'ü PDF dosyası olarak kaydet
                $rapor64 = (string)($result->Rapor64 ?? '');
                if ($rapor64) {
                    $uploadsDir = __DIR__ . '/../../public/uploads/lab_reports/';
                    if (!is_dir($uploadsDir)) {
                        mkdir($uploadsDir, 0755, true);
                    }
                    
                    $pdfContent = base64_decode($rapor64, true);
                    if ($pdfContent) {
                        $fileName = 'DISLAB_' . $patientId . '_' . time() . '.pdf';
                        $filePath = $uploadsDir . $fileName;
                        
                        if (file_put_contents($filePath, $pdfContent)) {
                            // Rapor dosyasını DB'ye kaydet
                            $reportStmt = $db_obj->prepare('
                                INSERT INTO patient_reports (patient_id, file_name, file_path, report_type, created_at)
                                VALUES (:patient_id, :file_name, :file_path, :report_type, NOW())
                            ');
                            $reportStmt->execute([
                                ':patient_id' => $patientId,
                                ':file_name' => $fileName,
                                ':file_path' => '/uploads/lab_reports/' . $fileName,
                                ':report_type' => 'dislaboratory'
                            ]);
                        }
                    }
                }
                
                echo json_encode([
                    'success' => true,
                    'patient_id' => $patientId,
                    'message' => "$adi $soyadi başarıyla kaydedildi ($testCount test sonucu)"
                ], JSON_UNESCAPED_UNICODE);
                exit;
                
            } catch (Throwable $e) {
                echo json_encode(['success' => false, 'error' => 'Hata: ' . $e->getMessage()], JSON_UNESCAPED_UNICODE);
                exit;
            }
        }

        if ($action === 'download_rapor') {
            // Dışlab raporunu indir (base64 decode → PDF)
            $ornekNo = (string)($_GET['ornekNo'] ?? $_GET['ornek_no'] ?? $_POST['ornek_no'] ?? '');

            if (!$ornekNo) {
                header('HTTP/1.0 400 Bad Request');
                exit('Örnek No gerekli');
            }

            try {
                // OrnekNo ile sorgula ve Rapor64/Rapor alanını al
                $soapXml = '<?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>
    <HastaSonucSorgulaOrnekNo xmlns="http://tenay.com.tr/">
      <order>
        <KurumBilgileri>
          <KullaniciAdi>' . htmlspecialchars($username, ENT_QUOTES, 'UTF-8') . '</KullaniciAdi>
          <Sifre>' . htmlspecialchars($pass, ENT_QUOTES, 'UTF-8') . '</Sifre>
          <Kodu>' . htmlspecialchars($kurumKodu, ENT_QUOTES, 'UTF-8') . '</Kodu>
          <KurumKodu></KurumKodu>
        </KurumBilgileri>
        <DoktorBilgileri>
          <KimlikNo>0</KimlikNo>
          <Adi></Adi>
          <Soyadi></Soyadi>
        </DoktorBilgileri>
        <OrnekNo>' . htmlspecialchars($ornekNo, ENT_QUOTES, 'UTF-8') . '</OrnekNo>
        <Rapor>true</Rapor>
      </order>
    </HastaSonucSorgulaOrnekNo>
  </soap:Body>
</soap:Envelope>';

                $ch = curl_init();
                curl_setopt($ch, CURLOPT_URL, $wsUrl);
                curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
                curl_setopt($ch, CURLOPT_TIMEOUT, 30);
                curl_setopt($ch, CURLOPT_POST, true);
                curl_setopt($ch, CURLOPT_POSTFIELDS, $soapXml);
                curl_setopt($ch, CURLOPT_HTTPHEADER, [
                    'Content-Type: text/xml; charset=utf-8',
                    'Accept: application/soap+xml, text/xml, */*',
                    'Content-Length: ' . strlen($soapXml),
                    'SOAPAction: "http://tenay.com.tr/HastaSonucSorgulaOrnekNo"'
                ]);
                // Decode gzip/deflate responses if server compresses SOAP output
                curl_setopt($ch, CURLOPT_ENCODING, '');
                curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
                curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);

                $response = curl_exec($ch);
                $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
                $curlErr  = curl_error($ch);
                curl_close($ch);

                if ($curlErr) {
                    header('HTTP/1.0 500 Server Error');
                    exit('İstek hatası: ' . $curlErr);
                }
                if ($httpCode !== 200 || !$response) {
                    // Debug: Yanıtı logla
                    try {
                        $debugDir = __DIR__ . '/../../public/uploads/lab_reports/';
                        if (!is_dir($debugDir)) { @mkdir($debugDir, 0755, true); }
                        @file_put_contents($debugDir . 'error_rapor_' . preg_replace('/[^0-9A-Za-z_-]/','_', $ornekNo) . '_' . time() . '.txt', 
                            "HTTP Code: $httpCode\n\nResponse:\n" . substr($response, 0, 5000));
                    } catch(Throwable $e) { /* ignore */ }
                    
                    header('HTTP/1.0 500 Server Error');
                    exit('Rapor alınamadı (HTTP ' . $httpCode . '). Hata detayı loglandı.');
                }

                // Debug: yanıtı dosyaya yaz (inceleme için)
                try {
                    $debugDir = __DIR__ . '/../../public/uploads/lab_reports/';
                    if (!is_dir($debugDir)) { @mkdir($debugDir, 0755, true); }
                    @file_put_contents($debugDir . 'debug_rapor_' . preg_replace('/[^0-9A-Za-z_-]/','_', $ornekNo) . '_' . time() . '.xml', $response);
                } catch(Throwable $e) { /* ignore */ }

                $root = $nl_parse_hasta_root($response);
                if (!$root) {
                    header('HTTP/1.0 500 Server Error');
                    exit('Geçersiz yanıt (XML parse edilemedi)');
                }

                // Kod kontrolü
                $kod = (string)$root->Kod;
                if ($kod !== '1') {
                    header('HTTP/1.0 500 Server Error');
                    exit('Servis hata kodu: ' . $kod);
                }

                // Rapor64 veya Rapor al - DOMDocument ile direkt oku (büyük base64 için)
                libxml_use_internal_errors(true);
                $dom = new DOMDocument();
                $dom->loadXML($response);
                libxml_use_internal_errors(false);
                
                $xpath = new DOMXPath($dom);
                $xpath->registerNamespace('soap', 'http://schemas.xmlsoap.org/soap/envelope/');
                $xpath->registerNamespace('tn', 'http://tenay.com.tr/');
                
                $rapor64 = '';
                
                // Rapor64 ara (önce namespace ile)
                $rapor64Nodes = $xpath->query('//tn:Rapor64');
                if ($rapor64Nodes->length > 0) {
                    $rapor64 = trim($rapor64Nodes->item(0)->nodeValue);
                }
                
                // Yoksa namespace olmadan dene
                if (empty($rapor64)) {
                    $rapor64Nodes = $xpath->query('//Rapor64');
                    if ($rapor64Nodes->length > 0) {
                        $rapor64 = trim($rapor64Nodes->item(0)->nodeValue);
                    }
                }
                
                // Yoksa Rapor ara (namespace ile)
                if (empty($rapor64)) {
                    $raporNodes = $xpath->query('//tn:Rapor');
                    if ($raporNodes->length > 0) {
                        $rapor64 = trim($raporNodes->item(0)->nodeValue);
                    }
                }
                
                // Yoksa Rapor namespace olmadan
                if (empty($rapor64)) {
                    $raporNodes = $xpath->query('//Rapor');
                    if ($raporNodes->length > 0) {
                        $rapor64 = trim($raporNodes->item(0)->nodeValue);
                    }
                }

                if (empty($rapor64)) {
                    header('HTTP/1.0 404 Not Found');
                    exit('Rapor bulunamadı');
                }

                $pdfContent = base64_decode($rapor64, true);
                if (!$pdfContent) {
                    header('HTTP/1.0 500 Server Error');
                    exit('Rapor decode hatası');
                }

                header('Content-Type: application/pdf');
                header('Content-Disposition: attachment; filename="DISLAB_' . htmlspecialchars($ornekNo) . '.pdf"');
                echo $pdfContent;
                exit;

            } catch (Throwable $e) {
                header('HTTP/1.0 500 Server Error');
                exit('Hata: ' . $e->getMessage());
            }
        }

        if ($action === 'lokale_kaydet_ornekno') {
            // Örnek No ile HastaSonucSorgulaOrnekNo çağırıp hastayı ve testleri lokale kaydet
            $ornekNo = (string)($_POST['ornekNo'] ?? $_GET['ornekNo'] ?? '');
            if (!$ornekNo) {
                echo json_encode(['success' => false, 'error' => 'Örnek No gerekli'], JSON_UNESCAPED_UNICODE);
                exit;
            }

            try {
                $soapXml = <<<XML
<?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>
    <HastaSonucSorgulaOrnekNo xmlns="http://tenay.com.tr/">
      <order>
        <KurumBilgileri>
          <KullaniciAdi>$username</KullaniciAdi>
          <Sifre>$pass</Sifre>
          <Kodu>$kurumKodu</Kodu>
          <KurumKodu></KurumKodu>
        </KurumBilgileri>
        <DoktorBilgileri>
          <KimlikNo>0</KimlikNo>
          <Adi></Adi>
          <Soyadi></Soyadi>
        </DoktorBilgileri>
        <OrnekNo>$ornekNo</OrnekNo>
        <Rapor>true</Rapor>
      </order>
    </HastaSonucSorgulaOrnekNo>
  </soap:Body>
</soap:Envelope>
XML;

                $ch = curl_init();
                curl_setopt($ch, CURLOPT_URL, $wsUrl);
                curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
                curl_setopt($ch, CURLOPT_TIMEOUT, 30);
                curl_setopt($ch, CURLOPT_POST, true);
                curl_setopt($ch, CURLOPT_POSTFIELDS, $soapXml);
                curl_setopt($ch, CURLOPT_HTTPHEADER, [
                    'Content-Type: text/xml; charset=utf-8',
                    'Accept: application/soap+xml, text/xml, */*',
                    'Content-Length: ' . strlen($soapXml),
                    'SOAPAction: "http://tenay.com.tr/HastaSonucSorgulaOrnekNo"'
                ]);
                curl_setopt($ch, CURLOPT_ENCODING, '');
                curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
                curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);

                $response = curl_exec($ch);
                $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
                $curlError = curl_error($ch);
                curl_close($ch);

                if ($curlError) {
                    echo json_encode(['success' => false, 'error' => 'İstek hatası: ' . $curlError], JSON_UNESCAPED_UNICODE);
                    exit;
                }
                if ($httpCode !== 200 || !$response) {
                    echo json_encode(['success' => false, 'error' => 'Geçersiz yanıt (HTTP ' . $httpCode . ')'], JSON_UNESCAPED_UNICODE);
                    exit;
                }

                $root = $nl_parse_hasta_root($response);
                if (!$root) {
                    echo json_encode(['success'=>false,'error'=>'XML parse hatası (servis yanıtı okunamadı)'], JSON_UNESCAPED_UNICODE);
                    exit;
                }

                // Servis durum kodunu kontrol et (Kod != 1 ise açıklayıcı hata dön)
                $kodVal = (string)($root->xpath('//*[local-name()="Kod"]')[0] ?? '');
                if ($kodVal !== '' && trim($kodVal) !== '1') {
                    $ornekVal = (string)($root->xpath('//*[local-name()="OrnekNo"]')[0] ?? '');
                    $msg = 'Servis hata kodu: ' . $kodVal;
                    echo json_encode(['success'=>false,'error'=>$msg . ($ornekVal ? ' (Örnek No: '.$ornekVal.')' : '')], JSON_UNESCAPED_UNICODE);
                    exit;
                }

                // HastaBilgileri
                $adi = (string)($root->xpath('//*[local-name()="HastaBilgileri"]/*[local-name()="Adi"]')[0] ?? '');
                $soyadi = (string)($root->xpath('//*[local-name()="HastaBilgileri"]/*[local-name()="Soyadi"]')[0] ?? '');
                $tc = (string)($root->xpath('//*[local-name()="HastaBilgileri"]/*[local-name()="KimlikNo"]')[0] ?? '');
                $dogumTarihi = (string)($root->xpath('//*[local-name()="HastaBilgileri"]/*[local-name()="DogumTarihi"]')[0] ?? '');
                $cinsiyetRaw = (string)($root->xpath('//*[local-name()="HastaBilgileri"]/*[local-name()="Cinsiyeti"]')[0] ?? '');
                $gender = ($cinsiyetRaw === 'Kadin') ? 'Kadın' : (($cinsiyetRaw === 'Erkek') ? 'Erkek' : 'Bilinmeyen');

                // Duplicate kontrol (TC ile)
                if ($tc !== '') {
                    $checkStmt = $db_obj->prepare('SELECT id FROM patients WHERE national_id = :tc LIMIT 1');
                    $checkStmt->execute([':tc' => $tc]);
                    if ($checkStmt->fetchColumn()) {
                        echo json_encode(['success' => false, 'error' => 'TC zaten sistemde: ' . $tc], JSON_UNESCAPED_UNICODE);
                        exit;
                    }
                }

                // DB işlemleri transaction
                if (method_exists($db_obj, 'beginTransaction')) { $db_obj->beginTransaction(); }

                // Hasta ekle
                $ins = $db_obj->prepare('
                  INSERT INTO patients (first_name, last_name, national_id, birth_date, gender)
                  VALUES (:f,:l,:tc,:b,:g)
                ');
                $ins->execute([
                    ':f' => $adi,
                    ':l' => $soyadi,
                    ':tc' => ($tc !== '' ? $tc : null),
                    ':b' => ($dogumTarihi !== '' ? substr($dogumTarihi, 0, 10) : null),
                    ':g' => $gender,
                ]);
                $patientId = (int)$db_obj->lastInsertId();

                // Test sonuçları
                $tests = $root->xpath('//*[local-name()="Tetkikler"]/*[local-name()="TestSonuc"]') ?: [];
                if (empty($tests)) {
                    $tests = $root->xpath('//*[local-name()="Tetkikler"]/*[local-name()="TetkikSonuc"]') ?: [];
                }
                
                // Dislab record ekle
                $insRecord = $db_obj->prepare('
                  INSERT INTO dislab_records (patient_id, first_name, last_name, national_id, status, created_at)
                  VALUES (:pid, :f, :l, :tc, :st, NOW())
                ');
                $insRecord->execute([
                    ':pid' => $patientId,
                    ':f' => $adi,
                    ':l' => $soyadi,
                    ':tc' => ($tc !== '' ? $tc : null),
                    ':st' => 'pending',
                ]);
                $recordId = (int)$db_obj->lastInsertId();

                // Test sonuçlarını dislab_records_tests'e ekle
                $testCount = 0;
                foreach ($tests as $t) {
                    $name = (string)($t->Adi ?? '');
                    $code = (string)($t->Kodu ?? '');
                    
                    if ($code !== '') {
                        $insTest = $db_obj->prepare('
                          INSERT INTO dislab_records_tests (record_id, test_code, test_name, created_at)
                          VALUES (:rid, :code, :name, NOW())
                        ');
                        $insTest->execute([
                            ':rid' => $recordId,
                            ':code' => $code,
                            ':name' => $name,
                        ]);
                        $testCount++;
                    }
                }

                // Rapor64'ü dosyaya yaz ve patient_reports'a ekle
                $rapor64 = (string)($root->xpath('//*[local-name()="Rapor64"]')[0] ?? '');
                if ($rapor64 !== '') {
                    $uploadsDir = __DIR__ . '/../../public/uploads/lab_reports/';
                    if (!is_dir($uploadsDir)) { @mkdir($uploadsDir, 0755, true); }
                    $pdf = base64_decode($rapor64, true);
                    if ($pdf) {
                        $fileName = 'DISLAB_' . $patientId . '_' . time() . '.pdf';
                        $filePath = $uploadsDir . $fileName;
                        if (@file_put_contents($filePath, $pdf) !== false) {
                            $rep = $db_obj->prepare('INSERT INTO patient_reports (patient_id, file_name, file_path, report_type, created_at) VALUES (:pid,:fn,:fp,:rt, NOW())');
                            $rep->execute([
                                ':pid' => $patientId,
                                ':fn' => $fileName,
                                ':fp' => '/uploads/lab_reports/' . $fileName,
                                ':rt' => 'dislaboratory',
                            ]);
                        }
                    }
                }

                echo json_encode(['success' => true, 'patient_id' => $patientId, 'message' => ($adi . ' ' . $soyadi) . ' kaydedildi (' . $testCount . ' test)'], JSON_UNESCAPED_UNICODE);
                if (method_exists($db_obj, 'commit')) { $db_obj->commit(); }
                exit;
            } catch (Throwable $e) {
                if (method_exists($db_obj, 'rollBack') && method_exists($db_obj, 'inTransaction') && $db_obj->inTransaction()) { $db_obj->rollBack(); }
                echo json_encode(['success' => false, 'error' => 'Hata: ' . $e->getMessage()], JSON_UNESCAPED_UNICODE);
                exit;
            }
        }

        if ($action === 'fetch_detail') {

                        $ornek_no = trim((string)($_GET['ornekNo'] ?? $_GET['referansKodu'] ?? ''));
                        if ($ornek_no === '') {
                            echo json_encode(['success' => false, 'error' => 'Örnek No boş olamaz.'], JSON_UNESCAPED_UNICODE);
                exit;
            }

                        // OrnekNo'yu olduğu gibi gönder (baştaki sıfırlar dahil)
                        $ornekNoStr = trim($ornek_no);

                        $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>
                                <HastaSonucSorgulaOrnekNo xmlns="http://tenay.com.tr/">
                                    <order>
                                            <KurumBilgileri>
                                                <KullaniciAdi>' . htmlspecialchars((string)$conf['username'], ENT_QUOTES, 'UTF-8') . '</KullaniciAdi>
                                                <Sifre>' . htmlspecialchars($pass, ENT_QUOTES, 'UTF-8') . '</Sifre>
                                                <Kodu>' . htmlspecialchars($kurumKodu, ENT_QUOTES, 'UTF-8') . '</Kodu>
                                                <KurumKodu></KurumKodu>
                                            </KurumBilgileri>
                                        <DoktorBilgileri>
                                            <KimlikNo>0</KimlikNo>
                                            <Adi></Adi>
                                            <Soyadi></Soyadi>
                                        </DoktorBilgileri>
                                        <OrnekNo>' . htmlspecialchars($ornekNoStr, ENT_QUOTES, 'UTF-8') . '</OrnekNo>
                                        <Rapor>false</Rapor>
                                    </order>
                                </HastaSonucSorgulaOrnekNo>
                            </soap:Body>
                        </soap:Envelope>';

                        $ch = curl_init($wsUrl);
                        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
                        curl_setopt($ch, CURLOPT_POST, true);
                        curl_setopt($ch, CURLOPT_POSTFIELDS, $xml_payload);
                        curl_setopt($ch, CURLOPT_HTTPHEADER, [
                            'Content-Type: text/xml; charset=utf-8',
                            'Accept: application/soap+xml, text/xml, */*',
                            'Content-Length: ' . strlen($xml_payload),
                            'SOAPAction: "http://tenay.com.tr/HastaSonucSorgulaOrnekNo"'
                        ]);
                        curl_setopt($ch, CURLOPT_ENCODING, '');
                        curl_setopt($ch, CURLOPT_TIMEOUT, 25);

            $response = curl_exec($ch);
            $curlErr  = curl_error($ch);
            $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
            curl_close($ch);

            // Debug: yanıtı inceleme için dosyaya yaz
            try {
                $debugDir = __DIR__ . '/../../public/uploads/lab_reports/';
                if (!is_dir($debugDir)) { @mkdir($debugDir, 0755, true); }
                @file_put_contents($debugDir . 'debug_detail_' . preg_replace('/[^0-9A-Za-z_-]/','_', $ornek_no) . '_' . time() . '.xml', $response ?: '');
            } catch (Throwable $e) { /* ignore */ }

            if (!$response) {
                echo json_encode(['success' => false, 'error' => 'Servis yanıtı alınamadı: ' . $curlErr . ' (HTTP ' . $httpCode . ')'], JSON_UNESCAPED_UNICODE);
                exit;
            }

            $toFloat = function($v): ?float {
                $s = trim((string)$v);
                if ($s === '' || mb_strtolower($s) === 'null') return null;
                if (!preg_match('/-?\d+(?:[.,]\d+)?/u', $s, $m)) return null;
                $num = str_replace(',', '.', $m[0]);
                return is_numeric($num) ? (float)$num : null;
            };

            $normalizeStatus = function(string $raw): string {
                $s = mb_strtolower(trim($raw));
                if (str_contains($s, 'panik')) return 'panik';
                if (str_contains($s, 'yuk'))   return 'yuksek';
                if (str_contains($s, 'dus'))   return 'dusuk';
                if (str_contains($s, 'norm'))  return 'normal';
                return 'none';
            };

            $calcStatus = function($sonucStr, $minStr, $maxStr, $refDurumStr) use ($toFloat, $normalizeStatus): array {
                $sonucRaw = trim((string)$sonucStr);
                $minRaw   = trim((string)$minStr);
                $maxRaw   = trim((string)$maxStr);
                $refDurum = $normalizeStatus((string)$refDurumStr);

                $sonuc = $toFloat($sonucRaw);
                $min   = $toFloat($minRaw);
                $max   = $toFloat($maxRaw);

                $status = 'none';

                if ($sonuc !== null && ($min !== null || $max !== null)) {
                    if ($min !== null && $sonuc < $min) $status = 'dusuk';
                    else if ($max !== null && $sonuc > $max) $status = 'yuksek';
                    else $status = 'normal';
                }

                if ($refDurum === 'panik') $status = 'panik';
                if ($status === 'none' && $refDurum !== 'none') $status = $refDurum;

                $map = [
                    'normal' => ['label' => 'Normal', 'class' => 'bg-success-subtle text-success border border-success-subtle', 'icon' => 'bi-check-circle'],
                    'yuksek' => ['label' => 'Yüksek', 'class' => 'bg-danger-subtle text-danger border border-danger-subtle', 'icon' => 'bi-arrow-up-circle'],
                    'dusuk'  => ['label' => 'Düşük',  'class' => 'bg-warning-subtle text-warning border border-warning-subtle', 'icon' => 'bi-arrow-down-circle'],
                    'panik'  => ['label' => 'Panik',  'class' => 'bg-danger text-white', 'icon' => 'bi-exclamation-triangle-fill'],
                    'none'   => ['label' => 'Belirsiz', 'class' => 'bg-secondary-subtle text-secondary border border-secondary-subtle', 'icon' => 'bi-dash-circle'],
                ];

                return [$status, $map[$status]];
            };

            ob_start();

            // Debug: full response'ı dosyaya yaz
            try {
                $debugDir = __DIR__ . '/../../public/uploads/lab_reports/';
                if (!is_dir($debugDir)) { @mkdir($debugDir, 0755, true); }
                @file_put_contents($debugDir . 'debug_detail_full_' . preg_replace('/[^0-9A-Za-z_-]/', '_', $ornek_no) . '_' . time() . '.xml', $response ?: 'EMPTY');
            } catch(Throwable $e) { /* ignore */ }

            $root = $nl_parse_hasta_root($response);
            if (!$root) {
                // Debug: yanıtın başını log'la
                $preview = substr($response, 0, 500);
                $logMsg = "XML parse hatası. Response length: " . strlen($response) . "\nPreview:\n" . $preview;
                try {
                    $debugDir = __DIR__ . '/../../public/uploads/lab_reports/';
                    @file_put_contents($debugDir . 'debug_detail_parse_error_' . time() . '.txt', $logMsg);
                } catch(Throwable $e) { /* ignore */ }
                
                echo json_encode(['success'=>false,'error'=>'XML parse edilemedi. Len: ' . strlen($response) . '. İlk 150 kar: ' . substr($preview, 0, 150)], JSON_UNESCAPED_UNICODE);
                exit;
            }

            // Kod kontrolü
            $kodVal = (string)($root->xpath('//*[local-name()="Kod"]')[0] ?? '');
            if ($kodVal !== '' && trim($kodVal) !== '1') {
                $ornekVal = (string)($root->xpath('//*[local-name()="OrnekNo"]')[0] ?? '');
                $msg = 'Servis hata kodu: ' . $kodVal;
                echo json_encode(['success'=>false,'error'=>$msg . ($ornekVal ? ' (Örnek No: '.$ornekVal.')' : '')], JSON_UNESCAPED_UNICODE);
                exit;
            }

            // $root zaten HastaSorguCevap
            // Bazı sürümlerde düğüm adı TestSonuc yerine TetkikSonuc olarak gelir
            $results = $root->xpath('//*[local-name()="Tetkikler"]/*[local-name()="TestSonuc"]') ?: [];
            if (empty($results)) {
                $results = $root->xpath('//*[local-name()="Tetkikler"]/*[local-name()="TetkikSonuc"]') ?: [];
            }

            $hastaAdi = (string)($root->xpath('//*[local-name()="HastaBilgileri"]/*[local-name()="Adi"]')[0] ?? '');
            $hastaSoy = (string)($root->xpath('//*[local-name()="HastaBilgileri"]/*[local-name()="Soyadi"]')[0] ?? '');
            $hastaTC  = (string)($root->xpath('//*[local-name()="HastaBilgileri"]/*[local-name()="KimlikNo"]')[0] ?? '');
            $hastaFull = trim($hastaAdi . ' ' . $hastaSoy);

            $rapor64 = (string)($root->xpath('//*[local-name()="Rapor64"]')[0] ?? '');
            if (trim($rapor64) === '') {
                // Bazı dökümlerde yalnızca <Rapor> alanı gelir
                $rapor64 = (string)($root->xpath('//*[local-name()="Rapor"]')[0] ?? '');
            }
            $raporAdi = (string)($root->xpath('//*[local-name()="RaporAdi"]')[0] ?? 'rapor.pdf');
            $xsingXml = (string)($root->xpath('//*[local-name()="Xml"]')[0] ?? '');

            $rows = [];
            $hasPanic = false;

            foreach ($results as $r) {
                $testAdi = (string)($r->Adi ?? '');
                $sonuc   = (string)($r->Sonuc ?? '');
                $birim   = (string)($r->Birim ?? '');
                $rMin    = (string)($r->ReferansMin ?? '');
                $rMax    = (string)($r->ReferansMax ?? '');
                $refDur  = (string)($r->ReferansDurum ?? '');

                [$statusKey, $ui] = $calcStatus($sonuc, $rMin, $rMax, $refDur);
                if ($statusKey === 'panik') $hasPanic = true;

                $ozel = trim((string)($r->OzelNormalDeger ?? ''));
                $acik = trim((string)($r->Aciklama ?? ''));

                $uzun = trim((string)($r->UzunRapor ?? ''));
                if ($uzun === '' && method_exists($r, 'xpath')) {
                    $u = $r->xpath('./*[local-name()="UzunRapor"]');
                    if ($u && isset($u[0])) $uzun = trim((string)$u[0]);
                }

                $rows[] = [
                    'test' => $testAdi,
                    'sonuc' => $sonuc,
                    'birim' => $birim,
                    'min' => $rMin,
                    'max' => $rMax,
                    'statusKey' => $statusKey,
                    'ui' => $ui,
                    'ozel' => $ozel,
                    'acik' => $acik,
                    'uzun' => $uzun,
                ];
            }
            ?>
                    <div class="mb-3 p-3 rounded-3 border bg-light">
                        <div class="d-flex justify-content-between align-items-start">
                            <div>
                                <div class="fw-bold"><?= htmlspecialchars($hastaFull ?: 'Hasta') ?></div>
                                <div class="small text-muted">TC: <?= htmlspecialchars($hastaTC ?: '-') ?></div>
                            </div>
                            <div class="d-flex gap-2">
                                <?php if (trim($rapor64) !== ''): ?>
                                    <button class="btn btn-sm btn-outline-primary" onclick='downloadRapor(<?= json_encode($rapor64) ?>, <?= json_encode($raporAdi) ?>)'>
                                        <i class="bi bi-file-earmark-pdf me-1"></i> Kurum Raporu
                                    </button>
                                <?php endif; ?>
                                <?php if (trim($xsingXml) !== ''): ?>
                                    <button class="btn btn-sm btn-outline-success" onclick="downloadXsing('<?= htmlspecialchars(addslashes($xsingXml)) ?>')">
                                        <i class="bi bi-file-earmark-code me-1"></i> XSing
                                    </button>
                                <?php endif; ?>
                            </div>
                        </div>
                    </div>

                    <?php if ($hasPanic): ?>
                        <div class="alert alert-danger d-flex align-items-start gap-2 mb-3">
                            <i class="bi bi-exclamation-triangle-fill fs-5"></i>
                            <div>
                                <div class="fw-bold">Panik Değer Uyarısı</div>
                                <div class="small">En az bir tetkikte “Panik” durum tespit edildi. Lütfen sonuçları öncelikli değerlendirin.</div>
                            </div>
                        </div>
                    <?php endif; ?>

                    <?php if (empty($rows)): ?>
                        <div class="alert alert-warning text-center mb-0">Sonuç bulunamadı.</div>
                    <?php else: ?>
                        <div class="table-responsive">
                            <table class="table table-hover align-middle border nl-result-table">
                                <thead class="bg-light">
                                    <tr class="small fw-bold text-muted">
                                        <th>TEST</th>
                                        <th class="text-center">SONUÇ</th>
                                        <th class="text-center">BİRİM</th>
                                        <th class="text-center">REFERANS</th>
                                        <th class="text-end">DURUM</th>
                                    </tr>
                                </thead>
                                <tbody>
                                <?php foreach ($rows as $row):
                                    $refText = '-';
                                    if (trim($row['min']) !== '' || trim($row['max']) !== '') {
                                        $refText = trim($row['min']) . ' - ' . trim($row['max']);
                                    }

                                    $notes = [];
                                    if ($row['ozel'] !== '') $notes[] = '<span class="nl-note-chip">Özel Normal: ' . htmlspecialchars($row['ozel']) . '</span>';
                                    if ($row['acik'] !== '') $notes[] = '<span class="nl-note-chip">Not: ' . htmlspecialchars($row['acik']) . '</span>';
                                ?>
                                    <tr class="flag-<?= htmlspecialchars($row['statusKey']) ?>">
                                        <td class="fw-bold nl-test-cell flag-<?= htmlspecialchars($row['statusKey']) ?>">
                                            <?= htmlspecialchars($row['test'] ?: '-') ?>

                                            <?php if (!empty($notes)): ?>
                                                <div class="nl-test-note mt-1">
                                                    <?= implode(' ', $notes) ?>
                                                </div>
                                            <?php endif; ?>

                                            <?php if (trim((string)($row['uzun'] ?? '')) !== ''): ?>
                                                <div class="nl-long-report mt-2">
                                                    <div class="nl-long-report-title">
                                                        <i class="bi bi-journal-text me-1"></i> Uzun Rapor
                                                    </div>
                                                    <div class="nl-long-report-text"><?= nl2br(htmlspecialchars((string)$row['uzun'])) ?></div>
                                                </div>
                                            <?php endif; ?>
                                        </td>

                                        <td class="text-center">
                                            <span class="badge bg-primary-subtle text-primary border border-primary-subtle px-3 py-2">
                                                <?= htmlspecialchars($row['sonuc'] ?: '-') ?>
                                            </span>
                                        </td>

                                        <td class="text-center text-muted">
                                            <?= htmlspecialchars($row['birim'] ?: '-') ?>
                                        </td>

                                        <td class="text-center font-monospace small">
                                            <?= htmlspecialchars($refText) ?>
                                        </td>

                                        <td class="text-end">
                                            <span class="badge px-3 py-2 <?= htmlspecialchars($row['ui']['class']) ?>">
                                                <i class="bi <?= htmlspecialchars($row['ui']['icon']) ?> me-1"></i>
                                                <?= htmlspecialchars($row['ui']['label']) ?>
                                            </span>
                                        </td>
                                    </tr>
                                <?php endforeach; ?>
                                </tbody>
                            </table>
                        </div>

                        <div class="small text-muted mt-2 d-lg-none">
                            <i class="bi bi-arrows-move me-1"></i> Tabloda yatay kaydırma yapabilirsiniz.
                        </div>
                    <?php endif; ?>

            <?php
            $html = ob_get_clean();
            echo json_encode(['success' => true, 'html' => $html], JSON_UNESCAPED_UNICODE);
            exit;
        }

        echo json_encode(['success' => false, 'error' => 'Bilinmeyen action: ' . $action], JSON_UNESCAPED_UNICODE);
        exit;

    } catch (Throwable $e) {
        http_response_code(500);
        echo json_encode(['success'=>false,'error'=>'Server: '.$e->getMessage()], JSON_UNESCAPED_UNICODE);
        exit;
    }
}

/* ---------------------------------------------------------
   2) HTML TASARIMI (TOPBAR include)
------------------------------------------------------------ */

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 (file_exists($db_path)) { require_once $db_path; }
}

$topbar_path = realpath(__DIR__ . '/../../layout/topbar.php');
if ($topbar_path && file_exists($topbar_path)) {
    require_once $topbar_path;
}
?>

<script>
(function ensureViewport(){
  try{
    if (!document.querySelector('meta[name="viewport"]')) {
      var m = document.createElement('meta');
      m.name = 'viewport';
      m.content = 'width=device-width, initial-scale=1, viewport-fit=cover';
      document.head.appendChild(m);
    }
  }catch(e){}
})();
</script>

<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css" rel="stylesheet">

<style>
    :root{
        --nl-bg: #f6f7fb;
        --nl-card: #ffffff;
        --nl-border: #e5e7eb;
        --nl-text: #0f172a;
        --nl-muted: #64748b;
        --nl-soft: #f1f5f9;
        --nl-primary: #2563eb;
        --nl-primary-soft: #eef2ff;
        --nl-radius: 16px;
        --nl-max: 100%;
    }

    html, body { width:100%; max-width:100%; overflow-x:hidden; }
    body { background: var(--nl-bg); }

    .nl-shell{
        max-width: none;
        width: 100%;
        margin: 0;
        padding: 0 16px;
    }

    .nl-toolbar{
        background: var(--nl-card);
        border: 1px solid var(--nl-border);
        border-radius: var(--nl-radius);
        padding: 14px;
        position: sticky;
        top: calc(var(--h, 70px) + 12px);
        z-index: 50;
        overflow: hidden;
        box-shadow: 0 12px 30px rgba(15,23,42,.05);
    }

    .nl-pill{
        display:inline-flex; align-items:center; gap:8px;
        padding: 10px 12px;
        border-radius: 999px;
        border: 1px solid var(--nl-border);
        background: #fff;
        font-weight: 800;
        color: var(--nl-primary);
        box-shadow: 0 6px 18px rgba(15, 23, 42, .04);
        white-space: nowrap;
        width: 100%;
        justify-content: center;
    }

    .nl-label {
        font-size: 0.70rem;
        font-weight: 800;
        color: #94a3b8;
        text-transform: uppercase;
        margin-bottom: 6px;
        letter-spacing: .04em;
    }

    .nl-input-ui{
        width: 100%;
        height: 44px;
        border-radius: 12px;
        border: 1px solid var(--nl-border);
        background: #fff;
        padding: 0 12px;
        outline: none;
        font-weight: 600;
        color: var(--nl-text);
        transition: .15s;
        max-width: 100%;
        min-width: 0;
        -webkit-appearance: none;
        appearance: none;
    }
    .nl-input-ui:focus{
        border-color: rgba(37,99,235,.35);
        box-shadow: 0 0 0 4px rgba(37,99,235,.10);
    }

    .nl-btn-search{
        height: 44px;
        width: 100%;
        border: 0;
        border-radius: 12px;
        background: var(--nl-primary);
        color: #fff;
        font-weight: 800;
        letter-spacing: .02em;
        transition: .15s;
        max-width: 100%;
        min-width: 0;
        white-space: nowrap;
    }
    .nl-btn-search:hover{ filter: brightness(.95); }
    .nl-btn-search:active{ transform: translateY(1px); }

    .nl-qwrap{ position:relative; display:flex; align-items:center; }
    .nl-qwrap > i{ position:absolute; left:12px; color:#94a3b8; pointer-events:none; }
    .nl-input-ui.nl-q{ padding-left:38px; padding-right:44px; }
    .nl-qclear{
        position:absolute; right:8px;
        width:34px; height:34px;
        border:0; border-radius:10px;
        background:transparent;
        color:#94a3b8;
        display:grid; place-items:center;
        cursor:pointer;
    }
    .nl-qclear:hover{ background:#f1f5f9; color:var(--nl-primary); }
    .nl-qhint{ margin-top:6px; font-size:.8rem; font-weight:700; color:#ef4444; }

    #nlFilterForm .col-12,
    #nlFilterForm .col-md-6,
    #nlFilterForm .col-lg-3,
    #nlFilterForm .col-lg-2,
    #nlFilterForm .col-lg-1 { min-width: 0; }
    #nlFilterForm input,
    #nlFilterForm select,
    #nlFilterForm button { max-width: 100%; min-width: 0; }

    .nl-head-row{
        background: transparent;
        border: 1px dashed rgba(148,163,184,.6);
        border-radius: 14px;
        padding: 10px 18px;
        margin-bottom: 10px;
        color: #94a3b8;
        font-size: .75rem;
        font-weight: 900;
        letter-spacing: .06em;
        text-transform: uppercase;

        display: grid;
        align-items: center;
        gap: 10px;
        grid-template-columns: 50px 2.5fr 1fr 1fr 1fr 0.9fr;
    }

    .nl-data-row{
        background: var(--nl-card);
        border: 1px solid var(--nl-border);
        border-radius: var(--nl-radius);
        padding: 14px 18px;
        display: grid;
        align-items: center;
        gap: 10px;
        grid-template-columns: 50px 2.5fr 1fr 1fr 1fr 0.9fr;
        transition: .15s;
    }
    .nl-data-row:hover{
        box-shadow: 0 18px 40px rgba(15,23,42,.06);
        transform: translateY(-1px);
    }

    @media (max-width: 991.98px){
        .nl-toolbar{ position: static; }
        .nl-head-row{ display:none !important; }
        .nl-data-row{
            grid-template-columns: 1fr !important;
            padding: 16px 16px;
        }
        .nl-col{
            border-bottom: 1px solid #f1f5f9;
            padding: 10px 0;
        }
        .nl-col:last-child{ border-bottom: none; padding-bottom: 0; }
        .nl-label{ margin-bottom: 4px; }
        .action-box{ padding-top: 10px !important; }
    }

    .nl-avatar{
        width: 44px; height: 44px;
        background: var(--nl-primary-soft);
        color: var(--nl-primary);
        border-radius: 12px;
        display:flex; align-items:center; justify-content:center;
        font-weight: 900;
        flex: 0 0 auto;
    }
    .patient-box{ display:flex; align-items:center; gap: 12px; min-width: 0; }
    .nl-info{ min-width: 0; }
    .nl-name{ font-size: .98rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
    .nl-sub{ color: var(--nl-muted); }

    .nl-barcode-badge{
        background: var(--nl-soft);
        padding: 7px 12px;
        border-radius: 12px;
        font-weight: 800;
        border: 1px solid var(--nl-border);
        width: fit-content;
        max-width: 100%;
    }

    .nl-status-pill{
        padding: 7px 14px;
        border-radius: 999px;
        font-size: .75rem;
        font-weight: 900;
        border: 1px solid transparent;
        display:inline-flex;
        align-items:center;
        justify-content:center;
        width: fit-content;
    }
    .st-rapor{ background:#dcfce7; color:#166534; border-color:#bbf7d0; }
    .st-labkabul{ background:#ffedd5; color:#9a3412; border-color:#fed7aa; }
    .st-none, .st-default{ background:#e2e8f0; color:#334155; border-color:#cbd5e1; }

    .nl-empty{
        background: var(--nl-card);
        border: 1px dashed rgba(148,163,184,.55);
        border-radius: var(--nl-radius);
        padding: 46px 18px;
        text-align: center;
        color: var(--nl-muted);
    }
    .nl-empty-icon{
        width: 52px; height: 52px;
        display:inline-flex; align-items:center; justify-content:center;
        border-radius: 16px;
        background: var(--nl-soft);
        border: 1px solid var(--nl-border);
        font-size: 1.4rem;
        margin-bottom: 10px;
        color: #475569;
    }
    .nl-empty-title{ font-weight: 900; color: #334155; }
    .nl-empty-sub{ font-size: .9rem; margin-top: 4px; }

    #nl-wait-layer{
        position: fixed; inset: 0;
        background: rgba(246,247,251,0.92);
        backdrop-filter: blur(10px);
        display:none;
        align-items:center;
        justify-content:center;
        z-index: 10000;
        flex-direction: column;
    }

    .modal-content{ border-radius: 22px; overflow:hidden; border:none; }

    .nl-result-table .nl-test-cell{
        position: relative;
        padding-left: 18px;
        min-width: 220px;
    }
    .nl-result-table .nl-test-cell::before{
        content:"";
        position:absolute;
        left: 6px;
        top: 10px;
        bottom: 10px;
        width: 4px;
        border-radius: 999px;
        background: transparent;
        opacity: .95;
    }

    .nl-result-table .nl-test-cell.flag-yuksek::before{ background:#ef4444; }
    .nl-result-table .nl-test-cell.flag-dusuk::before{ background:#f59e0b; }
    .nl-result-table .nl-test-cell.flag-panik::before{ background:#b91c1c; }
    .nl-result-table .nl-test-cell.flag-normal::before{ background:#22c55e; }
    .nl-result-table .nl-test-cell.flag-none::before{ background:#94a3b8; }

    .nl-test-note{ display:flex; flex-wrap: wrap; gap: 6px; }
    .nl-note-chip{
        display:inline-flex;
        align-items:center;
        padding: 5px 10px;
        border-radius: 999px;
        background: #f1f5f9;
        border: 1px solid #e2e8f0;
        font-size: .75rem;
        font-weight: 700;
        color: #475569;
        line-height: 1.1;
    }

    .nl-result-table tbody tr.flag-yuksek { background: rgba(239, 68, 68, 0.06); }
    .nl-result-table tbody tr.flag-dusuk  { background: rgba(245, 158, 11, 0.08); }
    .nl-result-table tbody tr.flag-panik  { background: rgba(185, 28, 28, 0.12); }
    .nl-result-table tbody tr.flag-normal { background: rgba(34, 197, 94, 0.05); }

    .nl-result-table.table-hover tbody tr.flag-yuksek:hover,
    .nl-result-table.table-hover tbody tr.flag-dusuk:hover,
    .nl-result-table.table-hover tbody tr.flag-panik:hover,
    .nl-result-table.table-hover tbody tr.flag-normal:hover{
        filter: brightness(0.99);
    }

    @media (max-width: 576px){
        .nl-result-table .nl-test-cell{ min-width: 180px; }
        .nl-note-chip{ font-size: .72rem; }
    }

    .nl-long-report{
      background:#f8fafc;
      border:1px solid #e2e8f0;
      border-radius: 14px;
      padding: 10px 12px;
    }
    .nl-long-report-title{
      font-size: .75rem;
      font-weight: 900;
      color:#334155;
      text-transform: uppercase;
      letter-spacing: .05em;
      display:flex;
      align-items:center;
      gap:6px;
      margin-bottom: 6px;
    }
    .nl-long-report-text{
      font-size: .86rem;
      font-weight: 650;
      color:#475569;
      line-height: 1.35;
      white-space: normal;
      word-break: break-word;
    }
</style>

<div id="nl-wait-layer">
    <div class="spinner-border text-primary" style="width: 3rem; height: 3rem;"></div>
    <div class="mt-3 fw-bold">Servis sorgulanıyor...</div>
    <div class="small text-muted">Lütfen bekleyin</div>
</div>

<div class="modal fade" id="sonucModal" tabindex="-1" aria-hidden="true">
    <div class="modal-dialog modal-xl modal-dialog-centered">
        <div class="modal-content shadow-lg">
            <div class="modal-header border-bottom bg-light px-4">
                <div>
                    <h5 class="modal-title fw-bold mb-0" id="modalPatientName">Hasta Bilgisi</h5>
                    <p class="small text-muted mb-0">Onaylı sonuç detayları</p>
                </div>
                <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
            </div>
            <div class="modal-body p-4" id="modalResultBody"></div>
            <div class="modal-footer border-top bg-light">
                <button type="button" class="btn btn-secondary fw-bold px-4" data-bs-dismiss="modal">Kapat</button>
            </div>
        </div>
    </div>
</div>

<div class="py-3">
    <div class="nl-shell">

        <div class="d-flex align-items-center justify-content-between mb-2">
            <div>
                <div class="fw-black fw-bold" style="font-size:1.05rem;">
                    <i class="bi bi-search me-1 text-primary"></i> Dışlab İzle
                </div>
                <div class="small text-muted">Tarih aralığı seç, "Sorgula" ile takip kayıtlarını getir. Sonra Hasta/Referans Kodu ile filtrele.</div>
            </div>
        </div>

        <div class="nl-toolbar mb-3">
            <form id="nlFilterForm" class="row g-2 g-md-3 align-items-end">
                <div class="col-12 col-md-6 col-lg-3">
                    <label class="nl-label d-block">Başlangıç</label>
                    <input type="datetime-local" name="start" class="nl-input-ui"
                           value="<?= date('Y-m-d\T00:00', strtotime('-3 days')) ?>">
                </div>

                <div class="col-12 col-md-6 col-lg-3">
                    <label class="nl-label d-block">Bitiş</label>
                    <input type="datetime-local" name="end" class="nl-input-ui"
                           value="<?= date('Y-m-d\T23:59') ?>">
                </div>

                <div class="col-12 col-md-6 col-lg-2">
                    <label class="nl-label d-block">Durum</label>
                    <select name="status" class="nl-input-ui">
                        <option value="Rapor">Rapor (Onaylı)</option>
                        <option value="LabKabul">Lab Kabul</option>
                        <option value="None">Hepsi</option>
                    </select>
                </div>

                <div class="col-12 col-md-6 col-lg-3">
                    <label class="nl-label d-block">Ara (Hasta / Referans Kodu)</label>
                    <div class="nl-qwrap">
                        <i class="bi bi-search"></i>
                        <input id="nlQuickSearch" type="text" class="nl-input-ui nl-q"
                               placeholder="Örn: Ahmet / REF001" autocomplete="off">
                        <button type="button" id="nlQuickClear" class="nl-qclear" aria-label="Temizle">
                            <i class="bi bi-x-lg"></i>
                        </button>
                    </div>
                    <div class="nl-qhint" id="nlQuickHint" style="display:none;">Eşleşme yok</div>
                </div>

                <div class="col-12 col-md-6 col-lg-1">
                    <button type="submit" class="nl-btn-search">
                        <i class="bi bi-search me-1"></i> Sorgula
                    </button>
                </div>

                <div class="col-12 col-lg-1">
                    <div id="nlCount" class="nl-pill">
                        <i class="bi bi-list-check"></i> <span>0</span>
                    </div>
                </div>
            </form>
        </div>

        <div id="nlDataContainer">
            <div class="nl-empty">
                <div class="nl-empty-icon"><i class="bi bi-search"></i></div>
                <div class="nl-empty-title">Sorgu bekleniyor</div>
                <div class="nl-empty-sub">Tarih aralığını seçip "Sorgula" ile sonuçları getir.</div>
            </div>
        </div>

    </div>
</div>

<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>

<script>
document.addEventListener('DOMContentLoaded', function() {
    const loader = document.getElementById('nl-wait-layer');
    const container = document.getElementById('nlDataContainer');
    const countBadge = document.getElementById('nlCount');
    const countSpan = countBadge ? countBadge.querySelector('span') : null;

    const currentFile = location.pathname;

    const qsInput = document.getElementById('nlQuickSearch');
    const qsClear = document.getElementById('nlQuickClear');
    const qsHint  = document.getElementById('nlQuickHint');

    window.applyQuickFilter = function(){
        const q = (qsInput?.value || '').toLowerCase().trim();
        const rows = Array.from(document.querySelectorAll('#nlDataContainer .nl-data-row'));

        let shown = 0;
        rows.forEach(r => {
            const p = (r.getAttribute('data-patient') || '');
            const o = (r.getAttribute('data-ornekno') || '');
            const ok = !q || p.includes(q) || o.includes(q);
            r.style.display = ok ? '' : 'none';
            if (ok) shown++;
        });

        if (countSpan) countSpan.innerText = String(shown);
        if (qsHint) qsHint.style.display = (rows.length > 0 && shown === 0) ? '' : 'none';
    };

    if (qsInput) qsInput.addEventListener('input', () => applyQuickFilter());
    if (qsClear) qsClear.addEventListener('click', () => {
        if (!qsInput) return;
        qsInput.value = '';
        applyQuickFilter();
        qsInput.focus();
    });

    document.getElementById('nlFilterForm').addEventListener('submit', function(e) {
        e.preventDefault();

        const params = new URLSearchParams(new FormData(this));
        params.append('action', 'fetch');

        loader.style.display = 'flex';

        fetch(currentFile + '?' + params.toString(), { cache: 'no-store' })
            .then(async res => {
                const text = await res.text();
                try {
                    return JSON.parse(text);
                } catch (err) {
                    console.error("KRİTİK HATA (JSON değil):", text);
                    alert("Kritik Hata: Sunucu JSON döndürmedi. Konsolu (F12) kontrol edin.");
                    throw new Error("JSON Parse Fail");
                }
            })
            .then(data => {
                if (data.success) {
                    container.innerHTML = data.html;
                    if (countSpan) countSpan.innerText = String(data.count || 0);
                    applyQuickFilter();
                } else {
                    alert("Servis Hatası: " + (data.error || 'Bilinmeyen hata'));
                }
            })
            .catch(err => console.error(err))
            .finally(() => { loader.style.display = 'none'; });
    });

    window.fetchDetail = function(ornekNo, patientName) {
        const modalBody = document.getElementById('modalResultBody');
        const modalEl = document.getElementById('sonucModal');

        document.getElementById('modalPatientName').innerText = (patientName || 'Hasta') + " | Örnek No: " + (ornekNo || '-');
        loader.style.display = 'flex';

        fetch(currentFile + '?action=fetch_detail&ornekNo=' + encodeURIComponent(ornekNo || ''), { cache: 'no-store' })
            .then(async res => {
                const text = await res.text();
                try { return JSON.parse(text); }
                catch(e){
                    console.error("DETAY JSON değil:", text);
                    throw e;
                }
            })
            .then(data => {
                if (data.success) {
                    modalBody.innerHTML = data.html;
                    const myModal = new bootstrap.Modal(modalEl);
                    myModal.show();
                } else {
                    alert("Detay Hatası: " + (data.error || 'Bilinmeyen hata'));
                }
            })
            .catch(err => console.error(err))
            .finally(() => { loader.style.display = 'none'; });
    };

    // Örnek No ile lokale kaydet
    window.saveLocal = function(btnEl, ornekNo){
        if (!ornekNo) { alert('Örnek No bulunamadı'); return; }
        const btn = (btnEl && btnEl.closest) ? btnEl.closest('button') : null;
        const restore = btn ? btn.innerHTML : '';
        if (btn) { btn.disabled = true; btn.innerHTML = '<span class="spinner-border spinner-border-sm me-1"></span> Kaydediliyor…'; }
        fetch(currentFile + '?action=lokale_kaydet_ornekno', {
            method: 'POST',
            headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
            body: 'ornekNo=' + encodeURIComponent(ornekNo)
        })
          .then(async r => {
              const text = await r.text();
              try { return JSON.parse(text); }
              catch(e){ throw new Error('JSON değil: ' + text.slice(0,200)); }
          })
          .then(data => {
              if (btn) { btn.disabled = false; btn.innerHTML = restore; }
              if (data && data.success) {
                  alert('✓ ' + (data.message || 'Kaydedildi'));
              } else {
                  alert('✗ ' + (data.error || 'Kaydedilemedi'));
              }
          })
          .catch(err => {
              if (btn) { btn.disabled = false; btn.innerHTML = restore; }
              alert('Hata: ' + err.message);
          });
    };

    // Örnek No ile PDF rapor indir
    window.getReport = async function(ornekNo){
        if (!ornekNo) { alert('Örnek No bulunamadı'); return; }
        
        try {
            const url = currentFile + '?action=download_rapor&ornekNo=' + encodeURIComponent(ornekNo);
            const response = await fetch(url);
            
            if (!response.ok) {
                const errorText = await response.text();
                alert('PDF indirilemedi: ' + errorText.substring(0, 200));
                return;
            }
            
            const contentType = response.headers.get('content-type');
            if (!contentType || !contentType.includes('application/pdf')) {
                const text = await response.text();
                alert('Hata: ' + text.substring(0, 200));
                return;
            }
            
            const blob = await response.blob();
            const downloadUrl = URL.createObjectURL(blob);
            const a = document.createElement('a');
            a.href = downloadUrl;
            a.download = `DISLAB_${ornekNo}_${Date.now()}.pdf`;
            document.body.appendChild(a);
            a.click();
            document.body.removeChild(a);
            URL.revokeObjectURL(downloadUrl);
        } catch(error) {
            alert('PDF indirme hatası: ' + error.message);
            console.error('getReport error:', error);
        }
    };

    window.downloadRapor = function(base64Data, fileName) {
        try {
            const linkSource = 'data:application/pdf;base64,' + base64Data;
            const downloadLink = document.createElement('a');
            downloadLink.href = linkSource;
            downloadLink.download = fileName || 'rapor.pdf';
            downloadLink.click();
        } catch(e) {
            alert('Rapor indirilemedi: ' + e.message);
        }
    };

    window.downloadXsing = function(xmlData) {
        try {
            const blob = new Blob([xmlData], { type: 'application/xml' });
            const url = URL.createObjectURL(blob);
            const downloadLink = document.createElement('a');
            downloadLink.href = url;
            downloadLink.download = 'xsing_data.xml';
            downloadLink.click();
            URL.revokeObjectURL(url);
        } catch(e) {
            alert('XSing verisi indirilemedi: ' + e.message);
        }
    };

    // Toplu seçim fonksiyonları
    window.toggleSelectAll = function(checkbox) {
        const checkboxes = document.querySelectorAll('.row-checkbox');
        checkboxes.forEach(cb => {
            cb.checked = checkbox.checked;
        });
        updateBulkButtons();
    };

    window.updateBulkButtons = function() {
        const selected = document.querySelectorAll('.row-checkbox:checked');
        const count = selected.length;
        
        const bulkSaveBtn = document.getElementById('bulkSaveBtn');
        const bulkPdfBtn = document.getElementById('bulkPdfBtn');
        const selectedCount = document.getElementById('selectedCount');
        const selectedPdfCount = document.getElementById('selectedPdfCount');
        
        if (selectedCount) selectedCount.textContent = count;
        if (selectedPdfCount) selectedPdfCount.textContent = count;
        
        if (bulkSaveBtn) bulkSaveBtn.disabled = count === 0;
        if (bulkPdfBtn) bulkPdfBtn.disabled = count === 0;
        
        // Sync header checkboxes
        const selectAll = document.getElementById('selectAll');
        const headerCheck = document.getElementById('headerCheck');
        const allCheckboxes = document.querySelectorAll('.row-checkbox');
        const allChecked = allCheckboxes.length > 0 && count === allCheckboxes.length;
        
        if (selectAll) selectAll.checked = allChecked;
        if (headerCheck) headerCheck.checked = allChecked;
    };

    window.bulkSaveLocal = async function() {
        const selected = document.querySelectorAll('.row-checkbox:checked');
        if (selected.length === 0) {
            alert('Lütfen en az bir kayıt seçin.');
            return;
        }
        
        const total = selected.length;
        let success = 0;
        let failed = 0;
        
        const bulkSaveBtn = document.getElementById('bulkSaveBtn');
        const originalText = bulkSaveBtn ? bulkSaveBtn.innerHTML : '';
        
        for (let i = 0; i < selected.length; i++) {
            const ornekNo = selected[i].getAttribute('data-ornek-no');
            const patientName = selected[i].getAttribute('data-patient-name');
            
            if (bulkSaveBtn) {
                bulkSaveBtn.innerHTML = `<i class="bi bi-hourglass-split me-1"></i> İşleniyor... ${i + 1}/${total}`;
            }
            
            try {
                const response = await fetch(window.location.href, {
                    method: 'POST',
                    headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
                    body: new URLSearchParams({
                        action: 'lokale_kaydet_ornekno',
                        ornek_no: ornekNo
                    })
                });
                
                const text = await response.text();
                let result;
                try {
                    result = JSON.parse(text);
                } catch {
                    console.error('Non-JSON response:', text.substring(0, 200));
                    result = { success: false, error: 'Geçersiz yanıt' };
                }
                
                if (result.success) {
                    success++;
                } else {
                    failed++;
                    console.error(`${patientName} (${ornekNo}): ${result.error}`);
                }
            } catch (error) {
                failed++;
                console.error(`${patientName} (${ornekNo}):`, error);
            }
        }
        
        if (bulkSaveBtn) bulkSaveBtn.innerHTML = originalText;
        
        alert(`Toplu kaydetme tamamlandı!\n\nBaşarılı: ${success}\nHata: ${failed}\nToplam: ${total}`);
        
        // Uncheck all
        document.querySelectorAll('.row-checkbox').forEach(cb => cb.checked = false);
        updateBulkButtons();
    };

    window.bulkDownloadPDF = async function() {
        const selected = document.querySelectorAll('.row-checkbox:checked');
        if (selected.length === 0) {
            alert('Lütfen en az bir kayıt seçin.');
            return;
        }
        
        const total = selected.length;
        let success = 0;
        let failed = 0;
        const errors = [];
        
        const bulkPdfBtn = document.getElementById('bulkPdfBtn');
        const originalText = bulkPdfBtn ? bulkPdfBtn.innerHTML : '';
        
        for (let i = 0; i < selected.length; i++) {
            const ornekNo = selected[i].getAttribute('data-ornek-no');
            const patientName = selected[i].getAttribute('data-patient-name');
            
            if (bulkPdfBtn) {
                bulkPdfBtn.innerHTML = `<i class="bi bi-hourglass-split me-1"></i> İndiriliyor... ${i + 1}/${total}`;
            }
            
            try {
                const url = window.location.pathname + '?action=download_rapor&ornekNo=' + encodeURIComponent(ornekNo);
                const response = await fetch(url);
                
                if (response.ok) {
                    const contentType = response.headers.get('content-type');
                    if (contentType && contentType.includes('application/pdf')) {
                        const blob = await response.blob();
                        const downloadUrl = URL.createObjectURL(blob);
                        const a = document.createElement('a');
                        a.href = downloadUrl;
                        a.download = `DISLAB_${ornekNo}_${Date.now()}.pdf`;
                        a.click();
                        URL.revokeObjectURL(downloadUrl);
                        success++;
                    } else {
                        // Not a PDF, probably an error message
                        const text = await response.text();
                        failed++;
                        errors.push(`${patientName} (${ornekNo}): ${text.substring(0, 100)}`);
                        console.error(`${patientName} (${ornekNo}): ${text}`);
                    }
                    
                    // Delay to avoid overwhelming the browser
                    await new Promise(resolve => setTimeout(resolve, 500));
                } else {
                    const errorText = await response.text();
                    failed++;
                    errors.push(`${patientName} (${ornekNo}): HTTP ${response.status} - ${errorText.substring(0, 50)}`);
                    console.error(`${patientName} (${ornekNo}): HTTP ${response.status}`, errorText);
                }
            } catch (error) {
                failed++;
                errors.push(`${patientName} (${ornekNo}): ${error.message}`);
                console.error(`${patientName} (${ornekNo}):`, error);
            }
        }
        
        if (bulkPdfBtn) bulkPdfBtn.innerHTML = originalText;
        
        let message = `Toplu PDF indirme tamamlandı!\n\nBaşarılı: ${success}\nHata: ${failed}\nToplam: ${total}`;
        if (errors.length > 0 && errors.length <= 5) {
            message += '\n\nHatalar:\n' + errors.join('\n');
        }
        alert(message);
        
        // Uncheck all
        document.querySelectorAll('.row-checkbox').forEach(cb => cb.checked = false);
        updateBulkButtons();
    };
});
</script>
