<?php
/*
 * This trait gets data of a human given his doc details
 * */
namespace App\Traits;

use App\Models\Docum;
use App\Models\Human;
use App\Models\RegistrOffice;
use App\Models\Relative;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\ModelNotFoundException;
use Illuminate\Support\Facades\DB;

trait GetHumanIDTrait
{
    /**
     * Does a basic search for a human in HUMAN table
     * @param array $params 'firstname', 'surname', 'lastname', 'idnum', 'pid', 'month', 'gender'
     * @return Collection|array
     */
    private function getHumanBasic(array $params = []): Collection|array
    {
            $searchInput = [
                'name'          =>  $params['firstname'] ?? '',
                'surn'          =>  $params['surname'] ?? '',
                'last_name'     =>  $params['lastname'] ?? '',
                'o_pid'         =>  $params['idnumber'] ?? '',
                'pid'           =>  $params['pid'] ?? '',
                'month_birth'   =>  $params['month'] ?? '',
                'sex'           =>  $params['gender'] ?? '',
            ];

            try{
                $conditions = array_filter($searchInput);
                $query = Human::query();

                foreach ($conditions as $column => $value) {
                    $query->where($column, $value);
                }

               return $query->whereColumn('rid', 'pid')
                    ->get(['rid', 'pid', 'name', 'surn', 'last_name', 'sex', 'date_birth', 'date_death', 'o_pid']);

            } catch (ModelNotFoundException $e){
                //fix this code
               // @TODO fix this code
                $this->humans=[];
                $this->records_not_found[] = $this->docNumber;
                $this->dispatch('viewResults', $this->humans,$this->serial_number,
                $this->doctype,$this->records_not_found,$this->search_count,$this->records_found);
            }
            return [];
    }



    private function apiGetHuman($id, $serial=null)
    {
       try{
           $human =Human::where('o_pid', $id)->select('name', 'surn', 'last_name', 'sex', 'date_birth', 'date_death')->first();
            return $human;
       } catch (ModelNotFoundException $e){
            //fix this code
       }
        return [];
    }

    /**
     * Simple Search for an ID given a serial number
     * @param $serNum
     * @return array|Collection
     */
    private function searchIDocums($serNum): array|Collection
    {
        $docum_data=Docum::where('ser_num', '=', $serNum)->first(['pid','ser_num']);
        return $this->getHumanID(['pid' => $docum_data['pid']]);
    }

    /**
     * Search and return a
     * @param $pid
     * @return string
     */
    private function getSerialDocums($pid)
    {
        return Docum::where('rid_h', '=', $pid)->value('ser_num');
    }

    /**
     * ID CARD - Gets all the details of a human including address info
     * @param $docNum
     * @param $serialNum
     * @param null $docType
     * @return array|Builder|Model|object
     */
    private function getDetailedIDHuman($docNum,$serialNum,$docType=null)
    {
        $human = Human::with(['addressLive.addressLocation', 'addressLive.adresComp'])
                        ->where('o_pid', '=', $docNum)
                        ->whereColumn('rid', 'pid')
                        ->orderBy('data_scan', 'desc')
                        ->first();

        if ($human) {
            //get the documents ID,BIRTH.... + the registration office name
            $docums   = $this->getRegistryOffice($this->searchDocums($human->rid,'',$serialNum,$docType));

            //$humanDocs = $this->getHumanAllDocs($human->pid); //use PID to pull all records
            $humanDocs=[];

            // Family relation
            $family    = $this->getFamily($human->rid);
            return ['human'=>$human,'docums'=>$docums,'family'=>$family, 'all_docs'=>$humanDocs];
        }
        return [];
    }

    /**
     * Search for a document in DOCUMS
     * @param null $rid_h
     * @param null $serialNum
     * @param null $docType
     * @return array of document details history
     */
    private function searchDocums($rid_h=null, $pid=null, $serialNum=null, $docType=null): array
    {
        $doctypes=['id'=>'IDC', 'birth'=>'BRA', 'passport'=>'DOI'];

        if($docType == 'all'){
            $query = "SELECT json_array(doc_rekv), TYPE, SER_NUM FROM docums
                  WHERE PID = :pid
                  ORDER BY DAT_PRODUCT desc";
            $documents= DB::select($query, ['pid' => $pid]);

        }else {
            $query = "SELECT json_array(doc_rekv), TYPE, SER_NUM FROM docums
                  WHERE RID_H = :rid_h
                  AND TYPE = :doc
                  ORDER BY DAT_PRODUCT desc";
            $documents = DB::select($query, ['rid_h' => $rid_h, 'doc' => $doctypes[$docType]]);
        }

        $documents_json= json_decode(json_encode($documents), true);

        /* @var $docums_data - an array of documents returned */
        foreach($documents_json as $doc_array) {
            $decoded = json_decode($doc_array["json_array(doc_rekv)"], true);
            $docums[] = $decoded[0];
        }

        return $docums;
    }

    /**
     * Gets the registry office of an ID card
     * @param $docums
     * @return array
     */
    private function getRegistryOffice($docs)
    {
        $count=0;
        foreach($docs as $doc){
            // $place_of_issue = RegistrOffice::where('rid', 'NRB'.$doc[0]['PRODUCT'])->value('name');
            $office_code='NRB'.$doc['PRODUCT'];
            //dd($office_code);
            $place_of_issue = RegistrOffice::where('rid',$office_code)->value('name');

            if(is_null($place_of_issue)){
                $docs[$count]['PRODUCT'] = "";
            }else{
                $docs[$count]['PRODUCT'] = $place_of_issue;
            }
            $count++;
        }
        return $docs;
    }

    /**
     * Gets all human documents in DOCUMS
     * @param $pid
     * @return array|mixed|null
     */
    private function getHumanAllDocs($pid)
    {
        $allDocs = $this->fetchAllDocuments($pid);
        //$docums = $this->getRegistryOffice($getDocums);
        //$docums = $this->getRegistryOffice($allDocs);
        if (empty($allDocs)) {
            return null;
        }
        return $allDocs;
    }

    private function fetchAllDocuments($pid)
    {
        $docs=[];
        $query = "SELECT json_array(doc_rekv), TYPE, SER_NUM FROM docums
                  WHERE PID = :pid
                  ORDER BY DAT_PRODUCT desc";
        $documents= DB::select($query, ['pid' => $pid]);

        foreach($documents as $document) {
            $documents_json= json_decode(json_encode($document), true);
            $docs[] = json_decode($documents_json["json_array(doc_rekv)"]);
        }
        return $documents;
    }

    /**
     * Gets a family relation of the human
     * @param $rid
     * @return array
     */
    private function getFamily($rid): array
    {
        $parents=[];
        $children=[];
        //get children
        $child_id  = Relative::where('first_person','=',$rid)->get(['second_person']);

        if(isset($child_id[0])){
            $parents_id= Relative::where('second_person', '=', $child_id[0]['second_person'])->get(['first_person','type_rel']);
            foreach($child_id as $child){
                $children[] = $this->getHumanBasic(['pid'=>$child['second_person']]);
                foreach($parents_id as $parent){
                    $parents[]=$this->getHumanBasic(['pid'=>$parent['first_person']]);
                }
            }

            return ['parents'=>$parents,'children'=>$children];
        }
        return [];
    }

    private function getIDHistory($id, $serialNum)
    {
        //get Human PID
       // return Human::where('rid', '=', $rid)->get(['pid','name','surn','last_name','sex','date_birth','date_death','o_pid']);
    }

}//end class
