<?php

namespace App\Http\Controllers;
use Illuminate\Support\Facades\DB;

use Laravel\Lumen\Routing\Controller as BaseController;

class Controller extends BaseController
{
    protected $pathImage   = "assets/image/";
    protected $pathDocument   = "assets/file/project/";
    protected $pathActivityDocument = "assets/file/activity/";
    protected $listJoinAll = ['first', 'second', 'third', 'fourth', 'fifth',
    'sixth', 'seventh', 'eighth', 'ninth', 'tenth'];
    protected $currentDate;
    protected $currentName;
    protected $currentId;

    public function __construct()
    {
        $this->currentDate = date("Y-m-d H:i:s");
        $this->currentName = auth()->user() ? auth()->user()->name : "system";
        $this->currentId = auth()->user() ? auth()->user()->id : 0;

        $this->pathImage = config('assets.image');
        $this->pathDocument = config('assets.project');
        $this->pathActivityDocument = config('assets.activity');
    }

    protected function setUpPayload($condition, $tableSelf)
    {
        $alias = "selfTable";
        $builder = DB::table($tableSelf." AS ".$alias);
        $builder = $builder->select($alias.".*");
        if($condition){
            if(isset($condition['joins'])){
                $selectColumn = [];
                $no = 0;
                foreach($condition['joins'] as $join){
                    $tableJoin = isset($join['name1']) ? $join['name1'] : $alias;
                    $tableName  = $join['name'];
                    $columnJoin = $join['column_join']; // foreign key table sini
                    $columnSelf = isset($join['column_self']) ? $join['column_self'] : "id"; // primary key table lawan
                    $columnResult = $join['column_results'];

                    foreach($columnResult as $sColumn){
                        $builder = $builder->addSelect($tableName.".".$sColumn." as join_".$this->listJoinAll[$no]."_".$sColumn);
                    }
                    $builder = $builder->leftJoin($tableName, $tableJoin.".".$columnJoin, '=', $tableName.'.'.$columnSelf);
                    $no++;
                }
            }

            if(isset($condition['columns'])){
                $listWhere = $condition['columns'];

                $builder = $builder->where(function ($query)  use($listWhere, $alias){
                    foreach($listWhere as $where){
                        $value = $where['value'];
                        if($value && $value!="" && $value!=" "){
                            $column = $where['name'];
                            $operator = strtolower($where['logic_operator']); // like, =, <>, range
                            $value2 = isset($where['value1']) ? $where['value1'] : "";
                            $tableColumn = isset($where['table_name']) ? $where['table_name'] : $alias;
                            $query = $this->whereCondition($query, $operator, $tableColumn, $column, $value, $value2);
                        }
                    }
                });
            }

            if(isset($condition['group_column'])){
                $builder = $this->groupWhere($builder, $condition['group_column'], $alias);
            }

            $data['count'] = clone $builder;

            if(isset($condition['paging'])){
                $builder = $builder->offset($condition['paging']['start'])->limit($condition['paging']['length']);
            }

            if(isset($condition['orders'])){
                $orders = $condition['orders'];
                $sortBy = $orders['ascending'] ? "ASC" : "DESC";
                $columnOrder = $orders['columns'];
                foreach($columnOrder as $column){
                    $builder = $builder->orderBy($alias.".".$column, $sortBy);
                }
            }
        }
        $data['builder'] = $builder;
        return $data;
    }

    private function groupWhere($oldBuilder, $groupWhere, $alias)
    {
        $builder = $oldBuilder;
        $listGroupWhere = $groupWhere;
        $operator = $listGroupWhere['operator'];
        $operatorGroup = $listGroupWhere['group_operator'];
        $listWhere = $listGroupWhere['where'];
        if(strtolower($operator)=="and"){
            $builder = $builder->where(function($query) use($operatorGroup, $listWhere, $alias){
                $no = 1;
                foreach ($listWhere as $where) {
                    $value = $where['value'];
                    $column = $where['name'];
                    $operator = strtolower($where['logic_operator']);
                    $value2 = isset($where['value1']) ? $where['value1'] : "";
                    $tableColumn = isset($where['table_name']) ? $where['table_name'] : $alias;
                    if($value && $value!="" && $value!=" "){
                        if($operatorGroup=="and"){
                            $query = $this->whereCondition($query, $operator, $tableColumn, $column, $value, $value2);
                        }else{
                            if($no==1){
                                $query = $this->whereCondition($query, $operator, $tableColumn, $column, $value, $value2);
                            }else{
                                $query = $this->orWhereCondition($query, $operator, $tableColumn, $column, $value, $value2);
                            }
                        }
                    }
                    $no = $no+1;
                }
            });
        }else if(strtolower($operator)=="or"){
            $builder = $builder->orWhere(function($query) use($operatorGroup, $listWhere, $alias){
                $no = 1;
                foreach ($listWhere as $where) {
                    $value = $where['value'];
                    $column = $where['name'];
                    $operator = strtolower($where['logic_operator']);
                    $value2 = isset($where['value1']) ? $where['value1'] : "";
                    $tableColumn = isset($where['table_name']) ? $where['table_name'] : $alias;
                    if($value && $value!="" && $value!=" "){
                        if($operatorGroup=="and"){
                            $query = $this->whereCondition($query, $operator, $tableColumn, $column, $value, $value2);
                        }else{
                            if($no==1){
                                $query = $this->whereCondition($query, $operator, $tableColumn, $column, $value, $value2);
                            }else{
                                $query = $this->orWhereCondition($query, $operator, $tableColumn, $column, $value, $value2);
                            }
                        }
                    }
                    $no++;
                }
            });
        }
        return $builder;
    }

    private function whereCondition($oldQuery, $operator, $tableColumn, $column, $value, $value2)
    {
        $query = $oldQuery;
        if($operator=="range"){
            $query = $query->whereBetween($tableColumn.".".$column, [$value, $value2]);
        }else if($operator=="like"){
            $query = $query->where($tableColumn.".".$column, 'like', '%'.$value.'%');
        }else if($operator=="ilike"){
            $query = $query->where($tableColumn.".".$column, '~*', $value);
        }else if($operator=="="){
            $query = $query->where($tableColumn.".".$column, $value);
        }else if($operator=="in"){
            $query = $query->whereIn($tableColumn.".".$column, $value);
        }else if($operator=="notin"){
            $query = $query->whereNotIn($tableColumn.".".$column, $value);
        }else{
            $query = $query->where($tableColumn.".".$column, $operator, $value);
        }
        return $query;
    }

    private function whereConditionSingleTable($oldQuery, $operator, $column, $value, $value2){
        $query = $oldQuery;
        if($operator=="range"){
            $query = $query->whereBetween($column, [$value, $value2]);
        }else if($operator=="like"){
            $query = $query->where($column, 'like', '%'.$value.'%');
        }else if($operator=="ilike"){
            $query = $query->where($column, '~*', $value);
        }else if($operator=="="){
            $query = $query->where($column, $value);
        }else if($operator=="in"){
            $query = $query->whereIn($column, $value);
        }else if($operator=="notin"){
            $query = $query->whereNotIn($column, $value);
        }else{
            $query = $query->where($column, $operator, $value);
        }
        return $query;
    }

    private function orWhereCondition($oldQuery, $operator, $tableColumn, $column, $value, $value2)
    {
        $query = $oldQuery;
        if($operator=="range"){
            $query = $query->orWhereBetween($tableColumn.".".$column, [$value, $value2]);
        }else if($operator=="like"){
            $query = $query->orWhere($tableColumn.".".$column, 'like', '%'.$value.'%');
        }else if($operator=="ilike"){
            $query = $query->where($tableColumn.".".$column, '~*', $value);
        }else if($operator=="="){
            $query = $query->orWhere($tableColumn.".".$column, $value);
        }else if($operator=="in"){
            $query = $query->orWhereIn($tableColumn.".".$column, $value);
        }else if($operator=="notin"){
            $query = $query->orWhereNotIn($tableColumn.".".$column, $value);
        }else{
            $query = $query->orWhere($tableColumn.".".$column, $operator, $value);
        }
        return $query;
    }

    protected function calculateAllCost($activity, $proyek_id){
        $humanCostPlanning = $this->calculateAllHumanCost($activity_id, $proyek_id);
        $materialCostPlanning = $this->calculateMaterialCost($activity_id, $proyek_id);
        $toolsCostPlanning = 0;

        $allCost = $humanCostPlanning + $materialCostPlanning + $toolsCostPlanning;
        return $allCost;
    }

    private function calculateAllHumanCost($activity_id, $proyek_id)
    {
        $dataHuman = UserToActivity::select("ahp.standart_rate as standart_rate","ahp.max_used as max_used", "ahp.cost_per_used as cost_per_used", "ahp.uom_standart_rate as uom_standart_rate")->leftJoin("assign_hr_to_proyek as ahp", "assign_hr_to_activity.user_id", "=", "ahp.user_id")
        ->where("assign_hr_to_activity.activity_id", $activity_id)->where("assign_hr_to_activity.proyek_id", $proyek_id)
        ->where("ahp.proyek_id", $proyek_id)
        ->get();

        $totalCost = 0;
        foreach ($dataHuman as $human) {
            $uom = $human->uom_standart_rate;
            $totalCost += $this->calculateHumanCost($human, $activity_id);
        }

        return $totalCost;
    }

    private function calculateHumanCost($human, $activity_id)
    {
        $activity = Activity::find($activity_id);
        $duration = $activity->duration;
        $standarRate = $human->standart_rate;
        $maxUsed = $human->max_used/100;
        $totalCost = ($standarRate*$duration)*$maxUsed;
        return $totalCost;
    }

    private function calculateMaterialCost($activity_id, $proyek_id)
    {
        $totalCost = AssignMaterial::selectRaw("ISNULL(qty_planning,0)*ISNULL(budget,0) as totalCost")->where("proyek_id", $proyek_id)->where("activity_id", $activity_id)->sum("totalCost");
        return $totalCost;
    }

    protected function updatedCostPlanning($id)
    {
        $sumBiaya = Activity::select(DB::raw('sum(cast(rencana_biaya as double precision))'))->where("parent_id", $id)->first();
        $dataActivity = Activity::find($id);
        $dataUpdate = array(
            "rencana_biaya" => $sumBiaya->sum,
            "updated_by" => $this->currentName
        );
        $dataActivity->update($dataUpdate);
        if($dataActivity){
            $parent = $dataActivity->parent_id;
            if($parent && (int)$parent > 0){
                $this->updateCostPlanning($parent);
            }
        }
    }
}