<?php

namespace App\Services;

use App\Models\User;
use App\Models\Ward;
use App\Models\Zone;
use App\Models\Status;
use App\Models\VrukshType;
use Illuminate\Support\Facades\DB;
use App\Models\ApprovalHierarchies;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Config;
use App\Models\ApprovalRequestHierarchy;

class CommonService
{
    private $waterKey;

    public function __construct()
    {
        $this->waterKey = Config::get('rtsapiurl.waterkey');
    }

    public function getActiveWard()
    {
        return Ward::where('status', 1)->get();
    }


    public function getActiveVruksh()
    {
        
        return VrukshType::all();
    }


    public function getActiveZone()
    {
        return Zone::where('status', 1)->get();
    }

    function encryptString($plainText)
    {
        $key = $this->waterKey;
        $iv = str_repeat("\0", 16);

        $ciphertext = openssl_encrypt(
            $plainText,
            'aes-256-cbc',
            $key,
            OPENSSL_RAW_DATA,
            $iv
        );

        return strtoupper(bin2hex($ciphertext));
    }

    function encryptStringProperty($plainText)
    {
        $key = 'AS23N7E2H4V717DEAS23N7E2H4V717DE';
        $iv = str_repeat("\0", 16);

        $ciphertext = openssl_encrypt(
            $plainText,
            'aes-256-cbc',
            $key,
            OPENSSL_RAW_DATA,
            $iv
        );

        return strtoupper(bin2hex($ciphertext));
    }

    function decryptString($cipherText)
    {
        $key = $this->waterKey;
        // if (strlen($key) !== 32) {
        //     return "Invalid key length. The key should be 32 bytes (256 bits).";
        // }

        $encryptedBytes = hex2bin($cipherText);

        $iv = str_repeat("\0", 16);

        $decryptedData = openssl_decrypt(
            $encryptedBytes,
            'aes-256-cbc',
            $key,
            OPENSSL_RAW_DATA,
            $iv
        );

        if ($decryptedData === false) {
            return "Decryption failed";
        }

        return $decryptedData;
    }

    function decryptStringProperty($cipherText)
    {
        $key = 'AS23N7E2H4V717DEAS23N7E2H4V717DE';
        // if (strlen($key) !== 32) {
        //     return "Invalid key length. The key should be 32 bytes (256 bits).";
        // }

        $encryptedBytes = hex2bin($cipherText);

        $iv = str_repeat("\0", 16);

        $decryptedData = openssl_decrypt(
            $encryptedBytes,
            'aes-256-cbc',
            $key,
            OPENSSL_RAW_DATA,
            $iv
        );

        if ($decryptedData === false) {
            return "Decryption failed";
        }

        return $decryptedData;
    }

    public function propertyDataStrore($encryptedString)
    {
        $url = config('payment.store_propertydata');

        $encodeData = json_encode([
            "RTSPostData" => [
                [
                    "encr_request" => $encryptedString
                ]
            ]
        ]);

        $ch = curl_init($url);

        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $encodeData);
        curl_setopt($ch, CURLOPT_HTTPHEADER, [
            'Content-Type: application/json',
            'Content-Length: ' . strlen($encodeData)
        ]);

        $response = curl_exec($ch);

        if (curl_errno($ch)) {
            return "error: " . curl_error($ch);
        }

        curl_close($ch);

        $data = json_decode($response);

        if (isset($data->RTSPostData[0]->encr_Response)) {
            $decrypted = $this->decryptStringProperty($data->RTSPostData[0]->encr_Response);

            $decryptedArray = json_decode($decrypted, true);
            if (isset($decryptedArray['RTSPostData'])) {
                return [
                    "RTSPostData" => $decryptedArray['RTSPostData']
                ];
            } else {
                return "Unexpected decrypted format: " . $decrypted;
            }
        } else {
            return "Invalid response: " . $response;
        }
    }

    // No Due Service Api
     public function sendNODueEncryptedData($encryptedData)
    {

        $url = config('payment.no_due_details');

        $encodeData =  json_encode([
            "jsonData" => [
                [
                    "encr_request" => $encryptedData
                ]
            ]
        ]);


        $ch = curl_init($url);


        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $encodeData);
        curl_setopt($ch, CURLOPT_HTTPHEADER, [
            'Content-Type: application/json',
            'Content-Length: ' . strlen($encodeData)
        ]);


        $response = curl_exec($ch);


        if (curl_errno($ch)) {
            return "error";
        }
        curl_close($ch);
        $data = json_decode($response);
        return $this->decryptString($data->jsonData[0]->encr_Response);
    }

    public function sendEncryptedData($encryptedData)
    {
        $url = config('payment.property_details');
        $encodeData = json_encode([
            "jsonData" => [
                [
                    "encr_request" => $encryptedData
                ]
            ]
        ]);

        $ch = curl_init($url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $encodeData);
        curl_setopt($ch, CURLOPT_HTTPHEADER, [
            'Content-Type: application/json',
            'Content-Length: ' . strlen($encodeData)
        ]);
        $response = curl_exec($ch);
        if (curl_errno($ch)) {
            return "error";
        }


        curl_close($ch);
        $data = json_decode($response);
        return $this->decryptString($data->jsonData[0]->encr_Response);
    }

    public function sendEncryptedWaterData($encryptedData)
    {
        //$urluat = "https://nagarkaryavaliuat.com/MBMCRTSAPI/Service.svc/GetWtDataDetails";
          $url = "https://nagarkaryavali.com/MBMCRTSAPI/Service.svc/GetWtDataDetails";

        $encodeData = json_encode([
            "jsonData" => [
                [
                    "encr_request" => $encryptedData
                ]
            ]
        ]);

        //dd($encodeData);




        $ch = curl_init($url);


        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $encodeData);
        curl_setopt($ch, CURLOPT_HTTPHEADER, [
            'Content-Type: application/json',
            'Content-Length: ' . strlen($encodeData)
        ]);


        $response = curl_exec($ch);
        

        if (curl_errno($ch)) {
            return "error";
        }


        curl_close($ch);
        $data = json_decode($response);
        return $this->decryptString($data->jsonData[0]->encr_Response);
    }

    public function store_approval_hierarchies($data, $user, $status, $start_from = 0)
    {
        DB::beginTransaction();

        try {
            $input['user_id'] = $user->id;
            $hierarchy = [];

            if ($status->service_id) {
                $hierarchy = ApprovalRequestHierarchy::where('service_id', $status->service_id)->first();
                \Log::info("Fetched hierarchy by service_id:$status->service_id", [$hierarchy]);
            }


            // if (empty($hierarchy)) {
            //     $hierarchy = ApprovalRequestHierarchy::where('requester_department_id', $status->department_id)->first();
            //     \Log::info('Fetched hierarchy by department_id:', [$hierarchy]);
            // }


            if (empty($hierarchy)) {
                DB::rollBack();
                \Log::warning("No approval hierarchy found for service_id: {$status->service_id} or department_id: {$status->department_id}");
                return response()->json([
                    'status' => false,
                    'message' => 'No approval hierarchy configured for this request.'
                ], 404);
            }

            $approverNames = ['first', 'second', 'third', 'fourth', 'five', 'six', 'seven', 'eight'];
            $approverNames = array_slice($approverNames, $start_from);
            $createdApprovers = [];

            foreach ($approverNames as $index => $approverName) {
                $designationKey = $approverName . '_approver_designation_id';
                $departmentKey = $approverName . '_department_id';

                if (!empty($hierarchy->$designationKey)) {
                    $targetDepartmentId = $hierarchy->$departmentKey ?? $hierarchy->requester_department_id;

                    $approver = User::whereHas('departments', function ($q) use ($targetDepartmentId, $data) {
                        $q->where('department_id', $targetDepartmentId)
                            ->when(!empty($data->ward_area), function ($query) use ($data) {
                                $query->where('ward_name', $data->ward_area);
                            });
                    })->whereHas('roles', function ($query) use ($hierarchy, $designationKey) {
                        $query->where('id', $hierarchy->$designationKey);
                    })
                        ->first();

                    if ($approver) {
                        ApprovalHierarchies::create([
                            'status_id' => $status->id,
                            'service_id' => $data->service_id,
                            'user_id' => $data->user_id,
                            'approver_user_id' => $approver->id,
                            'table_id' => $data->id,
                            'approver_department_id' => $approver->department_id,
                            'status' => 0,
                            'next_approval_flag' => empty($createdApprovers) ? 1 : 0,
                        ]);
                        $createdApprovers[] = $approver->id;
                    } else {
                        \Log::warning("Approver not found for level: {$approverName}", [
                            'designation_id' => $hierarchy->$designationKey,
                            'department_id' => $hierarchy->$departmentKey ?? null
                        ]);
                    }
                }
            }


            // If no approvers were created at all, rollback
            if (empty($createdApprovers)) {
                DB::rollBack();
                return response()->json([
                    'status' => false,
                    'message' => 'No valid approvers found. Approval hierarchy could not be created.'
                ], 422);
            }

            DB::commit();

            return response()->json([
                'status' => true,
                'message' => 'Approval hierarchy created successfully.',
                'approvers' => $createdApprovers
            ], 201);
        } catch (\Exception $e) {
            DB::rollBack();
            \Log::error('Error storing approval hierarchy:', ['exception' => $e]);
            return response()->json([
                'status' => false,
                'message' => 'An error occurred while creating the approval hierarchy.',
                'error' => $e->getMessage()
            ], 500);
        }
    }


    public function reset_next_approvers($statusId)
    {
        DB::beginTransaction();

        try {
            $status = Status::with(['user', 'serviceName'])->find($statusId);
            if (!$status) {
                DB::rollBack();
                return response()->json([
                    'status' => false,
                    'message' => 'Status record not found.'
                ], 404);
            }
            $data = $status->serviceName->model::where('id', $status->table_id)->first();
            // dd($data);



            $current = ApprovalHierarchies::where('status_id', $statusId)
                ->where('status', 0)
                ->where('next_approval_flag', 1)
                ->first();
            if (!$current) {
                $currentIndex = 0;
            }else{

                $allHierarchies = ApprovalHierarchies::where('status_id', $statusId)
                    ->orderBy('id', 'asc')
                    ->get();
                $currentIndex = $allHierarchies->search(fn($item) => $item->id === $current->id);
                $nextLevels = $allHierarchies->slice($currentIndex);
                if ($nextLevels->isNotEmpty()) {
                    $idsToDelete = $nextLevels->pluck('id')->toArray();
                    ApprovalHierarchies::whereIn('id', $idsToDelete)->whereStatus(0)->delete();
                    $start_from = $currentIndex;
                    \Log::info("Deleted next-level approvers", ['ids' => $idsToDelete]);
                } else {
                    ApprovalHierarchies::where('status_id', $statusId)->whereStatus(0)->delete();
                    $start_from = $currentIndex;
                    \Log::info("Deleted next-level approvers");
                }
             }
            $response = $this->store_approval_hierarchies($data, $data->user, $status, $start_from);

            $responseData = $response->getData(true);
            if (!empty($responseData['status']) && $responseData['status'] === true) {
                    DB::commit();
                  return response()->json([
                    'status' => true,
                    'message' => 'Next approvers reset and rebuilt successfully.',
                    ], 200);
            } else {
                // Failure case
                DB::rollBack();
                return response()->json([
                    'status' => false,
                    'message' => $responseData['message'],

                ], 422);
            }

        } catch (\Exception $e) {
            DB::rollBack();
            \Log::error('Error resetting next approvers:', ['exception' => $e]);
            return response()->json([
                'status' => false,
                'message' => 'Error while resetting next approvers.',
                'error' => $e->getMessage()
            ], 500);
        }
    }


    public function getFirstApproverId(int $statusId)
    {
        $firstApprover = ApprovalHierarchies::where('status_id', $statusId)->first();

        return $firstApprover ? $firstApprover->approver_user_id : null;
    }

}
