<?php

namespace App\Database\Seeds;

use CodeIgniter\Database\Seeder;
use App\Libraries\ValueSet;
use App\Services\RuleExpressionService;

class TestSeeder extends Seeder
{
  private array $entityTypes = [];

  private function loadEntityTypes(): void
  {
    if (empty($this->entityTypes)) {
      $json = file_get_contents(APPPATH . 'Libraries/Data/entity_type.json');
      $data = json_decode($json, true);
      foreach ($data['values'] as $item) {
        $this->entityTypes[$item['key']] = $item['key'];
      }
    }
  }

  private function getEntityType(string $name): ?string
  {
    $this->loadEntityTypes();
    return $this->entityTypes[$name] ?? null;
  }

  private function getKey(string $lookupName, string $key): ?string
  {
    $data = ValueSet::getRaw($lookupName);
    if ($data === null) return null;
    foreach ($data as $item) {
      if (($item['key'] ?? '') === $key) {
        return $item['key'];
      }
    }
    return null;
  }

  public function run()
  {
    $now = date('Y-m-d H:i:s');

    $tIDs = [];
    $testMapHeaders = []; // Store TestMapID by mapping key
    $testMapDetails = []; // Store detail records

    // Helper to get or create TestMap header ID
    $getTestMapID = function($testSiteID, $hostType, $hostID, $clientType, $clientID) use (&$testMapHeaders, &$now) {
      $key = "{$hostType}_{$hostID}_{$clientType}_{$clientID}";
      if (!isset($testMapHeaders[$key])) {
        $data = [
          'TestSiteID' => $testSiteID,
          'HostType' => $hostType,
          'HostID' => $hostID,
          'ClientType' => $clientType,
          'ClientID' => $clientID,
          'CreateDate' => $now
        ];
        $this->db->table('testmap')->insert($data);
        $testMapHeaders[$key] = $this->db->insertID();
      }
      return $testMapHeaders[$key];
    };

    // ========================================
    // DEPARTMENT 1 - HEMATOLOGY (Discipline 1)
    // Order: GROUP (<100) → PARAM (<100) → TEST (100+) → CALC (100+)
    // ========================================
    
    // GROUP: CBC (Complete Blood Count)
    $data = ['SiteID' => '1', 'TestSiteCode' => 'CBC', 'TestSiteName' => 'Complete Blood Count', 'TestType' => 'GROUP', 'Description' => 'Darah Lengkap', 'SeqScr' => '10', 'SeqRpt' => '10', 'IndentLeft' => '0', 'isVisibleScr' => '1', 'isVisibleRpt' => '1', 'isCountStat' => '1', 'ResultType' => 'NORES', 'RefType' => 'NOREF', 'CreateDate' => "$now"];
    $this->db->table('testdefsite')->insert($data);
    $tIDs['CBC'] = $this->db->insertID();

    // PARAM: (none for Hematology)

    // TEST: Hematology Tests
    $data = ['SiteID' => '1', 'TestSiteCode' => 'HB', 'TestSiteName' => 'Hemoglobin', 'TestType' => 'TEST', 'Description' => '', 'SeqScr' => '100', 'SeqRpt' => '100', 'IndentLeft' => '1', 'isVisibleScr' => '1', 'isVisibleRpt' => '1', 'isCountStat' => '1', 'DisciplineID' => '1', 'DepartmentID' => '1', 'ResultType' => 'NMRIC', 'RefType' => 'RANGE', 'VSet' => '', 'ReqQty' => '500', 'ReqQtyUnit' => 'uL', 'Unit1' => 'g/dL', 'Factor' => '', 'Unit2' => '', 'Decimal' => '1', 'Method' => 'CBC Analyzer', 'CreateDate' => "$now"];
    $this->db->table('testdefsite')->insert($data);
    $tIDs['HB'] = $this->db->insertID();

    $data = ['SiteID' => '1', 'TestSiteCode' => 'HCT', 'TestSiteName' => 'Hematocrit', 'TestType' => 'TEST', 'Description' => '', 'SeqScr' => '110', 'SeqRpt' => '110', 'IndentLeft' => '1', 'isVisibleScr' => '1', 'isVisibleRpt' => '1', 'isCountStat' => '1', 'DisciplineID' => '1', 'DepartmentID' => '1', 'ResultType' => 'NMRIC', 'RefType' => 'RANGE', 'VSet' => '', 'ReqQty' => '500', 'ReqQtyUnit' => 'uL', 'Unit1' => '%', 'Factor' => '', 'Unit2' => '', 'Decimal' => '1', 'Method' => 'CBC Analyzer', 'CreateDate' => "$now"];
    $this->db->table('testdefsite')->insert($data);
    $tIDs['HCT'] = $this->db->insertID();

    $data = ['SiteID' => '1', 'TestSiteCode' => 'RBC', 'TestSiteName' => 'Red Blood Cell', 'TestType' => 'TEST', 'Description' => 'Eritrosit', 'SeqScr' => '120', 'SeqRpt' => '120', 'IndentLeft' => '1', 'isVisibleScr' => '1', 'isVisibleRpt' => '1', 'isCountStat' => '1', 'DisciplineID' => '1', 'DepartmentID' => '1', 'ResultType' => 'NMRIC', 'RefType' => 'RANGE', 'VSet' => '', 'ReqQty' => '500', 'ReqQtyUnit' => 'uL', 'Unit1' => 'x10^6/uL', 'Factor' => '', 'Unit2' => '', 'Decimal' => '2', 'Method' => 'CBC Analyzer', 'CreateDate' => "$now"];
    $this->db->table('testdefsite')->insert($data);
    $tIDs['RBC'] = $this->db->insertID();

    $data = ['SiteID' => '1', 'TestSiteCode' => 'WBC', 'TestSiteName' => 'White Blood Cell', 'TestType' => 'TEST', 'Description' => 'Leukosit', 'SeqScr' => '130', 'SeqRpt' => '130', 'IndentLeft' => '1', 'isVisibleScr' => '1', 'isVisibleRpt' => '1', 'isCountStat' => '1', 'DisciplineID' => '1', 'DepartmentID' => '1', 'ResultType' => 'NMRIC', 'RefType' => 'RANGE', 'VSet' => '', 'ReqQty' => '500', 'ReqQtyUnit' => 'uL', 'Unit1' => 'x10^3/uL', 'Factor' => '', 'Unit2' => '', 'Decimal' => '2', 'Method' => 'CBC Analyzer', 'CreateDate' => "$now"];
    $this->db->table('testdefsite')->insert($data);
    $tIDs['WBC'] = $this->db->insertID();

    $data = ['SiteID' => '1', 'TestSiteCode' => 'PLT', 'TestSiteName' => 'Platelet', 'TestType' => 'TEST', 'Description' => 'Trombosit', 'SeqScr' => '140', 'SeqRpt' => '140', 'IndentLeft' => '1', 'isVisibleScr' => '1', 'isVisibleRpt' => '1', 'isCountStat' => '1', 'DisciplineID' => '1', 'DepartmentID' => '1', 'ResultType' => 'NMRIC', 'RefType' => 'RANGE', 'VSet' => '', 'ReqQty' => '500', 'ReqQtyUnit' => 'uL', 'Unit1' => 'x10^3/uL', 'Factor' => '', 'Unit2' => '', 'Decimal' => '0', 'Method' => 'CBC Analyzer', 'CreateDate' => "$now"];
    $this->db->table('testdefsite')->insert($data);
    $tIDs['PLT'] = $this->db->insertID();

    $data = ['SiteID' => '1', 'TestSiteCode' => 'MCV', 'TestSiteName' => 'MCV', 'TestType' => 'TEST', 'Description' => 'Mean Corpuscular Volume', 'SeqScr' => '150', 'SeqRpt' => '150', 'IndentLeft' => '1', 'isVisibleScr' => '1', 'isVisibleRpt' => '1', 'isCountStat' => '1', 'DisciplineID' => '1', 'DepartmentID' => '1', 'ResultType' => 'NMRIC', 'RefType' => 'RANGE', 'VSet' => '', 'ReqQty' => '500', 'ReqQtyUnit' => 'uL', 'Unit1' => 'fL', 'Factor' => '', 'Unit2' => '', 'Decimal' => '1', 'Method' => 'CBC Analyzer', 'CreateDate' => "$now"];
    $this->db->table('testdefsite')->insert($data);
    $tIDs['MCV'] = $this->db->insertID();

    $data = ['SiteID' => '1', 'TestSiteCode' => 'MCH', 'TestSiteName' => 'MCH', 'TestType' => 'TEST', 'Description' => 'Mean Corpuscular Hemoglobin', 'SeqScr' => '160', 'SeqRpt' => '160', 'IndentLeft' => '1', 'isVisibleScr' => '1', 'isVisibleRpt' => '1', 'isCountStat' => '1', 'DisciplineID' => '1', 'DepartmentID' => '1', 'ResultType' => 'NMRIC', 'RefType' => 'RANGE', 'VSet' => '', 'ReqQty' => '500', 'ReqQtyUnit' => 'uL', 'Unit1' => 'pg', 'Factor' => '', 'Unit2' => '', 'Decimal' => '1', 'Method' => 'CBC Analyzer', 'CreateDate' => "$now"];
    $this->db->table('testdefsite')->insert($data);
    $tIDs['MCH'] = $this->db->insertID();

    $data = ['SiteID' => '1', 'TestSiteCode' => 'MCHC', 'TestSiteName' => 'MCHC', 'TestType' => 'TEST', 'Description' => 'Mean Corpuscular Hemoglobin Concentration', 'SeqScr' => '170', 'SeqRpt' => '170', 'IndentLeft' => '1', 'isVisibleScr' => '1', 'isVisibleRpt' => '1', 'isCountStat' => '1', 'DisciplineID' => '1', 'DepartmentID' => '1', 'ResultType' => 'NMRIC', 'RefType' => 'RANGE', 'VSet' => '', 'ReqQty' => '500', 'ReqQtyUnit' => 'uL', 'Unit1' => 'g/dL', 'Factor' => '', 'Unit2' => '', 'Decimal' => '1', 'Method' => 'CBC Analyzer', 'CreateDate' => "$now"];
    $this->db->table('testdefsite')->insert($data);
    $tIDs['MCHC'] = $this->db->insertID();

    // Add CBC members now that tests are defined
    $this->db->table('testdefgrp')->insertBatch([
      ['TestSiteID' => $tIDs['CBC'], 'Member' => $tIDs['HB'], 'CreateDate' => "$now"],
      ['TestSiteID' => $tIDs['CBC'], 'Member' => $tIDs['HCT'], 'CreateDate' => "$now"],
      ['TestSiteID' => $tIDs['CBC'], 'Member' => $tIDs['RBC'], 'CreateDate' => "$now"],
      ['TestSiteID' => $tIDs['CBC'], 'Member' => $tIDs['WBC'], 'CreateDate' => "$now"],
      ['TestSiteID' => $tIDs['CBC'], 'Member' => $tIDs['PLT'], 'CreateDate' => "$now"],
      ['TestSiteID' => $tIDs['CBC'], 'Member' => $tIDs['MCV'], 'CreateDate' => "$now"],
      ['TestSiteID' => $tIDs['CBC'], 'Member' => $tIDs['MCH'], 'CreateDate' => "$now"],
      ['TestSiteID' => $tIDs['CBC'], 'Member' => $tIDs['MCHC'], 'CreateDate' => "$now"]
    ]);

    // CALC: (none for Hematology)

    // ========================================
    // DEPARTMENT 2 - CHEMISTRY (Discipline 2)
    // Order: GROUP (<100) → PARAM (<100) → TEST (100+) → CALC (100+)
    // ========================================

    // GROUP: LIPID, LFT, RFT
    $data = ['SiteID' => '1', 'TestSiteCode' => 'LIPID', 'TestSiteName' => 'Lipid Profile', 'TestType' => 'GROUP', 'Description' => 'Profil Lipid', 'SeqScr' => '10', 'SeqRpt' => '10', 'IndentLeft' => '0', 'isVisibleScr' => '1', 'isVisibleRpt' => '1', 'isCountStat' => '1', 'ResultType' => 'NORES', 'RefType' => 'NOREF', 'CreateDate' => "$now"];
    $this->db->table('testdefsite')->insert($data);
    $tIDs['LIPID'] = $this->db->insertID();

    $data = ['SiteID' => '1', 'TestSiteCode' => 'LFT', 'TestSiteName' => 'Liver Function Test', 'TestType' => 'GROUP', 'Description' => 'Fungsi Hati', 'SeqScr' => '20', 'SeqRpt' => '20', 'IndentLeft' => '0', 'isVisibleScr' => '1', 'isVisibleRpt' => '1', 'isCountStat' => '1', 'ResultType' => 'NORES', 'RefType' => 'NOREF', 'CreateDate' => "$now"];
    $this->db->table('testdefsite')->insert($data);
    $tIDs['LFT'] = $this->db->insertID();

    $data = ['SiteID' => '1', 'TestSiteCode' => 'RFT', 'TestSiteName' => 'Renal Function Test', 'TestType' => 'GROUP', 'Description' => 'Fungsi Ginjal', 'SeqScr' => '30', 'SeqRpt' => '30', 'IndentLeft' => '0', 'isVisibleScr' => '1', 'isVisibleRpt' => '1', 'isCountStat' => '1', 'ResultType' => 'NORES', 'RefType' => 'NOREF', 'CreateDate' => "$now"];
    $this->db->table('testdefsite')->insert($data);
    $tIDs['RFT'] = $this->db->insertID();

    // PARAM: (none for Chemistry)

    // TEST: Chemistry Tests
    $data = ['SiteID' => '1', 'TestSiteCode' => 'GLU', 'TestSiteName' => 'Glucose', 'TestType' => 'TEST', 'Description' => 'Glukosa Sewaktu', 'SeqScr' => '100', 'SeqRpt' => '100', 'IndentLeft' => '1', 'isVisibleScr' => '1', 'isVisibleRpt' => '1', 'isCountStat' => '1', 'DisciplineID' => '2', 'DepartmentID' => '2', 'ResultType' => 'NMRIC', 'RefType' => 'RANGE', 'VSet' => '', 'ReqQty' => '300', 'ReqQtyUnit' => 'uL', 'Unit1' => 'mg/dL', 'Factor' => '0.0555', 'Unit2' => 'mmol/L', 'Decimal' => '0', 'Method' => 'Hexokinase', 'CreateDate' => "$now"];
    $this->db->table('testdefsite')->insert($data);
    $tIDs['GLU'] = $this->db->insertID();

    $data = ['SiteID' => '1', 'TestSiteCode' => 'CREA', 'TestSiteName' => 'Creatinine', 'TestType' => 'TEST', 'Description' => 'Kreatinin', 'SeqScr' => '110', 'SeqRpt' => '110', 'IndentLeft' => '1', 'isVisibleScr' => '1', 'isVisibleRpt' => '1', 'isCountStat' => '1', 'DisciplineID' => '2', 'DepartmentID' => '2', 'ResultType' => 'NMRIC', 'RefType' => 'RANGE', 'VSet' => '', 'ReqQty' => '300', 'ReqQtyUnit' => 'uL', 'Unit1' => 'mg/dL', 'Factor' => '88.4', 'Unit2' => 'umol/L', 'Decimal' => '2', 'Method' => 'Enzymatic', 'CreateDate' => "$now"];
    $this->db->table('testdefsite')->insert($data);
    $tIDs['CREA'] = $this->db->insertID();

    $data = ['SiteID' => '1', 'TestSiteCode' => 'UREA', 'TestSiteName' => 'Blood Urea Nitrogen', 'TestType' => 'TEST', 'Description' => 'BUN', 'SeqScr' => '120', 'SeqRpt' => '120', 'IndentLeft' => '1', 'isVisibleScr' => '1', 'isVisibleRpt' => '1', 'isCountStat' => '1', 'DisciplineID' => '2', 'DepartmentID' => '2', 'ResultType' => 'NMRIC', 'RefType' => 'RANGE', 'VSet' => '', 'ReqQty' => '300', 'ReqQtyUnit' => 'uL', 'Unit1' => 'mg/dL', 'Factor' => '', 'Unit2' => '', 'Decimal' => '1', 'Method' => 'Urease-GLDH', 'CreateDate' => "$now"];
    $this->db->table('testdefsite')->insert($data);
    $tIDs['UREA'] = $this->db->insertID();

    $data = ['SiteID' => '1', 'TestSiteCode' => 'SGOT', 'TestSiteName' => 'AST (SGOT)', 'TestType' => 'TEST', 'Description' => 'Aspartate Aminotransferase', 'SeqScr' => '130', 'SeqRpt' => '130', 'IndentLeft' => '1', 'isVisibleScr' => '1', 'isVisibleRpt' => '1', 'isCountStat' => '1', 'DisciplineID' => '2', 'DepartmentID' => '2', 'ResultType' => 'NMRIC', 'RefType' => 'RANGE', 'VSet' => '', 'ReqQty' => '300', 'ReqQtyUnit' => 'uL', 'Unit1' => 'U/L', 'Factor' => '0.017', 'Unit2' => 'ukat/L', 'Decimal' => '0', 'Method' => 'IFCC', 'CreateDate' => "$now"];
    $this->db->table('testdefsite')->insert($data);
    $tIDs['SGOT'] = $this->db->insertID();

    $data = ['SiteID' => '1', 'TestSiteCode' => 'SGPT', 'TestSiteName' => 'ALT (SGPT)', 'TestType' => 'TEST', 'Description' => 'Alanine Aminotransferase', 'SeqScr' => '140', 'SeqRpt' => '140', 'IndentLeft' => '1', 'isVisibleScr' => '1', 'isVisibleRpt' => '1', 'isCountStat' => '1', 'DisciplineID' => '2', 'DepartmentID' => '2', 'ResultType' => 'NMRIC', 'RefType' => 'RANGE', 'VSet' => '', 'ReqQty' => '300', 'ReqQtyUnit' => 'uL', 'Unit1' => 'U/L', 'Factor' => '0.017', 'Unit2' => 'ukat/L', 'Decimal' => '0', 'Method' => 'IFCC', 'CreateDate' => "$now"];
    $this->db->table('testdefsite')->insert($data);
    $tIDs['SGPT'] = $this->db->insertID();

    $data = ['SiteID' => '1', 'TestSiteCode' => 'CHOL', 'TestSiteName' => 'Total Cholesterol', 'TestType' => 'TEST', 'Description' => 'Kolesterol Total', 'SeqScr' => '150', 'SeqRpt' => '150', 'IndentLeft' => '1', 'isVisibleScr' => '1', 'isVisibleRpt' => '1', 'isCountStat' => '1', 'DisciplineID' => '2', 'DepartmentID' => '2', 'ResultType' => 'NMRIC', 'RefType' => 'RANGE', 'VSet' => '', 'ReqQty' => '300', 'ReqQtyUnit' => 'uL', 'Unit1' => 'mg/dL', 'Factor' => '', 'Unit2' => '', 'Decimal' => '0', 'Method' => 'Enzymatic', 'CreateDate' => "$now"];
    $this->db->table('testdefsite')->insert($data);
    $tIDs['CHOL'] = $this->db->insertID();

    $data = ['SiteID' => '1', 'TestSiteCode' => 'TG', 'TestSiteName' => 'Triglycerides', 'TestType' => 'TEST', 'Description' => 'Trigliserida', 'SeqScr' => '160', 'SeqRpt' => '160', 'IndentLeft' => '1', 'isVisibleScr' => '1', 'isVisibleRpt' => '1', 'isCountStat' => '1', 'DisciplineID' => '2', 'DepartmentID' => '2', 'ResultType' => 'NMRIC', 'RefType' => 'RANGE', 'VSet' => '', 'ReqQty' => '300', 'ReqQtyUnit' => 'uL', 'Unit1' => 'mg/dL', 'Factor' => '', 'Unit2' => '', 'Decimal' => '0', 'Method' => 'GPO-PAP', 'CreateDate' => "$now"];
    $this->db->table('testdefsite')->insert($data);
    $tIDs['TG'] = $this->db->insertID();

    $data = ['SiteID' => '1', 'TestSiteCode' => 'HDL', 'TestSiteName' => 'HDL Cholesterol', 'TestType' => 'TEST', 'Description' => 'Kolesterol HDL', 'SeqScr' => '170', 'SeqRpt' => '170', 'IndentLeft' => '1', 'isVisibleScr' => '1', 'isVisibleRpt' => '1', 'isCountStat' => '1', 'DisciplineID' => '2', 'DepartmentID' => '2', 'ResultType' => 'NMRIC', 'RefType' => 'RANGE', 'VSet' => '', 'ReqQty' => '300', 'ReqQtyUnit' => 'uL', 'Unit1' => 'mg/dL', 'Factor' => '', 'Unit2' => '', 'Decimal' => '0', 'Method' => 'Direct', 'CreateDate' => "$now"];
    $this->db->table('testdefsite')->insert($data);
    $tIDs['HDL'] = $this->db->insertID();

    $data = ['SiteID' => '1', 'TestSiteCode' => 'LDL', 'TestSiteName' => 'LDL Cholesterol', 'TestType' => 'TEST', 'Description' => 'Kolesterol LDL', 'SeqScr' => '180', 'SeqRpt' => '180', 'IndentLeft' => '1', 'isVisibleScr' => '1', 'isVisibleRpt' => '1', 'isCountStat' => '1', 'DisciplineID' => '2', 'DepartmentID' => '2', 'ResultType' => 'NMRIC', 'RefType' => 'RANGE', 'VSet' => '', 'ReqQty' => '300', 'ReqQtyUnit' => 'uL', 'Unit1' => 'mg/dL', 'Factor' => '', 'Unit2' => '', 'Decimal' => '0', 'Method' => 'Direct', 'CreateDate' => "$now"];
    $this->db->table('testdefsite')->insert($data);
    $tIDs['LDL'] = $this->db->insertID();

    $data = ['SiteID' => '1', 'TestSiteCode' => 'TBIL', 'TestSiteName' => 'Total Bilirubin', 'TestType' => 'TEST', 'Description' => 'Bilirubin Total', 'SeqScr' => '185', 'SeqRpt' => '185', 'IndentLeft' => '1', 'isVisibleScr' => '1', 'isVisibleRpt' => '1', 'isCountStat' => '1', 'DisciplineID' => '2', 'DepartmentID' => '2', 'ResultType' => 'NMRIC', 'RefType' => 'RANGE', 'VSet' => '', 'ReqQty' => '300', 'ReqQtyUnit' => 'uL', 'Unit1' => 'mg/dL', 'Factor' => '', 'Unit2' => '', 'Decimal' => '2', 'Method' => 'Diazo', 'CreateDate' => "$now"];
    $this->db->table('testdefsite')->insert($data);
    $tIDs['TBIL'] = $this->db->insertID();

    $data = ['SiteID' => '1', 'TestSiteCode' => 'DBIL', 'TestSiteName' => 'Direct Bilirubin', 'TestType' => 'TEST', 'Description' => 'Bilirubin Direk', 'SeqScr' => '186', 'SeqRpt' => '186', 'IndentLeft' => '1', 'isVisibleScr' => '1', 'isVisibleRpt' => '1', 'isCountStat' => '1', 'DisciplineID' => '2', 'DepartmentID' => '2', 'ResultType' => 'NMRIC', 'RefType' => 'RANGE', 'VSet' => '', 'ReqQty' => '300', 'ReqQtyUnit' => 'uL', 'Unit1' => 'mg/dL', 'Factor' => '', 'Unit2' => '', 'Decimal' => '2', 'Method' => 'Diazo', 'CreateDate' => "$now"];
    $this->db->table('testdefsite')->insert($data);
    $tIDs['DBIL'] = $this->db->insertID();

    // CALC: Chemistry Calculated Tests
    $data = ['SiteID' => '1', 'TestSiteCode' => 'EGFR', 'TestSiteName' => 'eGFR (CKD-EPI)', 'TestType' => 'CALC', 'Description' => 'Estimated Glomerular Filtration Rate', 'SeqScr' => '190', 'SeqRpt' => '190', 'IndentLeft' => '1', 'isVisibleScr' => '1', 'isVisibleRpt' => '1', 'isCountStat' => '0', 'CreateDate' => "$now"];
    $this->db->table('testdefsite')->insert($data);
    $tIDs['EGFR'] = $this->db->insertID();
    $data = ['TestSiteID' => $tIDs['EGFR'], 'DisciplineID' => '2', 'DepartmentID' => '2', 'FormulaCode' => '142 * (({CREA}/{KAPPA}) < 1 ? ({CREA}/{KAPPA}) : 1) ** {ALPHA} * (({CREA}/{KAPPA}) > 1 ? ({CREA}/{KAPPA}) : 1) ** -1.200 * (0.9938 ** {AGE}) * {SEXFAC}', 'RefType' => 'RANGE', 'Unit1' => 'mL/min/1.73m2', 'Factor' => '', 'Unit2' => '', 'Decimal' => '0', 'CreateDate' => "$now"];
    $this->db->table('testdefcal')->insert($data);

    $data = ['SiteID' => '1', 'TestSiteCode' => 'LDLCALC', 'TestSiteName' => 'LDL Cholesterol (Calculated)', 'TestType' => 'CALC', 'Description' => 'Friedewald formula: TC - HDL - (TG/5)', 'SeqScr' => '200', 'SeqRpt' => '200', 'IndentLeft' => '1', 'isVisibleScr' => '1', 'isVisibleRpt' => '1', 'isCountStat' => '0', 'CreateDate' => "$now"];
    $this->db->table('testdefsite')->insert($data);
    $tIDs['LDLCALC'] = $this->db->insertID();
    $data = ['TestSiteID' => $tIDs['LDLCALC'], 'DisciplineID' => '2', 'DepartmentID' => '2', 'FormulaCode' => '{CHOL} - {HDL} - ({TG}/5)', 'RefType' => 'RANGE', 'Unit1' => 'mg/dL', 'Factor' => '', 'Unit2' => '', 'Decimal' => '0', 'CreateDate' => "$now"];
    $this->db->table('testdefcal')->insert($data);

    $data = ['SiteID' => '1', 'TestSiteCode' => 'IBIL', 'TestSiteName' => 'Indirect Bilirubin', 'TestType' => 'CALC', 'Description' => 'Bilirubin Indirek: TBIL - DBIL', 'SeqScr' => '210', 'SeqRpt' => '210', 'IndentLeft' => '1', 'isVisibleScr' => '1', 'isVisibleRpt' => '1', 'isCountStat' => '0', 'CreateDate' => "$now"];
    $this->db->table('testdefsite')->insert($data);
    $tIDs['IBIL'] = $this->db->insertID();
    $data = ['TestSiteID' => $tIDs['IBIL'], 'DisciplineID' => '2', 'DepartmentID' => '2', 'FormulaCode' => '{TBIL} - {DBIL}', 'RefType' => 'RANGE', 'Unit1' => 'mg/dL', 'Factor' => '', 'Unit2' => '', 'Decimal' => '2', 'CreateDate' => "$now"];
    $this->db->table('testdefcal')->insert($data);

    // CALC dependencies are grouped via testdefgrp
    $this->db->table('testdefgrp')->insertBatch([
      ['TestSiteID' => $tIDs['EGFR'], 'Member' => $tIDs['CREA'], 'CreateDate' => "$now"],
      ['TestSiteID' => $tIDs['LDLCALC'], 'Member' => $tIDs['CHOL'], 'CreateDate' => "$now"],
      ['TestSiteID' => $tIDs['LDLCALC'], 'Member' => $tIDs['HDL'], 'CreateDate' => "$now"],
      ['TestSiteID' => $tIDs['LDLCALC'], 'Member' => $tIDs['TG'], 'CreateDate' => "$now"],
      ['TestSiteID' => $tIDs['IBIL'], 'Member' => $tIDs['TBIL'], 'CreateDate' => "$now"],
      ['TestSiteID' => $tIDs['IBIL'], 'Member' => $tIDs['DBIL'], 'CreateDate' => "$now"],
    ]);

    // Add Chemistry Group members now that tests are defined
    $this->db->table('testdefgrp')->insertBatch([
      ['TestSiteID' => $tIDs['LIPID'], 'Member' => $tIDs['CHOL'], 'CreateDate' => "$now"],
      ['TestSiteID' => $tIDs['LIPID'], 'Member' => $tIDs['TG'], 'CreateDate' => "$now"],
      ['TestSiteID' => $tIDs['LIPID'], 'Member' => $tIDs['HDL'], 'CreateDate' => "$now"],
      ['TestSiteID' => $tIDs['LIPID'], 'Member' => $tIDs['LDL'], 'CreateDate' => "$now"],
      ['TestSiteID' => $tIDs['LIPID'], 'Member' => $tIDs['LDLCALC'], 'CreateDate' => "$now"]
    ]);

    $this->db->table('testdefgrp')->insertBatch([
      ['TestSiteID' => $tIDs['LFT'], 'Member' => $tIDs['SGOT'], 'CreateDate' => "$now"],
      ['TestSiteID' => $tIDs['LFT'], 'Member' => $tIDs['SGPT'], 'CreateDate' => "$now"],
      ['TestSiteID' => $tIDs['LFT'], 'Member' => $tIDs['TBIL'], 'CreateDate' => "$now"],
      ['TestSiteID' => $tIDs['LFT'], 'Member' => $tIDs['DBIL'], 'CreateDate' => "$now"],
      ['TestSiteID' => $tIDs['LFT'], 'Member' => $tIDs['IBIL'], 'CreateDate' => "$now"]
    ]);

    $this->db->table('testdefgrp')->insertBatch([
      ['TestSiteID' => $tIDs['RFT'], 'Member' => $tIDs['UREA'], 'CreateDate' => "$now"],
      ['TestSiteID' => $tIDs['RFT'], 'Member' => $tIDs['CREA'], 'CreateDate' => "$now"],
      ['TestSiteID' => $tIDs['RFT'], 'Member' => $tIDs['EGFR'], 'CreateDate' => "$now"]
    ]);

    // ========================================
    // DEPARTMENT 4 - URINALYSIS (Discipline 4)
    // Order: GROUP (<100) → PARAM (<100) → TEST (100+) → CALC (100+)
    // ========================================

    // GROUP: (none for Urinalysis in current setup)

    // PARAM: (none for Urinalysis)

    // TEST: Urinalysis Tests
    $data = ['SiteID' => '1', 'TestSiteCode' => 'UCOLOR', 'TestSiteName' => 'Urine Color', 'TestType' => 'TEST', 'Description' => 'Warna Urine', 'SeqScr' => '100', 'SeqRpt' => '100', 'IndentLeft' => '1', 'isVisibleScr' => '1', 'isVisibleRpt' => '1', 'isCountStat' => '1', 'DisciplineID' => '4', 'DepartmentID' => '4', 'ResultType' => 'VSET', 'RefType' => 'VSET', 'VSet' => '1001', 'ReqQty' => '10', 'ReqQtyUnit' => 'mL', 'Unit1' => '', 'Factor' => '', 'Unit2' => '', 'Decimal' => '', 'Method' => 'Visual', 'CreateDate' => "$now"];
    $this->db->table('testdefsite')->insert($data);
    $tIDs['UCOLOR'] = $this->db->insertID();

    $data = ['SiteID' => '1', 'TestSiteCode' => 'UGLUC', 'TestSiteName' => 'Urine Glucose', 'TestType' => 'TEST', 'Description' => 'Glukosa Urine', 'SeqScr' => '110', 'SeqRpt' => '110', 'IndentLeft' => '1', 'isVisibleScr' => '1', 'isVisibleRpt' => '1', 'isCountStat' => '1', 'DisciplineID' => '4', 'DepartmentID' => '4', 'ResultType' => 'VSET', 'RefType' => 'VSET', 'VSet' => '1002', 'ReqQty' => '10', 'ReqQtyUnit' => 'mL', 'Unit1' => '', 'Factor' => '', 'Unit2' => '', 'Decimal' => '', 'Method' => 'Dipstick', 'CreateDate' => "$now"];
    $this->db->table('testdefsite')->insert($data);
    $tIDs['UGLUC'] = $this->db->insertID();

    $data = ['SiteID' => '1', 'TestSiteCode' => 'UPROT', 'TestSiteName' => 'Urine Protein', 'TestType' => 'TEST', 'Description' => 'Protein Urine', 'SeqScr' => '120', 'SeqRpt' => '120', 'IndentLeft' => '1', 'isVisibleScr' => '1', 'isVisibleRpt' => '1', 'isCountStat' => '1', 'DisciplineID' => '4', 'DepartmentID' => '4', 'ResultType' => 'VSET', 'RefType' => 'VSET', 'VSet' => '1003', 'ReqQty' => '10', 'ReqQtyUnit' => 'mL', 'Unit1' => '', 'Factor' => '', 'Unit2' => '', 'Decimal' => '', 'Method' => 'Dipstick', 'CreateDate' => "$now"];
    $this->db->table('testdefsite')->insert($data);
    $tIDs['UPROT'] = $this->db->insertID();

    $data = ['SiteID' => '1', 'TestSiteCode' => 'PH', 'TestSiteName' => 'Urine pH', 'TestType' => 'TEST', 'Description' => 'pH Urine', 'SeqScr' => '130', 'SeqRpt' => '130', 'IndentLeft' => '1', 'isVisibleScr' => '1', 'isVisibleRpt' => '1', 'isCountStat' => '1', 'DisciplineID' => '4', 'DepartmentID' => '4', 'ResultType' => 'NMRIC', 'RefType' => 'RANGE', 'VSet' => '', 'ReqQty' => '10', 'ReqQtyUnit' => 'mL', 'Unit1' => '', 'Factor' => '', 'Unit2' => '', 'Decimal' => '1', 'Method' => 'Dipstick', 'CreateDate' => "$now"];
    $this->db->table('testdefsite')->insert($data);
    $tIDs['PH'] = $this->db->insertID();

    // CALC: (none for Urinalysis)

    // ========================================
    // DEPARTMENT 10 - GENERAL (Discipline 10)
    // Order: GROUP (<100) → PARAM (<100) → TEST (100+) → CALC (100+)
    // ========================================

    // GROUP: (none for General)

    // PARAM: General Parameters (< 100)
    $data = ['SiteID' => '1', 'TestSiteCode' => 'HEIGHT', 'TestSiteName' => 'Height', 'TestType' => 'PARAM', 'Description' => 'Tinggi Badan', 'SeqScr' => '10', 'SeqRpt' => '10', 'IndentLeft' => '0', 'isVisibleScr' => '1', 'isVisibleRpt' => '0', 'isCountStat' => '0', 'DisciplineID' => '10', 'DepartmentID' => '', 'ResultType' => 'NMRIC', 'RefType' => '', 'VSet' => '', 'ReqQty' => '', 'ReqQtyUnit' => '', 'Unit1' => 'cm', 'Factor' => '', 'Unit2' => '', 'Decimal' => '0', 'Method' => '', 'CreateDate' => "$now"];
    $this->db->table('testdefsite')->insert($data);
    $tIDs['HEIGHT'] = $this->db->insertID();

    $data = ['SiteID' => '1', 'TestSiteCode' => 'WEIGHT', 'TestSiteName' => 'Weight', 'TestType' => 'PARAM', 'Description' => 'Berat Badan', 'SeqScr' => '20', 'SeqRpt' => '20', 'IndentLeft' => '0', 'isVisibleScr' => '1', 'isVisibleRpt' => '0', 'isCountStat' => '0', 'DisciplineID' => '10', 'DepartmentID' => '', 'ResultType' => 'NMRIC', 'RefType' => '', 'VSet' => '', 'ReqQty' => '', 'ReqQtyUnit' => '', 'Unit1' => 'kg', 'Factor' => '', 'Unit2' => '', 'Decimal' => '1', 'Method' => '', 'CreateDate' => "$now"];
    $this->db->table('testdefsite')->insert($data);
    $tIDs['WEIGHT'] = $this->db->insertID();

    $data = ['SiteID' => '1', 'TestSiteCode' => 'AGE', 'TestSiteName' => 'Age', 'TestType' => 'PARAM', 'Description' => 'Usia', 'SeqScr' => '30', 'SeqRpt' => '30', 'IndentLeft' => '0', 'isVisibleScr' => '1', 'isVisibleRpt' => '0', 'isCountStat' => '0', 'DisciplineID' => '10', 'DepartmentID' => '', 'ResultType' => 'NMRIC', 'RefType' => '', 'VSet' => '', 'ReqQty' => '', 'ReqQtyUnit' => '', 'Unit1' => 'years', 'Factor' => '', 'Unit2' => '', 'Decimal' => '0', 'Method' => '', 'CreateDate' => "$now"];
    $this->db->table('testdefsite')->insert($data);
    $tIDs['AGE'] = $this->db->insertID();

    $data = ['SiteID' => '1', 'TestSiteCode' => 'ALPHA', 'TestSiteName' => 'Alpha', 'TestType' => 'PARAM', 'Description' => 'eGFR Alpha', 'SeqScr' => '35', 'SeqRpt' => '35', 'IndentLeft' => '0', 'isVisibleScr' => '1', 'isVisibleRpt' => '0', 'isCountStat' => '0', 'DisciplineID' => '10', 'DepartmentID' => '', 'ResultType' => 'NMRIC', 'RefType' => '', 'VSet' => '', 'ReqQty' => '', 'ReqQtyUnit' => '', 'Unit1' => '', 'Factor' => '', 'Unit2' => '', 'Decimal' => '3', 'Method' => '', 'CreateDate' => "$now"];
    $this->db->table('testdefsite')->insert($data);
    $tIDs['ALPHA'] = $this->db->insertID();

    $data = ['SiteID' => '1', 'TestSiteCode' => 'KAPPA', 'TestSiteName' => 'Kappa', 'TestType' => 'PARAM', 'Description' => 'eGFR Kappa', 'SeqScr' => '36', 'SeqRpt' => '36', 'IndentLeft' => '0', 'isVisibleScr' => '1', 'isVisibleRpt' => '0', 'isCountStat' => '0', 'DisciplineID' => '10', 'DepartmentID' => '', 'ResultType' => 'NMRIC', 'RefType' => '', 'VSet' => '', 'ReqQty' => '', 'ReqQtyUnit' => '', 'Unit1' => '', 'Factor' => '', 'Unit2' => '', 'Decimal' => '1', 'Method' => '', 'CreateDate' => "$now"];
    $this->db->table('testdefsite')->insert($data);
    $tIDs['KAPPA'] = $this->db->insertID();

    $data = ['SiteID' => '1', 'TestSiteCode' => 'SEXFAC', 'TestSiteName' => 'Sex Factor', 'TestType' => 'PARAM', 'Description' => 'eGFR Sex Factor', 'SeqScr' => '37', 'SeqRpt' => '37', 'IndentLeft' => '0', 'isVisibleScr' => '1', 'isVisibleRpt' => '0', 'isCountStat' => '0', 'DisciplineID' => '10', 'DepartmentID' => '', 'ResultType' => 'NMRIC', 'RefType' => '', 'VSet' => '', 'ReqQty' => '', 'ReqQtyUnit' => '', 'Unit1' => '', 'Factor' => '', 'Unit2' => '', 'Decimal' => '3', 'Method' => '', 'CreateDate' => "$now"];
    $this->db->table('testdefsite')->insert($data);
    $tIDs['SEXFAC'] = $this->db->insertID();

    $data = ['SiteID' => '1', 'TestSiteCode' => 'SYSTL', 'TestSiteName' => 'Systolic BP', 'TestType' => 'PARAM', 'Description' => 'Tekanan Darah Sistolik', 'SeqScr' => '40', 'SeqRpt' => '40', 'IndentLeft' => '0', 'isVisibleScr' => '1', 'isVisibleRpt' => '0', 'isCountStat' => '0', 'DisciplineID' => '10', 'DepartmentID' => '', 'ResultType' => 'NMRIC', 'RefType' => '', 'VSet' => '', 'ReqQty' => '', 'ReqQtyUnit' => '', 'Unit1' => 'mmHg', 'Factor' => '', 'Unit2' => '', 'Decimal' => '0', 'Method' => '', 'CreateDate' => "$now"];
    $this->db->table('testdefsite')->insert($data);
    $tIDs['SYSTL'] = $this->db->insertID();

    $data = ['SiteID' => '1', 'TestSiteCode' => 'DIASTL', 'TestSiteName' => 'Diastolic BP', 'TestType' => 'PARAM', 'Description' => 'Tekanan Darah Diastolik', 'SeqScr' => '50', 'SeqRpt' => '50', 'IndentLeft' => '0', 'isVisibleScr' => '1', 'isVisibleRpt' => '0', 'isCountStat' => '0', 'DisciplineID' => '10', 'DepartmentID' => '', 'ResultType' => 'NMRIC', 'RefType' => '', 'VSet' => '', 'ReqQty' => '', 'ReqQtyUnit' => '', 'Unit1' => 'mmHg', 'Factor' => '', 'Unit2' => '', 'Decimal' => '0', 'Method' => '', 'CreateDate' => "$now"];
    $this->db->table('testdefsite')->insert($data);
    $tIDs['DIASTL'] = $this->db->insertID();

    // TEST: (none for General)

    // CALC: BMI (>= 100)
    $data = ['SiteID' => '1', 'TestSiteCode' => 'BMI', 'TestSiteName' => 'Body Mass Index', 'TestType' => 'CALC', 'Description' => 'Indeks Massa Tubuh - weight/(height^2)', 'SeqScr' => '100', 'SeqRpt' => '100', 'IndentLeft' => '0', 'isVisibleScr' => '1', 'isVisibleRpt' => '1', 'isCountStat' => '0', 'CreateDate' => "$now"];
    $this->db->table('testdefsite')->insert($data);
    $tIDs['BMI'] = $this->db->insertID();
    $data = ['TestSiteID' => $tIDs['BMI'], 'DisciplineID' => '10', 'DepartmentID' => '', 'FormulaCode' => '{WEIGHT} / (({HEIGHT}/100) * ({HEIGHT}/100))', 'RefType' => 'RANGE', 'Unit1' => 'kg/m2', 'Factor' => '', 'Unit2' => '', 'Decimal' => '1', 'CreateDate' => "$now"];
    $this->db->table('testdefcal')->insert($data);

    $this->db->table('testdefgrp')->insertBatch([
      ['TestSiteID' => $tIDs['BMI'], 'Member' => $tIDs['WEIGHT'], 'CreateDate' => "$now"],
      ['TestSiteID' => $tIDs['BMI'], 'Member' => $tIDs['HEIGHT'], 'CreateDate' => "$now"],
      ['TestSiteID' => $tIDs['EGFR'], 'Member' => $tIDs['AGE'], 'CreateDate' => "$now"],
      ['TestSiteID' => $tIDs['EGFR'], 'Member' => $tIDs['ALPHA'], 'CreateDate' => "$now"],
      ['TestSiteID' => $tIDs['EGFR'], 'Member' => $tIDs['KAPPA'], 'CreateDate' => "$now"],
      ['TestSiteID' => $tIDs['EGFR'], 'Member' => $tIDs['SEXFAC'], 'CreateDate' => "$now"],
    ]);

    // ========================================
    // RULES: Auto-fill ALPHA/KAPPA by sex
    // ========================================
    $ruleExpr = new RuleExpressionService();
    $ruleDefs = [
      [
        'RuleCode' => 'ALPHA_SEX',
        'RuleName' => 'Set ALPHA from sex',
        'Description' => 'Set ALPHA based on patient sex (M=-0.302, F/other=-0.241)',
        'EventCode' => 'test_created',
        'TestSiteID' => $tIDs['ALPHA'],
        'Expr' => "if(sex('M'); set_result(-0.302); set_result(-0.241))",
      ],
      [
        'RuleCode' => 'KAPPA_SEX',
        'RuleName' => 'Set KAPPA from sex',
        'Description' => 'Set KAPPA based on patient sex (M=0.9, F/other=0.7)',
        'EventCode' => 'test_created',
        'TestSiteID' => $tIDs['KAPPA'],
        'Expr' => "if(sex('M'); set_result(0.9); set_result(0.7))",
      ],
      [
        'RuleCode' => 'SEXFAC_SEX',
        'RuleName' => 'Set SEXFAC from sex',
        'Description' => 'Set SEXFAC based on patient sex (F=1.012, M/other=1)',
        'EventCode' => 'test_created',
        'TestSiteID' => $tIDs['SEXFAC'],
        'Expr' => "if(sex('F'); set_result(1.012); set_result(1))",
      ],
    ];

    foreach ($ruleDefs as $ruleDef) {
      $compiled = $ruleExpr->compile($ruleDef['Expr']);
      $data = [
        'RuleCode' => $ruleDef['RuleCode'],
        'RuleName' => $ruleDef['RuleName'],
        'Description' => $ruleDef['Description'],
        'EventCode' => $ruleDef['EventCode'],
        'ConditionExpr' => $ruleDef['Expr'],
        'ConditionExprCompiled' => json_encode($compiled),
        'CreateDate' => $now,
        'StartDate' => null,
        'EndDate' => null,
      ];
      $this->db->table('ruledef')->insert($data);
      $ruleID = $this->db->insertID();

      $this->db->table('testrule')->insert([
        'RuleID' => $ruleID,
        'TestSiteID' => $ruleDef['TestSiteID'],
        'CreateDate' => $now,
      ]);
    }

    // ========================================
    // TEST MAP - Specimen Mapping
    // ========================================
    
    // Get container IDs (inserted by SpecimenSeeder in order)
    $conSST = 1;        // SST (Serum Separator Tube)
    $conEDTA = 9;       // EDTA - Hematology
    $conCitrate = 10;   // Citrate - Koagulasi
    $conPotUrin = 12;   // Pot Urin
    $conUrine = 13;     // Urine Container
    
    // Workstation IDs from OrganizationSeeder
    $wsHAuto = 1;       // Hematologi Auto
    $wsCAuto = 3;       // Kimia Auto
    $wsIAuto = 6;       // Imunologi Auto
    $wsUAuto = 8;       // Urin Auto
    
    // Equipment IDs from OrganizationSeeder
    $instHematology = 1;   // Sysmex XN-1000
    $instChemistry = 2;    // Roche Cobas C501
    $instImmunology = 3;   // Architect i2000
    $instUrinalysis = 4;   // Urisys 1100
    
    // Helper to get or create TestMap header ID (relationship only)
    $getTestMapID = function($hostType, $hostID, $clientType, $clientID) use (&$testMapHeaders, &$now) {
      $key = "{$hostType}_{$hostID}_{$clientType}_{$clientID}";
      if (!isset($testMapHeaders[$key])) {
        $data = [
          'HostType' => $hostType,
          'HostID' => $hostID,
          'ClientType' => $clientType,
          'ClientID' => $clientID,
          'CreateDate' => $now
        ];
        $this->db->table('testmap')->insert($data);
        $testMapHeaders[$key] = $this->db->insertID();
      }
      return $testMapHeaders[$key];
    };
    
    // Helper to add detail record
    $addDetail = function($testMapID, $hostTestCode, $hostTestName, $conDefID, $clientTestCode, $clientTestName) use (&$testMapDetails, &$now) {
      $testMapDetails[] = [
        'TestMapID' => $testMapID,
        'HostTestCode' => $hostTestCode,
        'HostTestName' => $hostTestName,
        'ConDefID' => $conDefID,
        'ClientTestCode' => $clientTestCode,
        'ClientTestName' => $clientTestName,
        'CreateDate' => $now
      ];
    };
    
    // Test mappings configuration
    $testMappings = [
      // Hematology: Site → HAUTO → Sysmex (EDTA)
      [
        'tests' => ['HB', 'HCT', 'RBC', 'WBC', 'PLT', 'MCV', 'MCH', 'MCHC'],
        'panels' => ['CBC'],
        'siteToWs' => ['ws' => $wsHAuto, 'con' => null],
        'wsToInst' => ['ws' => $wsHAuto, 'inst' => $instHematology, 'con' => $conEDTA],
      ],
      // Chemistry: Site → CAUTO → Cobas (SST)
      [
        'tests' => ['GLU', 'CREA', 'UREA', 'SGOT', 'SGPT', 'CHOL', 'TG', 'HDL', 'LDL', 'TBIL', 'DBIL'],
        'panels' => ['LIPID', 'LFT', 'RFT'],
        'siteToWs' => ['ws' => $wsCAuto, 'con' => null],
        'wsToInst' => ['ws' => $wsCAuto, 'inst' => $instChemistry, 'con' => $conSST],
      ],
      // Calculated: Site → CAUTO → Cobas (SST)
      [
        'tests' => ['EGFR', 'LDLCALC', 'IBIL'],
        'panels' => [],
        'siteToWs' => ['ws' => $wsCAuto, 'con' => null],
        'wsToInst' => ['ws' => $wsCAuto, 'inst' => $instChemistry, 'con' => $conSST],
      ],
      // Urinalysis: Site → UAUTO → Urisys (Pot Urin)
      [
        'tests' => ['UCOLOR', 'UGLUC', 'UPROT', 'PH'],
        'panels' => [],
        'siteToWs' => ['ws' => $wsUAuto, 'con' => null],
        'wsToInst' => ['ws' => $wsUAuto, 'inst' => $instUrinalysis, 'con' => $conPotUrin],
      ],
      // BMI: Site → CAUTO (no instrument mapping - calculated)
      [
        'tests' => ['BMI'],
        'panels' => [],
        'siteToWs' => ['ws' => $wsCAuto, 'con' => null],
        'wsToInst' => null,
      ],
    ];

    // Load entity types for mapping
    $entitySite = $this->getEntityType('SITE') ?? 'SITE';
    $entityWst = $this->getEntityType('WST') ?? 'WST';
    $entityInst = $this->getEntityType('INST') ?? 'INST';

    foreach ($testMappings as $mapping) {
      // Site → Workstation mapping
      $testMapSiteWsID = $getTestMapID($entitySite, '1', $entityWst, (string)$mapping['siteToWs']['ws']);
      foreach ($mapping['tests'] as $testCode) {
        $addDetail($testMapSiteWsID, $testCode, $testCode, $mapping['siteToWs']['con'], $testCode, $testCode);
      }
      foreach ($mapping['panels'] as $panelCode) {
        $addDetail($testMapSiteWsID, $panelCode, $panelCode, $mapping['siteToWs']['con'], $panelCode, $panelCode);
      }

      // Workstation → Instrument mapping
      if ($mapping['wsToInst'] !== null) {
        $testMapWsInstID = $getTestMapID($entityWst, (string)$mapping['wsToInst']['ws'], $entityInst, (string)$mapping['wsToInst']['inst']);
        foreach ($mapping['tests'] as $testCode) {
          $addDetail($testMapWsInstID, $testCode, $testCode, $mapping['wsToInst']['con'], $testCode, $testCode);
        }
        foreach ($mapping['panels'] as $panelCode) {
          $addDetail($testMapWsInstID, $panelCode, $panelCode, $mapping['wsToInst']['con'], $panelCode, $panelCode);
        }
      }
    }
    
    // Insert all testmapdetail records
    if (!empty($testMapDetails)) {
      $this->db->table('testmapdetail')->insertBatch($testMapDetails);
    }
  }
}
