<?php

namespace App\Models\Test;

use App\Models\BaseModel;
use App\Libraries\ValueSet;
use App\Libraries\TestValidationService;

class TestDefSiteModel extends BaseModel {
  protected $table      = 'testdefsite';
  protected $primaryKey = 'TestSiteID';
  protected $allowedFields = [
    'SiteID', 
    'TestSiteCode', 'TestSiteName', 'TestType', 'Description', 
    'DisciplineID', 'DepartmentID',
    'ResultType', 'RefType', 'Vset',
    'Unit1', 'Factor', 'Unit2', 'Decimal',
    'ReqQty', 'ReqQtyUnit', 'CollReq', 'Method', 'ExpectedTAT',
    'SeqScr', 'SeqRpt', 'IndentLeft', 'FontStyle', 'isVisibleScr', 'isVisibleRpt', 
    'isCountStat', 'Level', 'isRequestable',
    'CreateDate', 'StartDate','EndDate'
  ];
   
  protected $useTimestamps = true;
  protected $createdField = 'CreateDate';
  protected $updatedField = 'StartDate';
  protected $useSoftDeletes = true;
  protected $deletedField = "EndDate";

  public function getTests($siteId = null, $testType = null, $visibleScr = null, $visibleRpt = null, $search = null, $page = 1, $perPage = 20) {
    $builder = $this->select("testdefsite.TestSiteID, testdefsite.TestSiteCode, testdefsite.TestSiteName, testdefsite.TestType, 
                  testdefsite.SeqScr, testdefsite.SeqRpt, testdefsite.isVisibleScr, testdefsite.isVisibleRpt,
                  testdefsite.isCountStat, testdefsite.StartDate, testdefsite.EndDate")
      ->where('testdefsite.EndDate IS NULL');
    
    if ($siteId) {
        $builder->where('testdefsite.SiteID', $siteId);
    }
    
    if ($testType) {
        $builder->where('testdefsite.TestType', $testType);
    }
    
    if ($visibleScr !== null) {
        $builder->where('testdefsite.isVisibleScr', $visibleScr);
    }
    
    if ($visibleRpt !== null) {
        $builder->where('testdefsite.isVisibleRpt', $visibleRpt);
    }
    
    if ($search) {
        $builder->groupStart()
            ->like('testdefsite.TestSiteCode', $search)
            ->orLike('testdefsite.TestSiteName', $search)
            ->groupEnd();
    }
    
    // Get total count before pagination
    $totalBuilder = clone $builder;
    $total = $totalBuilder->countAllResults();
    
    // Apply pagination
    $offset = ($page - 1) * $perPage;
    $rows = $builder->orderBy('testdefsite.SeqScr', 'ASC')
        ->limit($perPage, $offset)
        ->findAll();
    
    $rows = ValueSet::transformLabels($rows, [
      'TestType' => 'test_type',
    ]);
    
    return [
        'data' => $rows,
        'pagination' => [
            'total' => $total
        ]
    ];
  }

  /**
   * Get tests list with discipline and department info
   */
  public function getTestsWithRelations($filters = []) {
    $builder = $this->db->table('testdefsite')
        ->select(
        "testdefsite.TestSiteID, testdefsite.TestSiteCode, testdefsite.TestSiteName, testdefsite.TestType, 
        testdefsite.SeqScr, testdefsite.SeqRpt, testdefsite.isVisibleScr, testdefsite.isVisibleRpt,
        testdefsite.isCountStat, testdefsite.StartDate, testdefsite.EndDate,
        COALESCE(testdefsite.DisciplineID, cal.DisciplineID) as DisciplineID,
        COALESCE(testdefsite.DepartmentID, cal.DepartmentID) as DepartmentID,
        d.DisciplineName, dept.DepartmentName"
      )
      ->join('testdefcal cal', 'cal.TestSiteID = testdefsite.TestSiteID AND cal.EndDate IS NULL', 'left')
      ->join('discipline d', 'd.DisciplineID = COALESCE(testdefsite.DisciplineID, cal.DisciplineID)', 'left')
      ->join('department dept', 'dept.DepartmentID = COALESCE(testdefsite.DepartmentID, cal.DepartmentID)', 'left')
      ->where('testdefsite.EndDate IS NULL');

    if (!empty($filters['SiteID'])) {
      $builder->where('testdefsite.SiteID', $filters['SiteID']);
    }

    if (!empty($filters['TestType'])) {
      $builder->where('testdefsite.TestType', $filters['TestType']);
    }

    if (isset($filters['isVisibleScr'])) {
      $builder->where('testdefsite.isVisibleScr', $filters['isVisibleScr']);
    }

    if (isset($filters['isVisibleRpt'])) {
      $builder->where('testdefsite.isVisibleRpt', $filters['isVisibleRpt']);
    }

    if (!empty($filters['TestSiteName'])) {
      $builder->like('testdefsite.TestSiteName', $filters['TestSiteName']);
    }

    if (!empty($filters['TestSiteCode'])) {
      $builder->like('testdefsite.TestSiteCode', $filters['TestSiteCode']);
    }

    if (!empty($filters['search'])) {
      $builder->groupStart()
        ->like('testdefsite.TestSiteCode', $filters['search'])
        ->orLike('testdefsite.TestSiteName', $filters['search'])
        ->groupEnd();
    }

    return $builder->orderBy('testdefsite.SeqScr', 'ASC')->get()->getResultArray();
  }

  public function getTest($TestSiteID) {
    $db = \Config\Database::connect();
    
    $row = $this->select("testdefsite.*")
      ->where("testdefsite.TestSiteID", $TestSiteID)
      ->find($TestSiteID);
    
    if (!$row) return null;

    $row = ValueSet::transformLabels([$row], [
      'TestType' => 'test_type',
    ])[0];

    $typeCode = $row['TestType'] ?? '';
    
    if (TestValidationService::isCalc($typeCode)) {
        $row['testdefcal'] = $db->table('testdefcal')
            ->select('testdefcal.*, d.DisciplineName, dept.DepartmentName')
            ->join('discipline d', 'd.DisciplineID=testdefcal.DisciplineID', 'left')
            ->join('department dept', 'dept.DepartmentID=testdefcal.DepartmentID', 'left')
            ->where('testdefcal.TestSiteID', $TestSiteID)
            ->where('testdefcal.EndDate IS NULL')
            ->get()->getResultArray();

    } elseif (TestValidationService::isGroup($typeCode)) {
        $testDefGrpModel = new \App\Models\Test\TestDefGrpModel();
        $row['testdefgrp'] = $testDefGrpModel->getGroupMembers($TestSiteID);

    } elseif (TestValidationService::isTitle($typeCode)) {

    } elseif (TestValidationService::isTechnicalTest($typeCode)) {
        // Technical details are now flattened into the main row
        if ($row['DisciplineID']) {
            $discipline = $db->table('discipline')->where('DisciplineID', $row['DisciplineID'])->get()->getRowArray();
            $row['DisciplineName'] = $discipline['DisciplineName'] ?? null;
        }
        if ($row['DepartmentID']) {
            $department = $db->table('department')->where('DepartmentID', $row['DepartmentID'])->get()->getRowArray();
            $row['DepartmentName'] = $department['DepartmentName'] ?? null;
        }
    }
    
    return $row;
  }

  /**
   * Validate test type combination
   *
   * @param string $testType
   * @param string $resultType
   * @param string $refType
   * @return array ['valid' => bool, 'error' => string|null]
   */
  public function validateTypes(string $testType, string $resultType, string $refType): array
  {
      return TestValidationService::validate($testType, $resultType, $refType);
  }

  /**
   * Check if test needs reference ranges
   *
   * @param string $resultType
   * @return bool
   */
  public function needsReferenceRanges(string $resultType): bool
  {
      return TestValidationService::needsReferenceRanges($resultType);
  }

  /**
   * Get reference table name
   *
   * @param string $resultType
   * @param string $refType
   * @return string|null
   */
  public function getReferenceTable(string $resultType, string $refType): ?string
  {
      return TestValidationService::getReferenceTable($resultType, $refType);
  }

  /**
   * Get test by ID with ValueSet transformation
   *
   * @param int $id
   * @return array|null
   */
  public function getTestById($id)
  {
      $row = $this->db->table('testdefsite')
          ->select('testdefsite.*, d.DisciplineName, dept.DepartmentName')
          ->join('discipline d', 'd.DisciplineID = testdefsite.DisciplineID', 'left')
          ->join('department dept', 'dept.DepartmentID = testdefsite.DepartmentID', 'left')
          ->where('testdefsite.TestSiteID', $id)
          ->where('testdefsite.EndDate IS NULL')
          ->get()
          ->getRowArray();
      
      if (!$row) {
          return null;
      }
      
      $rows = ValueSet::transformLabels([$row], [
          'TestType' => 'test_type',
      ]);
      
      return $rows[0];
  }

}
