<?php

namespace App\Livewire\Search;

use App\Models\Docum;
use App\Models\Doi_date;
use App\Models\Human;
use App\Models\RegistrOffice;
use App\Models\User;
use App\Traits\GetHumanIDTrait;
use Exception;
use Illuminate\Database\Eloquent\ModelNotFoundException;
use Illuminate\Database\QueryException;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Livewire\Component;
use Livewire\Attributes\Validate;
use Spatie\Permission\Models\Role;

class Searchform extends Component
{
    use GetHumanIDTrait;

    public $hasRole = false;
    public $role;
    #[Validate('required')]
    public $searchGroups=[]; //check sec
    #[Validate('min:1')]
    public $docNumber='';
    #[Validate('min:1')]
    public $serialNumber='';
    public $searchcategory;
    public $searchBirthEntryNum=''; //birth entry num
    public $bulkoption = '';
    public $records_not_found=[];
    public $search_count=0;

    public $passportNum;
    public $passportIdNum;

    public $humans=[];
    protected $serial_number;

    public $doctype='';
    public $records_found= [];

    public function save()
    {
        $this->store();
    }
    public function store()
    {
        $this->validate();

        switch ($this->searchcategory){
            case 'ID' :
                if(!empty($this->serialNumber) || !empty($this->docNumber)){
                    $this->getIDHuman();
                }else{
                    session()->flash('error', 'Either Document Number or Serial Number must be provided.');
                }
            break;
            case 'Passport' :
                if(!empty($this->passportNum) || !empty($this->passportIdNum)){
                    $this->getPassportHuman($this->passportNum,$this->passportIdNum);
                }else{
                    session()->flash('error', 'Either Document Number or Serial Number must be provided.');
                }
            break;
            case 'Birth' :
                if(!empty($this->searchBirthEntryNum)){

                    $this->getBirthHuman();
                }else{
                    session()->flash('error', 'Birth entry number not provided');
                }
            break;
            default:
                abort(403, "You don't have permission to perform basic search.");
        }
        return null;
    }
    public function mount()
    {

        /** @var Auth $user current logged-in user */
        $user = Auth::user();

        /** @var User $contract_id  user contract ID */
        $contractId = $user['contract_rid'];

        try {
            $this->role = Role::findByName('CID-'.$user->contract_rid);
            $this->hasRole = true;
        } catch (Exception $e)
        {
            //abort(403, "You don't have permission to perform basic search.");
            $this->hasRole = false;
        }

        // to add more ...
        if ($this->role->hasPermissionTo('Basic Search ID card')) {
            $this->searchGroups[]= 'ID';
        }

        if ($this->role->hasPermissionTo('Basic Search Passport card')) {
            $this->searchGroups[]= 'Passport';
        }

        if ($this->role->hasPermissionTo('Basic Search Birth Certificate')) {
            $this->searchGroups[]='Birth';
        }
    }
    public function render()
    {
        if ($this->hasRole) {
            return view('livewire.search.searchform', ['searchGroups' => $this->searchGroups, 'humans' => $this->humans]);
        }
        abort(403, "You don't have permission to perform basic search.");
    }

    protected function bulkSearch($docNums)
    {
        $this->search_count=0;
        $this->records_found=[];
        $this->records_not_found=[];

        try {
            $results=[];
            //@TODO add checks for validating comma separated id or throw an error
            $docNums=str_replace(' ', '', $docNums);
            $ids=explode(',' ,$docNums);
            //loop
            foreach($ids as $id){
                $this->search_count++;
                $human = Human::where('o_pid', '=', $id)->get(
                    ['pid','name','surn','last_name','sex','date_birth','date_death','o_pid']);
                if($human->isEmpty()){
                    $this->records_not_found[]=$id;
                }else{
                    $pid = $human[0]['pid'];
                    $serial_number = Docum::where('rid_h', '=', $pid)->value('ser_num');
                    $this->serial_number[]=$serial_number;
                    $results[]=$human;
                    $this->records_found[]=$id;
                }
            }
            return $results;

        } catch (QueryException $e) {
             return response()->json(['error' => 'Database error'], 500);
        } catch (Exception $e) {
             return response()->json(['error' => 'An error occurred'], 500);
        }
        return [];
    }

    /**
     * Basic search, fetch human given ID or serial number
     * @return void
     */
    private function getIDHuman(): void
    {

        if ($this->bulkoption == 'true') {
            //BULK SEARCH
            $this->humans = $this->bulkSearch($this->docNumber);
            $this->showTableResults();
        }else {
            $this->search_count=1;
            $this->records_found=[];
            $this->records_not_found=[];
            $this->doctype ='ID';

            //Get Human
            if(!empty($this->docNumber)){
                $human = $this->getHumanBasic(['idnumber'=> $this->docNumber]);
            }
            if(empty($this->docNumber) && !empty($this->serialNumber)){
                $human = $this->searchIDocums($this->serialNumber);
            }

                for ($x=0; $x < count($human); $x++){
                    $pid = $human[$x]['pid'];
                    $this->serial_number[]=$this->getSerialDocums($pid);
                }

                $this->records_found[] = $this->docNumber;
                $this->humans[] = $human;

                $this->showTableResults();

        }
    }

    private function getPassportHuman($passportNum, $idnum)
    {
        $passport= Doi_date::where('passport_no', $passportNum)->where('identity_card_no', $idnum)->get()->toArray();

        if($passport){
            $this->search_count=1;
            $this->doctype ='Passport';
            $this->records_found[]=$passportNum;
            $this->serial_number[]=$passportNum;
            $this->humans =  $passport;
            $this->showTableResults();
        }else{
            session()->flash('error', 'Search parameter Not found');
        }

    }

    /**
     * Basic search birth record
     * @return void
     * Uses property searchBirthEntryNum
     */
    private function getBirthHuman(): void
    {
      /*  if(!empty($this->searchBirthEntryNum)){
            $human = $this->searchIDocums($this->searchBirthEntryNum);

            $this->search_count=1;
            $this->doctype ='Birth';
            $this->records_found[]=$this->searchBirthEntryNum;
            $this->serial_number[]=$this->searchBirthEntryNum;
            $this->humans[] = $human;

            $this->showTableResults();
        }else{
            session()->flash('error', 'Search parameter is missing..');
        }*/
        $rid = Docum::where('ser_num', '=', $this->searchBirthEntryNum)->value('rid_h');

        if($rid){
            $human = Human::where('rid','=', $rid)->whereColumn('rid', 'pid')
                ->get(['rid', 'pid', 'name', 'surn', 'last_name', 'sex', 'date_birth', 'date_death', 'o_pid']);
            if($human->isEmpty()){
                throw new ModelNotFoundException('No record found');
            }else{
                $this->search_count=1;
                $this->doctype ='Birth';
                $this->records_found[]=$this->searchBirthEntryNum;
                $this->serial_number[]=$this->searchBirthEntryNum;
                $this->humans[] = $human;
                $this->dispatch('viewResults', $this->humans,$this->serial_number,
                    $this->doctype,$this->records_not_found,
                    $this->search_count,$this->records_found);
            }
        }
    }

    /**
     * Trigger to display result
     * @return void
     */
    public function showTableResults(): void
    {
            $this->dispatch('viewResults', $this->humans,$this->serial_number,
            $this->doctype,$this->records_not_found,
            $this->search_count,$this->records_found);
    }


}
