<?php

namespace Accounting\config;

use Accounting\ParamSetup;
use Base\DBQueries;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;

class DepartmentController extends ParamSetup
{
    private string $tbl = 'tbl_department';
    private Request $request;
    private $department_code;
    private $departmentStatus;
    private array $others;
    private $valuesToUpdate;
    const ARRAY_CATEGORIES = ['branches'];
    public function setParams()
    {
        return ['request' => $this->request, 'table' => $this->tbl];
    }

    public function main(Request $request): JsonResponse
    {
        $this->request = $request;

        try {
            if($this->generateParams()){
                $this->filterTable = $this->table;
                $action = $this->action;
                if (in_array($this->filterTable, array_keys(HIDDEN_REQUEST_FIELDS))) $this->others = $this->filterRequest();
                $this->execQuery();
                if ($this->response || $this->request->input("type") === "update") $this->saveOtherDetails();
                if ($this->response && $this->request->input("type") === "delete") $this->deleteDetails();
                return $this->getResponse($action);
            }
        } catch (\Exception $ex){
            return failedResponse("ERROR", ["msg" => $ex->getMessage()], 422);
        }
        return failedResponse("ERROR", ["msg" => "Unknown Error!"], 400);
    }
    private function getResponse($action): ?JsonResponse
    {
        if (in_array($this->filterTable, array_keys(HIDDEN_RESPONSE_FIELDS))) $this->filterResponse();
        $responseMsg = "No Data Found!";
        if($this->response) {
            if($action == 'dbInsert') {
                $responseMsg = 'dept_code';
            } else if($action === 'dbGetAll') {
                $response = $this->response;
                foreach ($response as $key => $data) {
                    $data->details = (new DBQueries("tbl_department_details", null, conditions: ["dept_code" => $data->code]))->dbGetAll();
                    $this->responseParser($data);
                }
                return successResponse("Success", $response);
            } else $responseMsg = "Success";
        }
        return successResponse($responseMsg, $this->response);
    }

    public function saveOtherDetails()
    {
        $this->department_code = $this->getValue('code');
        $this->departmentStatus = $this->getValue('status');
        if ($this->action === 'dbInsert') {
            $details = $this->others;
            foreach ($details['details'] as $k => $detail) {
                if (is_array($detail) || is_object($detail)) {
                    foreach ($detail as $key => $value) {
                        if (is_array($value)) {
                            foreach ($value as $k2 => $val) {
                                $this->addOtherDetails($k2, $k, $val);
                            }
                        } else $this->addOtherDetails($key, $k, $value);
                    }
                } else $this->addOtherDetails($k, 'info', $detail);
            }
        } else if ($this->action === "dbUpdate") {
            DB::table('tbl_department_details')->where('dept_code', $this->department_code)
                ->update(['status' => $this->departmentStatus]);
            $details = $this->others;
            foreach($details['details'] as $k => $detail) {
                if (is_array($detail)) {
                    foreach($detail as $key => $value) {
                        if (is_array($value)) {
                            foreach ($value as $k2 => $val) {
                                array_push($this->valuesToUpdate, $val);
                                $this->updateOtherDetails($k2, $k, $val);
                            }
                        }else $this->updateOtherDetails($key, $k, $value);
                    }
                    $this->valuesToUpdate = $detail;
                } else $this->updateOtherDetails($k, "info", $detail);
            }
             $this->onUpdateRemoveFields();
        }
    }

    private function addOtherDetails($type, $category, $value): void
    {
        $this->department_code = $this->getValue('code');
        $values['dept_code'] = $this->department_code;
        $values['type'] = $type;
        $values['category'] = $category;
        $values['value'] = $value;
        $values['status'] = $this->departmentStatus;
        $add = new DBQueries('tbl_department_details', $values);
        $this->response = $add->dbInsert();
    }
    private function updateOtherDetails($type, $category, $value): void
    {
        $this->department_code = $this->getValue('code');
        $conditions["dept_code"] = $this->department_code;
        $conditions["type"] = $type;
        $conditions["category"] = $category;
        $values["value"] = $value;
        $values["status"] = $this->departmentStatus;

        $query = DB::table('tbl_department_details')->where('dept_code', $this->department_code)
            ->where('type', $type)->where('value', $value)->first();
        if(empty($query) && in_array($category, self::ARRAY_CATEGORIES)){
            $this->addOtherDetails($type, $category, $value);
            return ;
        }
        if(!empty($query) && !is_null($query->deleted_at)) {
            DB::table('tbl_department_details')->where('dept_code', $this->department_code)
                ->where('type', $type)->where('value', $value)->update(['deleted_at' => null]);
            return ;
        }
        if(!in_array($category, self::ARRAY_CATEGORIES)){
            $this->response =  (new DBQueries("tbl_department_details", $values, $conditions))->dbUpdate();
        }
    }

    private function deleteDetails() : void {
        $department_code = $this->conditions['code'];

        $conditions["dept_code"] = $department_code;
        $this->response =  (new DBQueries("tbl_department_details", null, $conditions))->dbDelete();
    }

    private function responseParser($response) : void {
        $branchCodes = array();
        foreach($response->details as $detail) {
            $key = $detail->category;
            if($key === 'branches') {
                array_push($branchCodes, array('branchCode' => $detail->value));
            }
            $response->$key[$detail->type] = $detail->value ?? "";
        }
        $response->branches = $branchCodes;
        unset($response->details);
    }

    private function onUpdateRemoveFields() : void {
        $query = DB::table('tbl_department_details')->where('dept_code', $this->department_code)
            ->where('category', 'branches');
        $values = '';
        foreach ($this->valuesToUpdate as $k => $value) { $values .= $value['branchCode'] . ', '; }
        foreach($query->get() as $row) {
            if(!str_contains($values, $row->value)){
                DB::table('tbl_department_details')->where('dept_code', $this->department_code)
                    ->where('category', 'branches')->where('value', $row->value)->delete();
                // FOR SOFT DELETE
                /* $conditions["dept_code"] = $this->department_code;
                $conditions["category"] = 'branches';
                $conditions["value"] = $row->value;
                $this->response =  (new DBQueries("tbl_department_details", null, $conditions))->dbDelete(); */
            }
        }
    }
}
