<?php

namespace Accounting\config;

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

class SubsidiaryLedgerMapping extends ParamSetup
{
    private string $tbl = 'tbl_subsidiary_ledger';
    private Request $request;

    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;
                $account_code = $this->getValue('accCode');
                $sl_code = $this->getValue('slCode');
                $type = $this->getValue('type');
                $map_column = $this->getValue('mapColumn');
                $status = $this->getValue('status');

                $acc_code = DB::table('tbl_chart_of_accounts')->where('custom_code', $this->getValue('accCode'))->first();
                if($action === 'dbUpdate') {
                    $this->conditions['acc_code'] = $acc_code->code;
                    $this->values['acc_code'] = $acc_code->code;
                }

                if($action === 'dbDelete') {
                    $acc_code = DB::table('tbl_chart_of_accounts')->where('custom_code', $this->conditions['acc_code'])->first();
                    $this->conditions['acc_code'] = $acc_code->code;
                }

                if($action === 'dbInsert') {
                    $isExisting = $this->isDuplicate($acc_code->code, $sl_code, $type, $map_column);
                    if($acc_code){
                        if($isExisting === 0) {
                            $this->addValues('accCode', $acc_code->code);
                            $this->response = $this->insertValue();
                        } else if(($isExisting === -1)) {
                            $account_code = $acc_code->code;
                            DB::table('tbl_subsidiary_ledger')->where('acc_code', $account_code)
                                ->where('sl_code', $sl_code)->update(["deleted_at" => null, "status" => $status]);
                        } else {
                            return failedResponse("ERROR", ["msg" => 'Duplicate record. This already exists.'], 422);
                        }
                    }
                    else return failedResponse("ERROR", ["msg" => 'Custom code does not exists.'], 422);
                }
                else $this->execQuery();

                return $this->getResponse($action);
            }
        } catch (\Exception $ex) {
            return failedResponse("ERROR", ["msg" => $ex->getMessage()], 422);
        }
        return failedResponse("ERROR", ["msg" => "Unknown Error!"], 400);
    }

    private function insertValue() {
        return (new DBQueries('tbl_subsidiary_ledger', $this->values))->dbInsert();
    }


    private function isDuplicate($acc_code, $sl_code, $type, $map_column) : int
    {
        $query = DB::table('tbl_subsidiary_ledger')->where('acc_code', $acc_code)->where('sl_code', $sl_code)
            ->where('type', $type)->where('map_column', $map_column)->first();

       if(!$query) return 0; // totally doesn't exist

       if(!is_null($query->deleted_at)) return -1; // exists but deleted

       return 1; // existing and not deleted
    }

    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 = 'Successfully added!';
            } else if ($action === 'dbGetAll') {
                $response = $this->response;
                $response->map(function ($response){
                    $acc_code = DB::table('tbl_chart_of_accounts')->where('code', $response->acc_code)->first();
                    $response->acc_code = $acc_code?->custom_code;
                });
                return successResponse("Success", $response);
            } else $responseMsg = "Success";
        }
        return successResponse($responseMsg, $this->response);
    }

    // NOTE: for listing in Subsidiary Ledger Mapping | INDEPENDENT FUNCTION (FROM MAIN)
    public function entitiesOperationsListing(){
        $result = DB::select("SELECT CODE, NAME, type AS TYPE, 'entities' AS CATEGORY FROM tbl_entities
                                    WHERE approval_status = 1 AND status = 1 AND deleted_at IS NULL
                                    UNION
                                    SELECT opt.code, opt.name AS NAME, opt.type, 'operations' AS CATEGORY FROM tbl_operations AS opt
                                    WHERE opt.status = 1 AND deleted_at IS NULL ORDER BY category, TYPE");

        $this->response = $result;

        return successResponse("Success", $result);
    }

    public function journalVoucherSLListing(){
        $result = DB::select("SELECT code, name, type AS type FROM tbl_entities
                                    WHERE approval_status = 1 AND status = 1 AND deleted_at IS NULL
                                    UNION
                                    SELECT opt.code, opt.name, opt.type FROM tbl_operations AS opt
                                    WHERE opt.type = 'operation' AND opt.status = 1 AND deleted_at IS NULL order by
                                    CASE WHEN type = 'customer' THEN 1
                                        WHEN type ='supplier' THEN 2
                                        WHEN type = 'agent' THEN 3
                                        WHEN type = 'purchaser' THEN 4 ELSE 5 END");

        $this->response = $result;

        return successResponse("Success", $result);
    }

}
