select('*') ->from(['h' => EflCheckSentHisFinal::tableName()]) ->where(['is', 'h.lab_no', new Expression('NULL')]) ->all(); // ---------- Fetch pending items using EXISTS to avoid row duplication ---------- /*$query_lab = HanumanResultPhatthonCheck::find() ->alias('h') ->andWhere(['is', 'h.lab_no', new Expression('NULL')]) ->orderBy([ 'h.LabNo' => SORT_ASC, 'h.RiaHDocDate' => SORT_DESC, 'h.RiaLDSeq' => SORT_ASC ]) ->asArray() ->all();*/ //echo '
';
    //var_dump($query_lab);
    //die();

    if (empty($query_lab)) {
      error_log('No pending lab data matching efl_hl7_obr');
      return;
    }

    /* ===== Scan fallback ===== */
    $fallback = [
      'report_name'  => '',
      'report_dt'    => '',
      'approve_name' => '',
      'approve_dt'   => '',
    ];

    foreach ($query_lab as $r) {
      if (empty($fallback['report_name']) && !empty($r['RiaLDUserNameEntry'])) {
        $fallback['report_name'] = $r['RiaLDUserNameEntry'];
      }
      if (empty($fallback['report_dt']) && !empty($r['RiaLDUserDateEntry'])) {
        $fallback['report_dt'] = $r['RiaLDUserDateEntry'];
      }
      if (empty($fallback['approve_name']) && !empty($r['RiaLDUserNameAppr'])) {
        $fallback['approve_name'] = $r['RiaLDUserNameAppr'];
      }
      if (empty($fallback['approve_dt']) && !empty($r['RiaLDUserDateAppr'])) {
        $fallback['approve_dt'] = $r['RiaLDUserDateAppr'];
      }
    }

    // Group rows by LabNo and TestCode
    $grouped = [];
    foreach ($query_lab as $row) {
      $labNo = $row['LabNo'] ?? '';
      $testCode = $row['TestCode'] ?? '';
      if ($labNo && $testCode) {
        // Group by pair to ensure one ZIP per LN + TestCode as per efl_hl7_obr
        $grouped[$labNo . '_' . $testCode][] = $row;
      }
    }

    $outputDir = Yii::getAlias('@runtime/output_zips');
    if (!is_dir($outputDir)) {
      mkdir($outputDir, 0777, true);
    }

    foreach ($grouped as $groupKey => $rows) {
      $firstRow = $rows[0];
      $labNo = $firstRow['LabNo'] ?? '';
      $testCodeForFilename = $firstRow['TestCode'] ?? 'Unknown';
      $docIdParam = $firstRow['RiaHDocID'] ?? '';
      $docDate = !empty($firstRow['RiaHDocDate']) ? date('Y-m-d', strtotime($firstRow['RiaHDocDate'])) : '';

      // 1. Fetch Files
      $reportFiles = [];
      $reportFilenames = [];

      if (!empty($docIdParam)) {
        // Fetch PDF from URL
        $LisResultUrl = "https://report.prolab.co.th/prolab/printpdf.php?docID={$docIdParam}&docDate={$docDate}";
        $pdfContent = $this->fetchUrl($LisResultUrl, 20);
        if ($pdfContent !== false && strlen($pdfContent) > 0) {
          $fn = "{$labNo}_{$testCodeForFilename}.pdf";
          $reportFiles[] = ['name' => $fn, 'content' => $pdfContent];
          $reportFilenames[] = $fn;
        }

        // Fetch from Local Dir
        $localDir = "/var/www/html/pdflink/{$docIdParam}";
        if (is_dir($localDir)) {
          foreach (scandir($localDir) as $fn) {
            if ($fn === '.' || $fn === '..') continue;
            if (!preg_match('/\.(pdf|jpg|jpeg|png|doc|docx)$/i', $fn)) continue;
            $path = "{$localDir}/{$fn}";
            if (is_file($path) && is_readable($path)) {
              $content = @file_get_contents($path);
              if ($content !== false) {
                // Prefix filename to ensure uniqueness or use original
                $newFn = "{$labNo}_{$testCodeForFilename}_{$fn}";
                $reportFiles[] = ['name' => $newFn, 'content' => $content];
                $reportFilenames[] = $newFn;
              }
            }
          }
        }
      }

      // 2. Prepare JSON Data
      $labsData = [];
      foreach ($rows as $r) {
        $labsData[] = [
          "ln" => $r['LabNo'] ?? '',
          "result" => $r['RiaLDRsltAnal'] ?? '',
          "sub_result" => "",
          "unit" => $r['LabUnit'] ?? '',
          "method" => "",
          "test_code" => $r['TestCode'] ?? '',
          "test_name" => $r['TestName'] ?? '',
          "specimen" => "",
          "profile_name" => "",
          "normal_range" => trim(($r['LabNormal1'] ?? '') . ' ' . ($r['LabNormal2'] ?? '')),
          "report" => "",
          "comment" => $r['TestRemark'] ?? '',
          "status" => "Approve",
          "report_by" => (string)($r['RiaLDUserNameEntry'] ?: $fallback['report_name']),
          "report_time" => $this->dateTimeFormat($r['RiaLDUserDateEntry'] ?: $fallback['report_dt']),
          "approve_by" => (string)($r['RiaLDUserNameAppr'] ?: $fallback['approve_name']),
          "approve_time" => $this->dateTimeFormat($r['RiaLDUserDateAppr'] ?: $fallback['approve_dt']),
          "attache" => []
        ];
      }

      $patName = $firstRow['PatName'] ?? '';
      $fname = $patName;
      $lname = "";
      $parts = explode(' ', trim($patName), 2);
      if (count($parts) > 1) {
        $fname = $parts[0];
        $lname = $parts[1];
      }

      $jsonPayload = [
        "patient" => [
          "hn" => $firstRow['PatHN'] ?? '',
          "idcard" => "",
          "title" => "",
          "fname" => $fname,
          "lname" => $lname,
          "sex" => "",
          "dob" => ""
        ],
        "orderdetail" => [
          "order_number" => "",
          "ln" => $labNo,
          "hn_customer" => $firstRow['CustID'] ?? $firstRow['PatHN'] ?? '',
          "ref_no" => "",
          "ward_customer" => "",
          "status" => "",
          "doctor" => "",
          "comment_order" => "",
          "comment_patient" => "",
          "time_register" => $firstRow['RiaHDocDate'] ?? '',
          "download" => ""
        ],
        "labs" => $labsData,
        "report" => $reportFilenames,
        "report_original" => ""
      ];

      // 3. Create Zip
      $zipFilename = "{$labNo}_{$testCodeForFilename}.zip";
      $zipPath = $outputDir . DIRECTORY_SEPARATOR . $zipFilename;

      // Prepare Temp Directory for shell zip
      $tempDir = Yii::getAlias('@runtime/temp_zip_' . $labNo . '_' . uniqid());
      if (!is_dir($tempDir)) {
        mkdir($tempDir, 0777, true);
      }

      // Write JSON to temp
      $jsonFilename = "{$labNo}_{$testCodeForFilename}.json";
      file_put_contents($tempDir . DIRECTORY_SEPARATOR . $jsonFilename, json_encode($jsonPayload, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE));

      // Write Report Files to temp
      foreach ($reportFiles as $rf) {
        file_put_contents($tempDir . DIRECTORY_SEPARATOR . $rf['name'], $rf['content']);
      }

      // Execute zip command
      $cmd = "cd " . escapeshellarg($tempDir) . " && zip -r " . escapeshellarg($zipPath) . " .";
      exec($cmd, $output, $ret);

      if ($ret === 0) {
        error_log("Created ZIP (Shell): {$zipPath}");

        // บันทึก LisResult สำหรับทุก Test ใน lab นี้ที่ถูก Zip ไปแล้ว
        foreach ($rows as $r) {
          $testCode = (string)($r['TestCode'] ?? '');
          $testName = (string)($r['TestName'] ?? '');
          $hn = (string)($r['PatHN'] ?? '');
          $riahDocId = (string)($r['RiaHDocID'] ?? '');
          $riahDocDate = $r['RiaHDocDate'] ?? null;
          $resultValue = (string)($r['RiaLDRsltAnal'] ?? '');
          $resultUnit = (string)($r['LabUnit'] ?? '');
          $referenceRange = trim(($r['LabNormal1'] ?? '') . ' ' . ($r['LabNormal2'] ?? ''));
          $custId = '1600'; // กำหนดค่าตาม snippet ของผู้ใช้
          $seq = $r['RiaLDSeq'] ?? 0;

          $existsQuery = [
            'lab_no' => $labNo,
            'test_code' => $testCode,
            'cust_id' => $custId,
            'hn' => $hn,
            'seq' => $seq,
          ];

          $exists = EflResultSent::find()->where($existsQuery)->exists();

          if (!$exists) {
            $lisResult = new EflResultSent([
              'lab_no' => $labNo,
              'riah_doc_id' => $riahDocId,
              'riah_doc_date' => $riahDocDate,
              'test_code' => $testCode,
              'test_name' => $testName,
              'cust_id' => $custId,
              'hn' => $hn,
              'result_value' => $resultValue,
              'result_unit' => $resultUnit,
              'reference_range' => $referenceRange,
              'status' => 1,
              'seq' => $seq,
            ]);
            if (!$lisResult->save(false)) {
              error_log("Failed to save LisResult for LabNo={$labNo}, TestCode={$testCode}");
            }
          } else {
            error_log(
              "Record already exists in LisResult, skipping insert: "
                . "LabNo={$labNo}, TestCode={$testCode}, CustID={$custId}, HN={$hn}"
            );
          }
        }
      } else {
        error_log("Failed to create ZIP (Shell): {$zipPath} (Exit Code: $ret)");
      }

      // Cleanup temp directory
      if (is_dir($tempDir)) {
        FileHelper::removeDirectory($tempDir);
      }
    }

    error_log("=== Hanuman Result Phatthon Zip Generator END ===");
  }

  /**
   * helper: fetch URL via cURL (robust)
   */
  protected function fetchUrl($url, $timeout = 10)
  {
    $ch = curl_init($url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
    curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
    curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
    $data = curl_exec($ch);
    $http = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    $err = curl_errno($ch) ? curl_error($ch) : null;
    curl_close($ch);

    if ($data === false || $http >= 400) {
      error_log("fetchUrl failed: {$url} http={$http} err=" . ($err ?? 'none'));
      return false;
    }
    return $data;
  }

  /** helper: แปลง datetime เป็น Y-m-d H:i:s */
  public function dateTimeFormat($value)
  {
    if (empty($value)) return '';
    try {
      $dt = new \DateTime($value);
      return $dt->format('Y-m-d H:i:s');
    } catch (\Throwable $e) {
      return '';
    }
  }
}