<?php
namespace App\Controllers;

use CodeIgniter\API\ResponseTrait;
use App\Controllers\BaseController;

class TestsController extends BaseController
{
    use ResponseTrait;

    protected $db;
    protected $rules;
    protected $model;
    protected $modelCal;
    protected $modelTech;
    protected $modelGrp;
    protected $modelMap;
    protected $modelValueSet;
    protected $modelRefNum;
    protected $modelRefTxt;

    // Valueset ID constants
    const VALUESET_REF_TYPE = 44;        // testdeftech.RefType
    const VALUESET_RANGE_TYPE = 45;      // refnum.RangeType
    const VALUESET_NUM_REF_TYPE = 46;    // refnum.NumRefType
    const VALUESET_TXT_REF_TYPE = 47;    // reftxt.TxtRefType
    const VALUESET_SEX = 3;              // Sex values
    const VALUESET_MATH_SIGN = 41;       // LowSign, HighSign

    public function __construct()
    {
        $this->db = \Config\Database::connect();
        $this->model = new \App\Models\Test\TestDefSiteModel;
        $this->modelCal = new \App\Models\Test\TestDefCalModel;
        $this->modelTech = new \App\Models\Test\TestDefTechModel;
        $this->modelGrp = new \App\Models\Test\TestDefGrpModel;
        $this->modelMap = new \App\Models\Test\TestMapModel;
        $this->modelValueSet = new \App\Models\ValueSet\ValueSetModel;
        $this->modelRefNum = new \App\Models\RefRange\RefNumModel;
        $this->modelRefTxt = new \App\Models\RefRange\RefTxtModel;

        // Validation rules for main test definition
        $this->rules = [
            'TestSiteCode' => 'required|min_length[3]|max_length[6]',
            'TestSiteName' => 'required',
            'TestType' => 'required',
            'SiteID' => 'required'
        ];
    }

    /**
     * GET /v1/tests
     * GET /v1/tests/site
     * List all tests with optional filtering
     */
    public function index()
    {
        $siteId = $this->request->getGet('SiteID');
        $testType = $this->request->getGet('TestType');
        $visibleScr = $this->request->getGet('VisibleScr');
        $visibleRpt = $this->request->getGet('VisibleRpt');
        $keyword = $this->request->getGet('TestSiteName');

        $builder = $this->db->table('testdefsite')
            ->select("testdefsite.TestSiteID, testdefsite.TestSiteCode, testdefsite.TestSiteName, testdefsite.TestType, 
                  testdefsite.SeqScr, testdefsite.SeqRpt, testdefsite.VisibleScr, testdefsite.VisibleRpt,
                  testdefsite.CountStat, testdefsite.StartDate, testdefsite.EndDate,
                  valueset.VValue as TypeCode, valueset.VDesc as TypeName")
            ->join("valueset", "valueset.VID=testdefsite.TestType", "left")
            ->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.VisibleScr', $visibleScr);
        }

        if ($visibleRpt !== null) {
            $builder->where('testdefsite.VisibleRpt', $visibleRpt);
        }

        if ($keyword) {
            $builder->like('testdefsite.TestSiteName', $keyword);
        }

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

        if (empty($rows)) {
            return $this->respond(['status' => 'success', 'message' => "No data.", 'data' => []], 200);
        }
        return $this->respond(['status' => 'success', 'message' => "Data fetched successfully", 'data' => $rows], 200);
    }

    /**
     * GET /v1/tests/{id}
     * GET /v1/tests/site/{id}
     * Get single test by ID with all related details
     */
    public function show($id = null)
    {
        if (!$id)
            return $this->failValidationErrors('TestSiteID is required');

        $row = $this->model->select("testdefsite.*, valueset.VValue as TypeCode, valueset.VDesc as TypeName")
            ->join("valueset", "valueset.VID=testdefsite.TestType", "left")
            ->where("testdefsite.TestSiteID", $id)
            ->find($id);

        if (!$row) {
            return $this->respond(['status' => 'success', 'message' => "No data.", 'data' => null], 200);
        }

        // Load related details based on TestType
        $typeCode = $row['TypeCode'] ?? '';

        if ($typeCode === 'CALC') {
            // Load calculation details
            $row['testdefcal'] = $this->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', $id)
                ->where('testdefcal.EndDate IS NULL')
                ->get()->getResultArray();

            // Load test mappings
            $row['testmap'] = $this->modelMap->where('TestSiteID', $id)->where('EndDate IS NULL')->findAll();

        } elseif ($typeCode === 'GROUP') {
            // Load group members with test details
            $row['testdefgrp'] = $this->db->table('testdefgrp')
                ->select('testdefgrp.*, t.TestSiteCode, t.TestSiteName, t.TestType, vs.VValue as MemberTypeCode')
                ->join('testdefsite t', 't.TestSiteID=testdefgrp.Member', 'left')
                ->join('valueset vs', 'vs.VID=t.TestType', 'left')
                ->where('testdefgrp.TestSiteID', $id)
                ->where('testdefgrp.EndDate IS NULL')
                ->orderBy('testdefgrp.TestGrpID', 'ASC')
                ->get()->getResultArray();

            // Load test mappings
            $row['testmap'] = $this->modelMap->where('TestSiteID', $id)->where('EndDate IS NULL')->findAll();

        } elseif ($typeCode === 'TITLE') {
            // Load test mappings only for TITLE type
            $row['testmap'] = $this->modelMap->where('TestSiteID', $id)->where('EndDate IS NULL')->findAll();

        } else {
            // TEST or PARAM - load technical details
            $row['testdeftech'] = $this->db->table('testdeftech')
                ->select('testdeftech.*, d.DisciplineName, dept.DepartmentName')
                ->join('discipline d', 'd.DisciplineID=testdeftech.DisciplineID', 'left')
                ->join('department dept', 'dept.DepartmentID=testdeftech.DepartmentID', 'left')
                ->where('testdeftech.TestSiteID', $id)
                ->where('testdeftech.EndDate IS NULL')
                ->get()->getResultArray();

            // Load test mappings
            $row['testmap'] = $this->modelMap->where('TestSiteID', $id)->where('EndDate IS NULL')->findAll();

            // Load refnum/reftxt based on RefType
            if (!empty($row['testdeftech'])) {
                $techData = $row['testdeftech'][0];
                $refType = (int) $techData['RefType'];

                // Load refnum for NMRC type (RefType = 1)
                if ($refType === 1) {
                    $refnumData = $this->modelRefNum
                        ->where('TestSiteID', $id)
                        ->where('EndDate IS NULL')
                        ->orderBy('Display', 'ASC')
                        ->findAll();

                    // Add VValue for display
                    $row['refnum'] = array_map(function ($r) {
                        return [
                            'RefNumID' => $r['RefNumID'],
                            'NumRefType' => (int) $r['NumRefType'],
                            'NumRefTypeVValue' => $this->getVValue(46, $r['NumRefType']),
                            'RangeType' => (int) $r['RangeType'],
                            'RangeTypeVValue' => $this->getVValue(45, $r['RangeType']),
                            'Sex' => (int) $r['Sex'],
                            'SexVValue' => $this->getVValue(3, $r['Sex']),
                            'AgeStart' => (int) $r['AgeStart'],
                            'AgeEnd' => (int) $r['AgeEnd'],
                            'LowSign' => $r['LowSign'] !== null ? (int) $r['LowSign'] : null,
                            'LowSignVValue' => $this->getVValue(41, $r['LowSign']),
                            'Low' => $r['Low'] !== null ? (int) $r['Low'] : null,
                            'HighSign' => $r['HighSign'] !== null ? (int) $r['HighSign'] : null,
                            'HighSignVValue' => $this->getVValue(41, $r['HighSign']),
                            'High' => $r['High'] !== null ? (int) $r['High'] : null,
                            'Flag' => $r['Flag']
                        ];
                    }, $refnumData ?? []);

                    $row['numRefTypeOptions'] = $this->getValuesetOptions(46);
                    $row['rangeTypeOptions'] = $this->getValuesetOptions(45);
                }

                // Load reftxt for TEXT type (RefType = 2)
                if ($refType === 2) {
                    $reftxtData = $this->modelRefTxt
                        ->where('TestSiteID', $id)
                        ->where('EndDate IS NULL')
                        ->orderBy('RefTxtID', 'ASC')
                        ->findAll();

                    $row['reftxt'] = array_map(function ($r) {
                        return [
                            'RefTxtID' => $r['RefTxtID'],
                            'TxtRefType' => (int) $r['TxtRefType'],
                            'TxtRefTypeVValue' => $this->getVValue(47, $r['TxtRefType']),
                            'Sex' => (int) $r['Sex'],
                            'SexVValue' => $this->getVValue(3, $r['Sex']),
                            'AgeStart' => (int) $r['AgeStart'],
                            'AgeEnd' => (int) $r['AgeEnd'],
                            'RefTxt' => $r['RefTxt'],
                            'Flag' => $r['Flag']
                        ];
                    }, $reftxtData ?? []);

                    $row['txtRefTypeOptions'] = $this->getValuesetOptions(47);
                }
            }
        }

        // Include valueset options for dropdowns
        $row['refTypeOptions'] = $this->getValuesetOptions(self::VALUESET_REF_TYPE);
        $row['sexOptions'] = $this->getValuesetOptions(self::VALUESET_SEX);
        $row['mathSignOptions'] = $this->getValuesetOptions(self::VALUESET_MATH_SIGN);

        return $this->respond(['status' => 'success', 'message' => "Data fetched successfully", 'data' => $row], 200);
    }

    /**
     * POST /v1/tests
     * POST /v1/tests/site
     * Create new test definition
     */
    public function create()
    {
        $input = $this->request->getJSON(true);

        if (!$this->validateData($input, $this->rules)) {
            return $this->failValidationErrors($this->validator->getErrors());
        }

        $this->db->transStart();

        try {
            // 1. Insert into Main Table (testdefsite)
            $testSiteData = [
                'SiteID' => $input['SiteID'],
                'TestSiteCode' => $input['TestSiteCode'],
                'TestSiteName' => $input['TestSiteName'],
                'TestType' => $input['TestType'],
                'Description' => $input['Description'] ?? null,
                'SeqScr' => $input['SeqScr'] ?? 0,
                'SeqRpt' => $input['SeqRpt'] ?? 0,
                'IndentLeft' => $input['IndentLeft'] ?? 0,
                'FontStyle' => $input['FontStyle'] ?? null,
                'VisibleScr' => $input['VisibleScr'] ?? 1,
                'VisibleRpt' => $input['VisibleRpt'] ?? 1,
                'CountStat' => $input['CountStat'] ?? 1,
                'StartDate' => $input['StartDate'] ?? date('Y-m-d H:i:s')
            ];

            $id = $this->model->insert($testSiteData);
            if (!$id) {
                throw new \Exception("Failed to insert main test definition");
            }

            // 2. Handle Details based on TestType
            $this->handleDetails($id, $input, 'insert');

            $this->db->transComplete();

            if ($this->db->transStatus() === false) {
                return $this->failServerError('Transaction failed');
            }

            return $this->respondCreated([
                'status' => 'created',
                'message' => "Test created successfully",
                'data' => ['TestSiteId' => $id]
            ]);
        } catch (\Exception $e) {
            $this->db->transRollback();
            return $this->failServerError('Something went wrong: ' . $e->getMessage());
        }
    }

    /**
     * PUT/PATCH /v1/tests/{id}
     * PUT/PATCH /v1/tests/site/{id}
     * Update existing test definition
     */
    public function update($id = null)
    {
        $input = $this->request->getJSON(true);

        // Determine ID
        if (!$id && isset($input["TestSiteID"])) {
            $id = $input["TestSiteID"];
        }
        if (!$id) {
            return $this->failValidationErrors('TestSiteID is required.');
        }

        // Verify record exists
        $existing = $this->model->find($id);
        if (!$existing) {
            return $this->failNotFound('Test not found');
        }

        $this->db->transStart();

        try {
            // 1. Update Main Table
            $testSiteData = [];
            $allowedUpdateFields = [
                'TestSiteCode',
                'TestSiteName',
                'TestType',
                'Description',
                'SeqScr',
                'SeqRpt',
                'IndentLeft',
                'FontStyle',
                'VisibleScr',
                'VisibleRpt',
                'CountStat',
                'StartDate'
            ];

            foreach ($allowedUpdateFields as $field) {
                if (isset($input[$field])) {
                    $testSiteData[$field] = $input[$field];
                }
            }

            if (!empty($testSiteData)) {
                $this->model->update($id, $testSiteData);
            }

            // 2. Handle Details
            $this->handleDetails($id, $input, 'update');

            $this->db->transComplete();

            if ($this->db->transStatus() === false) {
                return $this->failServerError('Transaction failed');
            }

            return $this->respond([
                'status' => 'success',
                'message' => "Test updated successfully",
                'data' => ['TestSiteId' => $id]
            ]);
        } catch (\Exception $e) {
            $this->db->transRollback();
            return $this->failServerError('Something went wrong: ' . $e->getMessage());
        }
    }

    /**
     * DELETE /v1/tests/{id}
     * DELETE /v1/tests/site/{id}
     * Soft delete test by setting EndDate
     */
    public function delete($id = null)
    {
        $input = $this->request->getJSON(true);

        // Determine ID
        if (!$id && isset($input["TestSiteID"])) {
            $id = $input["TestSiteID"];
        }
        if (!$id) {
            return $this->failValidationErrors('TestSiteID is required.');
        }

        // Verify record exists
        $existing = $this->model->find($id);
        if (!$existing) {
            return $this->failNotFound('Test not found');
        }

        // Check if already disabled
        if (!empty($existing['EndDate'])) {
            return $this->failValidationErrors('Test is already disabled');
        }

        $this->db->transStart();

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

            // 1. Soft delete main record
            $this->model->update($id, ['EndDate' => $now]);

            // 2. Get TestType to handle related records
            $testType = $existing['TestType'];
            $vs = $this->modelValueSet->find($testType);
            $typeCode = $vs['VValue'] ?? '';

            // 3. Soft delete related records based on TestType
            if ($typeCode === 'CALC') {
                $this->db->table('testdefcal')
                    ->where('TestSiteID', $id)
                    ->update(['EndDate' => $now]);
            } elseif ($typeCode === 'GROUP') {
                $this->db->table('testdefgrp')
                    ->where('TestSiteID', $id)
                    ->update(['EndDate' => $now]);
            } elseif (in_array($typeCode, ['TEST', 'PARAM'])) {
                $this->db->table('testdeftech')
                    ->where('TestSiteID', $id)
                    ->update(['EndDate' => $now]);

                // Soft delete refnum and reftxt records
                $this->modelRefNum->where('TestSiteID', $id)->set('EndDate', $now)->update();
                $this->modelRefTxt->where('TestSiteID', $id)->set('EndDate', $now)->update();
            }

            // 4. Soft delete test mappings
            $this->db->table('testmap')
                ->where('TestSiteID', $id)
                ->update(['EndDate' => $now]);

            $this->db->transComplete();

            if ($this->db->transStatus() === false) {
                return $this->failServerError('Transaction failed');
            }

            return $this->respond([
                'status' => 'success',
                'message' => "Test disabled successfully",
                'data' => ['TestSiteId' => $id, 'EndDate' => $now]
            ]);
        } catch (\Exception $e) {
            $this->db->transRollback();
            return $this->failServerError('Something went wrong: ' . $e->getMessage());
        }
    }

    /**
     * Helper to get valueset options
     */
    private function getValuesetOptions($vsetID)
    {
        return $this->db->table('valueset')
            ->select('VID as vid, VValue as vvalue, VDesc as vdesc')
            ->where('VSetID', $vsetID)
            ->orderBy('VOrder', 'ASC')
            ->get()->getResultArray();
    }

    /**
     * Helper to get VValue from VID for display
     */
    private function getVValue($vsetID, $vid)
    {
        if ($vid === null || $vid === '')
            return null;
        $row = $this->db->table('valueset')
            ->select('VValue as vvalue')
            ->where('VSetID', $vsetID)
            ->where('VID', (int) $vid)
            ->get()->getRowArray();
        return $row ? $row['vvalue'] : null;
    }

    /**
     * Helper to handle inserting/updating sub-tables based on TestType
     */
    private function handleDetails($testSiteID, $input, $action)
    {
        $testTypeID = $input['TestType'] ?? null;

        // If update and TestType not in payload, fetch from DB
        if (!$testTypeID && $action === 'update') {
            $existing = $this->model->find($testSiteID);
            $testTypeID = $existing['TestType'] ?? null;
        }

        if (!$testTypeID)
            return;

        // Get Type Code (TEST, PARAM, CALC, GROUP, TITLE)
        $vs = $this->modelValueSet->find($testTypeID);
        $typeCode = $vs['VValue'] ?? '';

        // Get details data from input
        $details = $input['details'] ?? $input;
        $details['TestSiteID'] = $testSiteID;
        $details['SiteID'] = $input['SiteID'] ?? 1;

        switch ($typeCode) {
            case 'CALC':
                $this->saveCalcDetails($testSiteID, $details, $action);
                break;

            case 'GROUP':
                $this->saveGroupDetails($testSiteID, $details, $input, $action);
                break;

            case 'TITLE':
                // TITLE type only has testdefsite, no additional details needed
                // But we should save test mappings if provided
                if (isset($input['testmap']) && is_array($input['testmap'])) {
                    $this->saveTestMap($testSiteID, $input['testmap'], $action);
                }
                break;

            case 'TEST':
            case 'PARAM':
            default:
                $this->saveTechDetails($testSiteID, $details, $action, $typeCode);

                // Save refnum/reftxt for TEST/PARAM types
                if (in_array($typeCode, ['TEST', 'PARAM']) && isset($details['RefType'])) {
                    $refType = (int) $details['RefType'];

                    // Save refnum for NMRC type (RefType = 1)
                    if ($refType === 1 && isset($input['refnum']) && is_array($input['refnum'])) {
                        $this->saveRefNumRanges($testSiteID, $input['refnum'], $action, $input['SiteID'] ?? 1);
                    }

                    // Save reftxt for TEXT type (RefType = 2)
                    if ($refType === 2 && isset($input['reftxt']) && is_array($input['reftxt'])) {
                        $this->saveRefTxtRanges($testSiteID, $input['reftxt'], $action, $input['SiteID'] ?? 1);
                    }
                }
                break;
        }

        // Save test mappings for TEST and CALC types as well
        if (in_array($typeCode, ['TEST', 'CALC']) && isset($input['testmap']) && is_array($input['testmap'])) {
            $this->saveTestMap($testSiteID, $input['testmap'], $action);
        }
    }

    /**
     * Save technical details for TEST and PARAM types
     */
    private function saveTechDetails($testSiteID, $data, $action, $typeCode)
    {
        $techData = [
            'TestSiteID' => $testSiteID,
            'DisciplineID' => $data['DisciplineID'] ?? null,
            'DepartmentID' => $data['DepartmentID'] ?? null,
            'ResultType' => $data['ResultType'] ?? null,
            'RefType' => $data['RefType'] ?? null,
            'VSet' => $data['VSet'] ?? null,
            'ReqQty' => $data['ReqQty'] ?? null,
            'ReqQtyUnit' => $data['ReqQtyUnit'] ?? null,
            'Unit1' => $data['Unit1'] ?? null,
            'Factor' => $data['Factor'] ?? null,
            'Unit2' => $data['Unit2'] ?? null,
            'Decimal' => $data['Decimal'] ?? 2,
            'CollReq' => $data['CollReq'] ?? null,
            'Method' => $data['Method'] ?? null,
            'ExpectedTAT' => $data['ExpectedTAT'] ?? null
        ];

        if ($action === 'update') {
            $exists = $this->db->table('testdeftech')
                ->where('TestSiteID', $testSiteID)
                ->where('EndDate IS NULL')
                ->get()->getRowArray();

            if ($exists) {
                $this->modelTech->update($exists['TestTechID'], $techData);
            } else {
                $this->modelTech->insert($techData);
            }
        } else {
            $this->modelTech->insert($techData);
        }
    }

    /**
     * Save refnum ranges for NMRC type
     */
    private function saveRefNumRanges($testSiteID, $ranges, $action, $siteID)
    {
        if ($action === 'update') {
            $this->modelRefNum->where('TestSiteID', $testSiteID)
                ->set('EndDate', date('Y-m-d H:i:s'))
                ->update();
        }

        foreach ($ranges as $index => $range) {
            $this->modelRefNum->insert([
                'TestSiteID' => $testSiteID,
                'SiteID' => $siteID,
                'NumRefType' => (int) $range['NumRefType'],
                'RangeType' => (int) $range['RangeType'],
                'Sex' => (int) $range['Sex'],
                'AgeStart' => (int) ($range['AgeStart'] ?? 0),
                'AgeEnd' => (int) ($range['AgeEnd'] ?? 150),
                'LowSign' => !empty($range['LowSign']) ? (int) $range['LowSign'] : null,
                'Low' => !empty($range['Low']) ? (int) $range['Low'] : null,
                'HighSign' => !empty($range['HighSign']) ? (int) $range['HighSign'] : null,
                'High' => !empty($range['High']) ? (int) $range['High'] : null,
                'Flag' => $range['Flag'] ?? null,
                'Display' => $index,
                'CreateDate' => date('Y-m-d H:i:s')
            ]);
        }
    }

    /**
     * Save reftxt ranges for TEXT type
     */
    private function saveRefTxtRanges($testSiteID, $ranges, $action, $siteID)
    {
        if ($action === 'update') {
            $this->modelRefTxt->where('TestSiteID', $testSiteID)
                ->set('EndDate', date('Y-m-d H:i:s'))
                ->update();
        }

        foreach ($ranges as $range) {
            $this->modelRefTxt->insert([
                'TestSiteID' => $testSiteID,
                'SiteID' => $siteID,
                'TxtRefType' => (int) $range['TxtRefType'],
                'Sex' => (int) $range['Sex'],
                'AgeStart' => (int) ($range['AgeStart'] ?? 0),
                'AgeEnd' => (int) ($range['AgeEnd'] ?? 150),
                'RefTxt' => $range['RefTxt'] ?? '',
                'Flag' => $range['Flag'] ?? null,
                'CreateDate' => date('Y-m-d H:i:s')
            ]);
        }
    }

    /**
     * Save calculation details for CALC type
     */
    private function saveCalcDetails($testSiteID, $data, $action)
    {
        $calcData = [
            'TestSiteID' => $testSiteID,
            'DisciplineID' => $data['DisciplineID'] ?? null,
            'DepartmentID' => $data['DepartmentID'] ?? null,
            'FormulaInput' => $data['FormulaInput'] ?? null,
            'FormulaCode' => $data['FormulaCode'] ?? $data['Formula'] ?? null,
            'RefType' => $data['RefType'] ?? 'NMRC',
            'Unit1' => $data['Unit1'] ?? $data['ResultUnit'] ?? null,
            'Factor' => $data['Factor'] ?? null,
            'Unit2' => $data['Unit2'] ?? null,
            'Decimal' => $data['Decimal'] ?? 2,
            'Method' => $data['Method'] ?? null
        ];

        if ($action === 'update') {
            $exists = $this->db->table('testdefcal')
                ->where('TestSiteID', $testSiteID)
                ->where('EndDate IS NULL')
                ->get()->getRowArray();

            if ($exists) {
                $this->modelCal->update($exists['TestCalID'], $calcData);
            } else {
                $this->modelCal->insert($calcData);
            }
        } else {
            $this->modelCal->insert($calcData);
        }
    }

    /**
     * Save group details for GROUP type
     */
    private function saveGroupDetails($testSiteID, $data, $input, $action)
    {
        if ($action === 'update') {
            // Soft delete existing members
            $this->db->table('testdefgrp')
                ->where('TestSiteID', $testSiteID)
                ->update(['EndDate' => date('Y-m-d H:i:s')]);
        }

        // Get members from details or input
        $members = $data['members'] ?? ($input['Members'] ?? []);

        if (is_array($members)) {
            foreach ($members as $m) {
                $memberID = is_array($m) ? ($m['Member'] ?? ($m['TestSiteID'] ?? null)) : $m;
                if ($memberID) {
                    $this->modelGrp->insert([
                        'TestSiteID' => $testSiteID,
                        'Member' => $memberID
                    ]);
                }
            }
        }
    }

    /**
     * Save test mappings
     */
    private function saveTestMap($testSiteID, $mappings, $action)
    {
        if ($action === 'update') {
            // Soft delete existing mappings
            $this->db->table('testmap')
                ->where('TestSiteID', $testSiteID)
                ->update(['EndDate' => date('Y-m-d H:i:s')]);
        }

        if (is_array($mappings)) {
            foreach ($mappings as $map) {
                $mapData = [
                    'TestSiteID' => $testSiteID,
                    'HostType' => $map['HostType'] ?? null,
                    'HostID' => $map['HostID'] ?? null,
                    'HostDataSource' => $map['HostDataSource'] ?? null,
                    'HostTestCode' => $map['HostTestCode'] ?? null,
                    'HostTestName' => $map['HostTestName'] ?? null,
                    'ClientType' => $map['ClientType'] ?? null,
                    'ClientID' => $map['ClientID'] ?? null,
                    'ClientDataSource' => $map['ClientDataSource'] ?? null,
                    'ConDefID' => $map['ConDefID'] ?? null,
                    'ClientTestCode' => $map['ClientTestCode'] ?? null,
                    'ClientTestName' => $map['ClientTestName'] ?? null
                ];
                $this->modelMap->insert($mapData);
            }
        }
    }
}
