<?php

namespace twa\apilibs\controllers;

use App\Http\Repositories\API;
use App\Http\Repositories\GeneralFunctions;
use twa\apilibs\models\PageInfoModel;
use twa\apilibs\models\PageModel;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;
use Illuminate\Support\Str;
use twa\apilibs\traits\APITrait;

class GetterController
{
    use APITrait;
    public function get($EntityID,$values = [], $lang = false){
//        DB::enableQueryLog();
        $FileBaseRoot = env("DATA_URL",env("APP_URL"));
        if(Str::endsWith($FileBaseRoot,'/')){
            $FileBaseRoot = substr($FileBaseRoot,0,strlen($FileBaseRoot)-1);
        }
        if(!str_contains($FileBaseRoot,"/storage/data")){
            $FileBaseRoot = $FileBaseRoot."/storage/data";
        }


        $values = $this->ProcessValues($values);
        $Check = $this->ProcessRequired($values,[ ]);
        if($Check!==true){ return $Check; }
        $Entity = PageModel::where('id',$EntityID)->where('cancelled',0)->first();
        if(!$Entity){
            return $this->APIDisplayCustomResponse('0','error','Error','Entity with ID = '.$EntityID.' Was Not Found','Entity Was Not Found');
        }
        $Values = DB::table($Entity->main_table)->where('cancelled',0);
        $Fields = PageInfoModel::where('cms_structure_entities_id',$Entity->id)->where('cancelled',0)->get();
        $arr = [];
        foreach ($Fields AS $field){
            $arr[$field->name] = $field;
        }
        $Fields = $arr;

        if($values->get('column')){

            $attributes_builder = [];

            foreach ($values->get('column') AS $key => $value) {
                if (!Str::contains($value,'attributes_') && !Schema::hasColumn($Entity->main_table, $value)) {
                    return $this->APIDisplayCustomResponse('0','error','Error','Column \''.$value.'\' Not Found in the entity \''.$Entity->name.'\'','Column \''.$value.'\' Not Found in the entity \''.$Entity->name.'\'');
                }elseif(Str::contains($value,'attributes_')){
                    $attributes_builder = [ $value => $values->get('value')[$key] ];
                }
            }

            foreach ($attributes_builder AS $key => $row){
                //we add the where tags for the cms_attributes json
                $Values = $Values->where('cms_attributes','LIKE','%"'.$key.'":"'.$row.'"%');
            }


            foreach ($values->get('column') AS $key => $value){
                if(array_key_exists($value,$Fields) || $value == "id" || $value == "locked" || $value == "version"){
                    if(!array_key_exists($value,$Fields)){
                        $Fields[$value] = new \stdClass();
                        $Fields[$value]->db_type = "";
                        $Fields[$value]->type = "";
                    }
                    switch (strtolower($Fields[$value]->db_type)){
                        case "text":
                            try{ $operand = $values->get('operand')[$key]; }catch (\Throwable $e){ $operand = "="; }
                            $Values = $Values->where($values->get('column')[$key], $operand, $values->get('value')[$key]);
                            break;
                        default:
                            $value = json_decode($values->get('value')[$key],1);
                            if(!$value){  $value = $values->get('value')[$key];  }
                            if(is_array($value)){
                                $Values = $Values->whereIn($values->get('column')[$key], $value);
                            }else{
                                $Values = $Values->where($values->get('column')[$key], $value);
                            }
                    }
                }

            }
//            dump(DB::getQueryLog());
        }




        if($values->get('orcolumn')){

            $attributes_builder = [];

            foreach ($values->get('orcolumn') AS $key => $value) {
                if (!Str::contains($value,'attributes_') && !Schema::hasColumn($Entity->main_table, $value)) {
                    return $this->APIDisplayCustomResponse('0','error','Error','Column \''.$value.'\' Not Found in the entity \''.$Entity->name.'\'','Column \''.$value.'\' Not Found in the entity \''.$Entity->name.'\'');
                }elseif(Str::contains($value,'attributes_')){
                    $attributes_builder = [ $value => $values->get('orvalue')[$key] ];
                }
            }

            foreach ($attributes_builder AS $key => $row){
                //we add the where tags for the cms_attributes json
                $Values = $Values->where('cms_attributes','LIKE','%"'.$key.'":"'.$row.'"%');
            }


            foreach ($values->get('orcolumn') AS $key => $value){
                if(array_key_exists($value,$Fields) || $value == "id" || $value == "locked" || $value == "version"){
                    if(!array_key_exists($value,$Fields)){
                        $Fields[$value] = new \stdClass();
                        $Fields[$value]->db_type = "";
                        $Fields[$value]->type = "";
                    }
                    switch (strtolower($Fields[$value]->db_type)){
                        case "text":
                            try{ $operand = $values->get('oroperand')[$key]; }catch (\Throwable $e){ $operand = "="; }
                            $Values = $Values->orwhere($values->get('orcolumn')[$key], $operand, $values->get('orvalue')[$key]);
                            break;
                        default:
                            $value = json_decode($values->get('orvalue')[$key],1);
                            if(!$value){  $value = $values->get('orvalue')[$key];  }
                            if(is_array($value)){
                                $Values = $Values->orwhereIn($values->get('orcolumn')[$key], $value);
                            }else{
                                $Values = $Values->orwhere($values->get('orcolumn')[$key], $value);
                            }
                    }
                }

            }
        }



        if($values->get('limit')){
            $Values = $Values->take($values->get('limit'));
        }
        if($values->get('orderByColumn')){
            $Values = $Values->orderBy($values->get('orderByColumn'), $values->get('orderByDirection','ASC'));
        }
        $Values = $Values->get();
//        $Values = $this->ProcessAttributes($Values,$values);

        foreach ($Values AS $value){
            if(property_exists($value,"cms_attributes")){
                try{
                    $value->cms_attributes = \twa\apilibs\controllers\AttributesController::ProcessCMSAttributesModel($value->cms_attributes);
                }catch (\Throwable $e){
//                    dd($e);
                }
            }
            foreach ($Fields AS $field){
                switch ($field->type){
                    case "image":
                        if($field->size){ $add = "_".$field->size; }else{ $add = ''; }
                        try{ $alt = $value->{'alt_'.$field->name}; }catch (\Throwable $e){ $alt = ""; }
                        $value->{$field->name} = [
                            "image" => $FileBaseRoot.'/'.$field->file_folder.'/'.$value->id.'.'.$value->{'extension_'.$field->name},
                            "thumb" => $FileBaseRoot.'/'.$field->file_folder.$add.'/'.$value->id.'.jpg',
                            "alt" => $alt
                        ];
                        break;
                    case "gallery":
                    case "multiple-image":
                        $gallery = json_decode($value->{$field->name});
                        if(!$gallery){ $gallery = []; }
                        if($field->size){ $add = "_".$field->size; }else{ $add = ''; }
                        foreach ($gallery AS $key => $item){
                            $item = [
                                "image" => $FileBaseRoot.'/'.$field->file_folder.'/'.$item,
                                "thumb" => $FileBaseRoot.'/'.$field->file_folder.$add.'/'.str_replace(['.png','.PNG','.jpeg','.gif'],'.jpg',$item)
                            ];
                            $gallery[$key] = $item;
                        }
                        $value->{$field->name} = $gallery;
                        break;
                    case "multiple-select":
                    case "jsonbuilder":
                        $value->{$field->name} = json_decode($value->{$field->name});
                        break;
                }
            }
        }

        if($lang && count($Values) > 0){
            $Values = $this->ProcessMultiLanguage($Values,$lang);
            try{
                if($Values->getStatusCode() == 400){ return $Values; }
            }catch (\Throwable $e){}
        }

        return response()->json(collect($Values)->recursive(),200);
    }

    private function ProcessMultiLanguage($Values,$lang){
        if(count($Values) == 0){
            return $Values;
        }

        $langs = [];
        $keys = array_keys(collect($Values[0])->toArray());
        $languages = json_decode(str_replace("'",'"',env('CMS_LANGUAGES')));
        if($languages){
            foreach ($languages AS $row){
                $langs[] = $row->prefix;
            }
        }


        //we check if the lang is in the array of langs
        if(!in_array($lang,$langs)){
            return $this->APIDisplayCustomResponse('0','error','Error','Language not in use','The language you are trying to query is not used in this project');
        }

        $Values = json_decode(json_encode($Values));

        //we ge the fields we need to remove
        $to_rename=[];
        foreach ($keys AS $key){
            if(Str::endsWith($key,'_'.$lang)) {
                $to_rename[$key] = substr($key,0,strrpos($key,'_'.$lang));
            }
        }

        $to_remove=[];
        foreach ($langs AS $lang_row){
            if($lang_row != $lang){
                foreach ($to_rename AS $torename_row){
                    $to_remove[] = $torename_row.'_'.$lang_row;
                }
            }
        }


        foreach ($Values AS $value){
            foreach ($keys AS $key){
                if(in_array($key,$to_remove)){
                    unset($value->$key);
                }
                foreach ($to_rename AS $torename_key => $torename_row){
                    if(property_exists($value,$torename_key)){
                        $value->{$torename_row} = $value->{$torename_key};
                        unset($value->{$torename_key});
                    }
                }
            }
        }
        return collect($Values)->toArray();
    }





    public static function set($EntityID,$lang = false){
        $Entity = PageModel::where('id',$EntityID)->where('cancelled',0)->first();
        if(!$Entity){
            return API::APIDisplayCustomResponse('0','error','Error','Entity Was Not Found','Entity Was Not Found');
        }

        $missing = [];

        $Fields = PageInfoModel::where('cms_structure_entities_id',$Entity->id)->where('cancelled',0)->where('type','!=','panel block')->where('type','!=','image')->where('type','!=','gallery')->where('type','!=','multiple-image')->get();
        foreach($Fields AS $field){
            if($field->required == 1 && !request()->input($field->name)){
                $missing[] = $field->name;
            }
        }
        if(count($missing)>0){
            return API::APIDisplayCustomResponse('0','error','Error','Missing fields','You have missed some values that are required. The required values are '.implode(' , ',$missing));
        }

        $insertValues = [];
        foreach($Fields AS $field){
            $insertValues[$field->name] =request()->input($field->name);
        }

        try{
            DB::table($Entity->main_table)->insert($insertValues);
        }catch (\Throwable $e){
            return API::APIDisplayCustomResponse('0','error','error',$e,$e);
        }
        return API::APIDisplayCustomResponse('0','success','Success',"We have inserted a new record in the table $Entity->main_table","We have inserted a new record in the table $Entity->main_table");
    }
}



