<?php
namespace App\Controllers\Patient;

use CodeIgniter\API\ResponseTrait;
use CodeIgniter\Controller;

use App\Models\Patient\PatientModel;

class PatientController extends Controller {
    use ResponseTrait;

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

    public function __construct() {
        $this->db = \Config\Database::connect();
        $this->model = new PatientModel();
        $this->rules = [
            'PatientID'         => 'required|regex_match[/^[A-Za-z0-9]+$/]|max_length[30]',
            'AlternatePID'      => 'permit_empty|regex_match[/^[A-Za-z0-9]+$/]|max_length[30]',
            'Prefix'            => 'permit_empty|regex_match[/^[A-Za-z\'\. ]+$/]|max_length[10]',
            'Gender'            => 'required',

            'NameFirst'         => 'required|regex_match[/^[A-Za-z\'\. ]+$/]|min_length[1]|max_length[60]',
            'NameMiddle'        => 'permit_empty|regex_match[/^[A-Za-z\'\. ]+$/]|min_length[1]|max_length[60]',
            'NameMaiden'        => 'permit_empty|regex_match[/^[A-Za-z\'\. ]+$/]|min_length[1]|max_length[60]',
            'NameLast'          => 'permit_empty|regex_match[/^[A-Za-z\'\. ]+$/]|min_length[1]|max_length[60]',

            'Suffix'            => 'permit_empty|regex_match[/^[A-Za-z\'\. ]+$/]|max_length[10]',
            'PlaceOfBirth'      => 'permit_empty|regex_match[/^[A-Za-z\'\. ]+$/]|max_length[100]',
            'Citizenship'       => 'permit_empty|regex_match[/^[A-Za-z\'\. ]+$/]|max_length[100]',

            'Street_1'          => 'permit_empty|regex_match[/^[A-Za-z0-9\'.,\/\- ]+$/]|max_length[255]',
            'Street_2'          => 'permit_empty|regex_match[/^[A-Za-z0-9\'.,\/\- ]+$/]|max_length[255]',
            'Street_3'          => 'permit_empty|regex_match[/^[A-Za-z0-9\'.,\/\- ]+$/]|max_length[255]',

            'EmailAddress1'     => 'permit_empty|valid_email|max_length[100]',
            'EmailAddress2'     => 'permit_empty|valid_email|max_length[100]',
            
            'Birthdate'             => 'required',
            'PatIdt.IdentifierType' => 'permit_empty',
            'PatIdt.Identifier'     => 'permit_empty|max_length[255]',

            'ZIP'               => 'permit_empty|is_natural|max_length[10]',
            'Phone'             => 'permit_empty|regex_match[/^\\+?[0-9]{8,15}$/]',
            'MobilePhone'       => 'permit_empty|regex_match[/^\\+?[0-9]{8,15}$/]'
        ];
    }

    public function index() {
        $filters = [
            'InternalPID' => $this->request->getVar('InternalPID'),
            'PatientID'   => $this->request->getVar('PatientID'),
            'Name'        => $this->request->getVar('Name'),
            'Birthdate'   => $this->request->getVar('Birthdate'),
        ];

        try {
            $rows = $this->model->getPatients($filters);
            return $this->respond([ 'status' => 'success', 'message'=> "data fetched successfully", 'data'   => $rows ], 200);
        } catch (\Exception $e) {
            return $this->failServerError('Exception : '.$e->getMessage());
        }
    }

    public function show($InternalPID = null) {
        try {
            $row = $this->model->getPatient($InternalPID);
            if (empty($row)) { return $this->respond([ 'status'  => 'success', 'message' => "data not found.", 'data' => null ], 200); }
            return $this->respond([ 'status'  => 'success', 'message' => "data fetched successfully", 'data' => $row ], 200);
        } catch (\Exception $e) {
            return $this->failServerError('Something went wrong: ' . $e->getMessage());
        }
    }

    public function create() {
        $input = $this->request->getJSON(true);

        // Khusus untuk Override PATIDT
        $type = $input['PatIdt']['IdentifierType'] ?? null;
        $identifierRulesMap = [
            'KTP'  => 'required|regex_match[/^[0-9]{16}$/]',            // 16 pas digit numeric
            'PASS' => 'required|regex_match[/^[A-Za-z0-9]{1,9}$/]',     // alphanumeric max 9
            'SSN'  => 'required|regex_match[/^[0-9]{9}$/]',             // numeric, pas 9 digit
            'SIM'  => 'required|regex_match[/^[0-9]{19,20}$/]',         // numeric 19–20 digit
            'KTAS' => 'required|regex_match[/^[0-9]{11}$/]',            // numeric, pas 11 digit
        ];
        if ($type === null || $type === '' || !is_string($type)) {
            $identifierRule = 'permit_empty|max_length[255]';
            $this->rules['PatIdt.IdentifierType'] = 'permit_empty';
            $this->rules['PatIdt.Identifier']     = $identifierRule;
        } else {
            $identifierRule = $identifierRulesMap[$type] ?? 'permit_empty|max_length[255]';
            $this->rules['PatIdt.IdentifierType'] = 'required';
            $this->rules['PatIdt.Identifier']     = $identifierRule;
        }

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

    public function update() {
        $input = $this->request->getJSON(true);

        // Khusus untuk Override PATIDT
        $type = $input['PatIdt']['IdentifierType'] ?? null;
        $identifierRulesMap = [
            'KTP'  => 'required|regex_match[/^[0-9]{16}$/]',
            'PASS' => 'required|regex_match[/^[A-Za-z0-9]{6,9}$/]',
            'SSN'  => 'required|regex_match[/^[0-9]{3}-[0-9]{2}-[0-9]{4}$/]',
            'SIM'  => 'required|regex_match[/^[A-Za-z0-9]{12,14}$/]',
            'KTAS' => 'required|regex_match[/^[A-Za-z0-9]{12,15}$/]',
        ];
        if ($type === null || $type === '' || !is_string($type)) {
            $identifierRule = 'permit_empty|max_length[255]';
            $this->rules['PatIdt.IdentifierType'] = 'permit_empty';
            $this->rules['PatIdt.Identifier']     = $identifierRule;
        } else {
            $identifierRule = $identifierRulesMap[$type] ?? 'permit_empty|max_length[255]';
            $this->rules['PatIdt.IdentifierType'] = 'required';
            $this->rules['PatIdt.Identifier']     = $identifierRule;
        }

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

            // Mencegah Inputan 0, [], null, sql injection
            if (empty($InternalPID) || !ctype_digit((string) $InternalPID)) {
                return $this->respond([
                    'status' => 'error',
                    'message' => "Patient ID must be a valid integer."
                ], 400);
            }

            $patient = $this->db->table('patient')->where('InternalPID', $InternalPID)->get()->getRow();

            if (!$patient) {
                return $this->failNotFound("Patient ID with {$InternalPID} not found.");
            }

            $this->db->table('patient')->where('InternalPID', $InternalPID)->update(['DelDate' => date('Y-m-d H:i:s')]);

            return $this->respondDeleted([
                'status' => 'success',
                'message' => "Patient ID with {$InternalPID} deleted successfully."
            ]);
 
        } catch (\Exception $e) {
            return $this->failServerError("Internal server error: " . $e->getMessage());
        }
    }

    public function patientCheck() {
        try {
            $PatientID = $this->request->getVar('PatientID');
            $EmailAddress1 = $this->request->getVar('EmailAddress1');

            $tableName = '';
            $searchName = '';

            if (!empty($PatientID)){
                $tableName = 'PatientID';
                $searchName = $PatientID;
            } elseif (!empty($EmailAddress1)){
                $tableName = 'EmailAddress1';
                $searchName = $EmailAddress1;
            } else {
                return $this->respond([
                    'status' => 'error',
                    'message' => 'PatientID or EmailAddress1 parameter is required.',
                    'data' => null
                ], 400); 
            }

            $patient = $this->db->table('patient')
                ->where($tableName, $searchName)
                ->get()
                ->getRowArray();

            if (!$patient) {
                return $this->respond([
                    'status'  => 'success',
                    'message' => "$tableName not found.",
                    'data'    => true,
                ], 200);
            }

            return $this->respond([
                'status'  => 'success',
                'message' => "$tableName already exists.",
                'data'    => false,
            ], 200);


        } catch (\Exception $e) {
            // Error Server Mengembalikan 500
            return $this->failServerError('Something went wrong.'.$e->getMessage());
        }
    }
}
