<?php

namespace Accounting\config;

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

class TransactionSettings extends ParamSetup
{
    private string $tbl = 'tbl_transaction_settings';
    private Request $request;
    private array $others;
    private $trans_code;
    private $lastSubCategory;
    private $subCategoryQuery;

    public function setParams() : array
    {
        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();
                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 = 'trans_code';
            } else if($action === 'dbGetAll') {
                $response = $this->response;
                foreach ($response as $key => $data) {
                    $data->status = (bool)$data->status;
                    $data->details = (new DBQueries("tbl_transaction_settings_details", null, conditions: ["trans_code" => $data->code]))->dbGetAll();
                    $this->responseParser($data);
                }
                return successResponse("Success", $response);
            } else $responseMsg = "Success";
        }
        return successResponse($responseMsg, $this->response);
    }

    public function saveOtherDetails()
    {
        $details = $this->others;
        if ($this->action === 'dbInsert') {
            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, $key);
                            }
                        } else $this->addOtherDetails($key, $k, $value);
                    }
                } else $this->addOtherDetails($k, 'fieldConfig', $detail);
            }
        } else if ($this->action === "dbUpdate") {
            foreach($details['details'] as $k => $detail) {
                if (is_array($detail)) {
                    foreach($detail as $key => $value) {
                        if(is_int($key)) {
                            $this->lastSubCategory = $key;
                        }
                        if (is_array($value)) {
                            $this->subCategoryQuery = DB::table('tbl_transaction_settings_details')->where('trans_code', $this->trans_code)
                                ->where('category', $k)->orderByDesc('sub_category')->first();
                            foreach ($value as $k2 => $val) {
                                $this->updateOtherDetails($k2, $k, $val, $key);
                            }
                        }else $this->updateOtherDetails($key, $k, $value);
                    }
                } else $this->updateOtherDetails($k, 'fieldConfig', $detail);
            }
            if(!is_null($this->lastSubCategory)) $this->onUpdateRemoveFields($k, $this->lastSubCategory);
        }
    }

    private function addOtherDetails($type, $category, $value, $sub_category = null): void
    {
        $this->trans_code = $this->getValue('code');
        $values['trans_code'] = $this->trans_code;
        $values['type'] = $type;
        $values['category'] = $category;
        if (!is_null($sub_category)) $values["sub_category"] = $sub_category;
        $values['value'] = $value;
        $values['status'] = 1;
        $add = new DBQueries('tbl_transaction_settings_details', $values);
        $this->response = $add->dbInsert();
    }
    private function updateOtherDetails($type, $category, $value, $sub_category = null): void
    {
        $this->trans_code = $this->getValue('code');
        $conditions["trans_code"] = $this->trans_code;
        $conditions["type"] = $type;
        $conditions["category"] = $category;
        if (!is_null($sub_category)) $conditions["sub_category"] = $sub_category;
        $values["value"] = $value;
        $values["status"] = 1;

        if($this->subCategoryQuery && !is_null($this->subCategoryQuery->sub_category)) {
            if($sub_category > $this->subCategoryQuery->sub_category) {
                $this->addOtherDetails($type, $category, $value, $sub_category);
                return ;
            }
        }

        $this->response =  (new DBQueries("tbl_transaction_settings_details", $values, $conditions))->dbUpdate();
    }

    private function onUpdateRemoveFields($category, $lastSubCategory) : void
    {
        $getData = DB::table('tbl_transaction_settings_details')->where('trans_code', $this->trans_code)->where('category', $category)->get();
        if(!is_null($getData->value('sub_category'))) {
            foreach ($getData as $data) {
                if($data->sub_category > $lastSubCategory) {
                    DB::table('tbl_transaction_settings_details')->where('trans_code', $this->trans_code)
                        ->where('sub_category', $data->sub_category)->delete();
                }
            }
        }
    }

    private function responseParser($response) : void
    {
        foreach ($response->details as $detail) {
            $key = $detail->category;
            if (is_null($detail->sub_category)) {
                $response->$key[$detail->type] = $detail->value ?? "";
            } else {
                if (!property_exists($response, $key)) $response->$key = [];
                if (!array_key_exists($detail->sub_category, $response->$key)) $response->$key[$detail->sub_category] = [];
                $response->$key[$detail->sub_category][$detail->type] = $detail->value ?? "";
            }
        }
        unset($response->details);
    }
}
