<?php

namespace App\Controllers\Test;

use App\Controllers\BaseController;
use App\Traits\PatchValidationTrait;
use App\Traits\ResponseTrait;
use App\Models\Test\TestMapDetailModel;

class TestMapDetailController extends BaseController {
    use ResponseTrait;
    use PatchValidationTrait;

    protected $db;
    protected $rules;
    protected $patchRules;
    protected $model;

    public function __construct() {
        $this->db = \Config\Database::connect();
        $this->model = new TestMapDetailModel;
        $this->rules = [
            'TestMapID' => 'required|integer',
            'HostTestCode' => 'permit_empty|max_length[10]',
            'HostTestName' => 'permit_empty|max_length[100]',
            'ConDefID' => 'permit_empty|integer',
            'ClientTestCode' => 'permit_empty|max_length[10]',
            'ClientTestName' => 'permit_empty|max_length[100]',
        ];
        $this->patchRules = [
            'TestMapID' => 'permit_empty|integer',
            'HostTestCode' => 'permit_empty|max_length[10]',
            'HostTestName' => 'permit_empty|max_length[100]',
            'ConDefID' => 'permit_empty|integer',
            'ClientTestCode' => 'permit_empty|max_length[10]',
            'ClientTestName' => 'permit_empty|max_length[100]',
        ];
    }

    public function index() {
        $testMapID = $this->request->getGet('TestMapID');
        
        if ($testMapID) {
            $rows = $this->model->getDetailsByTestMap($testMapID);
        } else {
            $rows = $this->model->where('EndDate', null)->findAll();
        }
        
        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);
    }

    public function show($id = null) {
        if (!$id) {
            return $this->failValidationErrors('TestMapDetailID is required.');
        }
        
                $row = $this->model->where('TestMapDetailID', $id)->where('EndDate', null)->first();
        
        if (empty($row)) { 
            return $this->respond([ 'status'  => 'success', 'message' => "no Data.", 'data' => null ], 200); 
        }

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

    public function showByTestMap($testMapID = null) {
        if (!$testMapID) { 
            return $this->failValidationErrors('TestMapID is required.'); 
        }
        
        $rows = $this->model->getDetailsByTestMap($testMapID);
        
        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);
    }

    public function create() {
        $input = $this->request->getJSON(true);
        
        if (!$this->validateData($input, $this->rules)) { 
            return $this->failValidationErrors($this->validator->getErrors()); 
        }
        
        try {
            $id = $this->model->insert($input);
            return $this->respondCreated([ 
                'status'  => 'success', 
                'message' => "data created successfully", 
                'data' => $id 
            ]);
        } catch (\Exception $e) {
            return $this->failServerError('Something went wrong: ' . $e->getMessage());
        }
    }

    public function update($TestMapDetailID = null) {
        $input = $this->requirePatchPayload($this->request->getJSON(true));
        if ($input === null) {
            return;
        }

        $id = $this->requirePatchId($TestMapDetailID, 'TestMapDetailID');
        if ($id === null) {
            return;
        }

        $existing = $this->model->where('TestMapDetailID', $id)->where('EndDate', null)->first();
        if (!$existing) {
            return $this->respond([ 'status' => 'failed', 'message' => 'Test map detail not found', 'data' => [] ], 404);
        }

        if (isset($input['TestMapDetailID']) && (string) $input['TestMapDetailID'] !== (string) $id) {
            return $this->failValidationErrors('TestMapDetailID in URL does not match body.');
        }

        $input['TestMapDetailID'] = $id;
        $validationInput = array_intersect_key($input, $this->patchRules);
        if (!empty($validationInput) && !$this->validateData($validationInput, $this->patchRules)) { 
            return $this->failValidationErrors($this->validator->getErrors()); 
        }

        try {
            $this->model->update($id, $input);
            return $this->respond([
                'status'  => 'success', 
                'message' => 'data updated successfully', 
                'data' => $id 
            ], 200);
        } catch (\Exception $e) {
            return $this->failServerError('Something went wrong: ' . $e->getMessage());
        }
    }

    public function delete() {
        $input = $this->request->getJSON(true);
        $id = $input["TestMapDetailID"] ?? null;
        
        if (!$id) { 
            return $this->failValidationErrors('TestMapDetailID is required.'); 
        }
        
        try {
            $row = $this->model->where('TestMapDetailID', $id)->where('EndDate', null)->first();
            
            if (empty($row)) { 
                return $this->respond([ 
                    'status'  => 'failed', 
                    'message' => "Data not found or already deleted.", 
                    'data' => null 
                ], 404); 
            }
            
            $this->model->update($id, ['EndDate' => date('Y-m-d H:i:s')]);
            
            return $this->respond([ 
                'status'  => 'success', 
                'message' => "data deleted successfully", 
                'data' => $id 
            ], 200);
        } catch (\Exception $e) {
            return $this->failServerError('Something went wrong: ' . $e->getMessage());
        }
    }

    public function batchCreate() {
        $items = $this->request->getJSON(true);
        
        if (!is_array($items)) { 
            return $this->failValidationErrors('Expected array of items'); 
        }
        
        $results = ['success' => [], 'failed' => []];
        $this->db->transStart();
        
        foreach ($items as $index => $item) {
            if (!$this->validateData($item, $this->rules)) {
                $results['failed'][] = ['index' => $index, 'errors' => $this->validator->getErrors()];
                continue;
            }
            try {
                $id = $this->model->insert($item);
                $results['success'][] = ['index' => $index, 'TestMapDetailID' => $id];
            } catch (\Exception $e) {
                $results['failed'][] = ['index' => $index, 'error' => $e->getMessage()];
            }
        }
        
        $this->db->transComplete();
        
        return $this->respond([
            'status' => empty($results['failed']) ? 'success' : 'partial',
            'message' => 'Batch create completed',
            'data' => $results
        ], 200);
    }

    public function batchUpdate() {
        $items = $this->request->getJSON(true);
        
        if (!is_array($items)) { 
            return $this->failValidationErrors('Expected array of items'); 
        }
        
        $results = ['success' => [], 'failed' => []];
        $this->db->transStart();
        
        foreach ($items as $index => $item) {
            $id = $item['TestMapDetailID'] ?? null;
            
            if (!$id) {
                $results['failed'][] = ['index' => $index, 'error' => 'TestMapDetailID required'];
                continue;
            }

            $updateData = $item;
            unset($updateData['TestMapDetailID']);

            if ($updateData === []) {
                $results['failed'][] = ['index' => $index, 'error' => 'No fields to update'];
                continue;
            }
            
            if (!$this->validateData($updateData, $this->patchRules)) {
                $results['failed'][] = ['index' => $index, 'errors' => $this->validator->getErrors()];
                continue;
            }
            
            try {
                $this->model->update($id, $updateData);
                $results['success'][] = ['index' => $index, 'TestMapDetailID' => $id];
            } catch (\Exception $e) {
                $results['failed'][] = ['index' => $index, 'error' => $e->getMessage()];
            }
        }
        
        $this->db->transComplete();
        
        return $this->respond([
            'status' => empty($results['failed']) ? 'success' : 'partial',
            'message' => 'Batch update completed',
            'data' => $results
        ], 200);
    }

    public function batchDelete() {
        $ids = $this->request->getJSON(true);
        
        if (!is_array($ids)) { 
            return $this->failValidationErrors('Expected array of TestMapDetailIDs'); 
        }
        
        $results = ['success' => [], 'failed' => []];
        $this->db->transStart();
        
        foreach ($ids as $id) {
            try {
        $row = $this->model->where('TestMapDetailID', $id)->where('EndDate', null)->first();
                
                if (empty($row)) {
                    $results['failed'][] = ['TestMapDetailID' => $id, 'error' => 'Not found or already deleted'];
                    continue;
                }
                
                $this->model->update($id, ['EndDate' => date('Y-m-d H:i:s')]);
                $results['success'][] = $id;
            } catch (\Exception $e) {
                $results['failed'][] = ['TestMapDetailID' => $id, 'error' => $e->getMessage()];
            }
        }
        
        $this->db->transComplete();
        
        return $this->respond([
            'status' => empty($results['failed']) ? 'success' : 'partial',
            'message' => 'Batch delete completed',
            'data' => $results
        ], 200);
    }
}
