<?php

namespace App\Http\Controllers\Wallet;

use App\Events\PusherEvent;
use App\Helpers\ResponseHelper;
use App\Http\Controllers\Controller;
use App\Models\ApiKey\ApikeyModel;
use App\Models\ErrorLogs\ErrorLogsModel;
use App\Models\InternalUserProfilesModel;
use App\Models\LinesModel;
use App\Models\ProvinceAndCity\CityModel;
use App\Models\ProvinceAndCity\ProvinceModel;
use App\Models\User;
use App\Models\WalletModel;
use Illuminate\Http\Request;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use PhpParser\Node\Scalar\String_;
use Psy\Util\Str;

class WalletController extends Controller
{

    public function modifyCredit(Request $request)
    {
        $apikey = ApikeyModel::where('apikey', $request->header('apikey'))->first();
        if ($apikey) {
            /** Define requestBody */

            $user_id = $request->user_id;
            $uc = $request->uc;
            $price = $request->price;
            $type = $request->type;

            /** Check if all filed is fill */
            if (!isset($user_id)) {
                return ResponseHelper::systemErrorResponse(0, "ایدی کاربر الزامیست", [], 200, 5);
            }
            if (!isset($price)) {
                return ResponseHelper::systemErrorResponse(0, "مبلغ تراکنش الزامیست", [], 200, 6);
            }
            if (!isset($type)) {
                return ResponseHelper::systemErrorResponse(0, "تایپ تراکنش الزامیست", [], 200, 7);
            }
            if (!isset($uc)) {
                return ResponseHelper::systemErrorResponse(0, "شناسه شهر الزامیست", [], 200, 8);
            }


            /** find User Using id */
            $findUser = User::where('id', $user_id)->first();
            // if user not found return unsuccessfully response
            if (!$findUser) {
                return ResponseHelper::systemErrorResponse(0, "کاربر یافت نشد", [], 404, 2);
            }
            /** find City UC */
            $findCityUC = CityModel::where('uc', $uc)->first();
            // if uc of city not found return unsuccessfully response
            if (!$findCityUC) {
                return ResponseHelper::systemErrorResponse(0, "شهر یافت نشد", [], 404, 3);
            }
            /** find City UC */
            $findWallet = WalletModel::where('city_id', $findCityUC->id)->where('user_id', $user_id)->first();
            // if wallet not found return unsuccessfully response
            if (!$findWallet) {
                return ResponseHelper::systemErrorResponse(0, "کیف پول یافت نشد", [], 404, 4);
            }

            /** update user wallet */
            $priceToUpdate = 0;
            if ($type == 1) {
                $priceToUpdate = $findWallet->credit + $price;
            } else if ($type == 2) {
                $priceToUpdate = $findWallet->credit - $price;
            }

            $updateWallet = WalletModel::where('city_id', $findCityUC->id)->where('user_id', $user_id)->update([
                'credit' => $priceToUpdate
            ]);

            if ($updateWallet) {
                if ($type == 2) {
                    broadcast(new PusherEvent(['type' => 1, 'message' => 'کسر اعتبار با موفقیت انجام شد']))->toOthers();
                }
                return ResponseHelper::successResponse(1, "تراکنش با موفقیت انجام شد", [], 200);
            } else {
                return ResponseHelper::unSuccessResponse(0, "خطا در انجام تراکنش", 200);
            }
        } else {
            ErrorLogsModel::insert([
                'type' => 1,
                'description' => "modifyCredit | apikey auth unsuccessfully!",
                'ip_address' => $request->ip()
            ]);
            return response()->json(['status' => 0, 'message' => "خطا در احراز هویت سرویس", 'code' => 500], 200);
        }
    }

    public function getUserWallet(Request $request)
    {
        $verifyApiKey = ApikeyModel::where('apikey', $request->header('apikey'))->first();


        if ($verifyApiKey) {

            $wallet = WalletModel::where('user_id', Auth::user()->getAuthIdentifier())->get();
            if (count($wallet) > 0) {

                $walletData = [];
                foreach ($wallet as $key) {
                    $city = CityModel::where('id', $key->city_id)->first();
                    if ($city) {
                        // تنظیم پارامترهای کانکشن به صورت داینامیک
                        $host = $city->ip_address;
                        $port = '1433'; // پورت پیش‌فرض SQL Server
                        $database = 'Ecity'; // نام دیتابیس
                        $username = $city->username;
                        $password = $city->password;

                        // ایجاد نام کانکشن داینامیک
                        $dynamicConnectionName = 'dynamic_sqlsrv_' . $city->id;

                        // حذف کانکشن موجود با همین نام (اگر وجود داشته باشد)
                        DB::purge($dynamicConnectionName);

                        // تنظیم کانفیگ برای کانکشن داینامیک
                        config([
                            "database.connections.$dynamicConnectionName" => [
                                'driver' => 'sqlsrv',
                                'host' => $host,
                                'port' => $port,
                                'database' => $database,
                                'username' => $username,
                                'password' => $password,
                                'charset' => 'utf8',
                                'prefix' => '',
                                'prefix_indexes' => true,
                                'encrypt' => 'no',
                                'trust_server_certificate' => env('DB_TRUST_SERVER_CERTIFICATE', 'true')
                            ],
                        ]);


                        try {
                            // چک کردن وجود شماره موبایل کاربر در SQL Server
                            $sql_srv = DB::connection($dynamicConnectionName)->table('ACardT')->select('*')->where('Mobile', Auth::user()->phone)->get();
                            if ($sql_srv) {
                                $card_id = (string)$sql_srv[0]->Code;
                                $uc = (int)$sql_srv[0]->UC;
                            }
                        } catch (\Exception $e) {
                            return response()->json(['status' => 0, 'message' => 'برقرار نشد' . $key->name . 'ارتباط با سرور مرکز ']);
                        }

                        $walletData[] = [
                            'id' => $key->id,
                            'user_id' => $key->user_id,
                            'city_id' => $key->city_id,
                            'city' => $city->name,
                            'credit' => $key->credit,
                            'created_at' => Carbon::createFromFormat('Y-m-d H:i:s', $key->created_at)->timestamp,
                            'updated_at' => Carbon::createFromFormat('Y-m-d H:i:s', $key->updated_at)->timestamp,
                            'uc' => $uc,
                            'card_id' => $card_id
                        ];
                    }

                }
                return response()->json(['status' => 1, 'message' => 'کیف پول یافت شد', 'data' => $walletData]);
            } else {
                return response()->json(['status' => 0, 'message' => 'کیف پول یافت نشد']);
            }
        } else {
            ErrorLogsModel::insert([
                'type' => 1,
                'description' => "Get User Wallet | apikey auth unsuccessfully!",
                'ip_address' => $request->ip()
            ]);
            return response()->json(['status' => 0, 'message' => "خطا در احراز هویت سرویس", 'code' => 500], 200);
        }
    }

    public function syncWallet(Request $request)
    {
        $verifyApiKey = ApikeyModel::where('apikey', $request->header('apikey'))->first();

        if ($verifyApiKey) {
            $data = $request->json()->all();
            $user = Auth::user();

            if (!isset($data['data'])) {
                return response()->json(['status' => 0, 'message' => 'دیتا الزامیست!', 'code' => 666]);
            }

            $array = $data['data'];


            if (!is_array($array)) {
                return response()->json(['status' => 0, 'message' => 'فرمت داده‌ها نادرست است!', 'code' => 667]);
            }

            $updatedArray = [];

            foreach ($array as $item) {
                WalletModel::where('id', $item['id'])->where('user_id', $item['userId'])->where('city_id', $item['cityId'])->update([
                    'credit' => $item['credit'],
                ]);

                $wallet = WalletModel::where('id', $item['id'])->first();

                if (!$wallet) {
                    return response()->json(['status' => 0, 'message' => 'کیف با پول ایدی ' . $item['id'] . ' یافت نشد']);
                }
                $city = CityModel::where('id', $wallet->city_id)->first();


                $updatedArray[] = [
                    'id' => $item['id'],
                    'user_id' => $item['userId'],
                    'city_id' => $item['cityId'],
                    'city' => $city->name,
                    'credit' => $item['credit'],
                    'created_at' => $item['createdAt'],
                    'updated_at' => $item['updatedAt'],
                    'uc' => $city->uc,
                    'card_id' => $item['cardId'],
                ];
            }
            return response()->json(['status' => 1, 'message' => 'کیف پول ها با موفقیت همگام سازی شدند', 'data' => (object)['transaction' => $updatedArray]], 200);


        } else {
            ErrorLogsModel::insert([
                'type' => 1,
                'description' => "sync Wallet | apikey auth unsuccessfully!",
                'ip_address' => $request->ip()
            ]);
            return response()->json(['status' => 0, 'message' => "خطا در احراز هویت سرویس", 'code' => 500], 200);
        }
    }

    public function insertWallet(Request $request)
    {
        // Verify API key from request header
        $verifyApiKey = ApikeyModel::where('apikey', $request->header('apikey'))->first();

        if ($verifyApiKey) {

            // Check if city exists
            $verify_city = CityModel::where('id', $request->city_id)->first();

            if (!$verify_city) {
                return response()->json(['status' => 0, 'message' => 'City ID not found on server']);
            }

            // Check if user already has a wallet in the specified city
            $check_city_wallet = WalletModel::where('user_id', Auth::user()->getAuthIdentifier())
                ->where('city_id', $request->city_id)
                ->first();

            if ($check_city_wallet) {
                return response()->json(['status' => 0, 'message' => "شما در این شهر کیف پول دارید"], 200);
            }

            // Fetch city details
            $city = CityModel::select('*')->where('id', $request->city_id)->first();

            // Set up dynamic connection parameters
            $host = $city->ip_address;
            $port = '1433'; // Default SQL Server port
            $database = 'Ecity'; // Database name
            $username = $city->username;
            $password = $city->password;

            // Create a dynamic connection name
            $dynamicConnectionName = 'dynamic_sqlsrv_' . $city->id;

            // Purge existing connection with the same name (if any)
            DB::purge($dynamicConnectionName);

            // Configure the dynamic connection
            config([
                "database.connections.$dynamicConnectionName" => [
                    'driver' => 'sqlsrv',
                    'host' => $host,
                    'port' => $port,
                    'database' => $database,
                    'username' => $username,
                    'password' => $password,
                    'charset' => 'utf8',
                    'prefix' => '',
                    'prefix_indexes' => true,
                    'encrypt' => 'no',
                    'trust_server_certificate' => env('DB_TRUST_SERVER_CERTIFICATE', 'true')
                ],
            ]);

            try {
                // Check if user mobile number exists in SQL Server
                $sql_srv = DB::connection($dynamicConnectionName)
                    ->table('ACardT')
                    ->select('*')
                    ->where('Mobile', Auth::user()->phone)
                    ->get();

                if ($sql_srv->count() == 0) {
                    // Generate a unique code
                    $isUniqueCode = false;
                    $param1 = 0;
                    while (!$isUniqueCode) {
                        $param1 = rand(100000, 999999);
                        $codeExists = DB::connection($dynamicConnectionName)
                            ->table('ACardT')
                            ->where('Code', $param1)
                            ->exists();
                        if (!$codeExists) {
                            $isUniqueCode = true;
                        }
                    }

                    // Begin database transaction
                    DB::beginTransaction();

                    // Insert new card and get its ID
                    $id = DB::connection($dynamicConnectionName)
                        ->table('ACardT')
                        ->insertGetId([
                            'Code' => $param1,
                            'FKCardGroup' => 1,
                            'PreCode' => 0,
                            'CardPrice' => 0,
                            'CardType' => 1,
                            'DateTime' => Carbon::now(),
                            'PLack' => 0,
                            'Mobile' => Auth::user()->phone,
                            'Name' => 0,
                            'Fam' => 0,
                            'Number' => 0,
                            'UC' => $city->uc,
                        ]);

                    if (!$id) {
                        DB::rollBack();
                        return response()->json(['status' => 0, 'message' => "خطا در ایجاد کاربر در سرور مرکزی"]);
                    }

                    // Check and create internal user profile
                    $internalUserProfiles = InternalUserProfilesModel::where('user_id', Auth::user()->getAuthIdentifier())
                        ->where('city_id', $city->id)
                        ->where('uc', $city->uc)
                        ->first();

                    if (!$internalUserProfiles) {
                        $internalUserProfiles = new InternalUserProfilesModel();
                        $internalUserProfiles->city_id = $city->id;
                        $internalUserProfiles->user_id = Auth::user()->getAuthIdentifier();
                        $internalUserProfiles->uc = $city->uc;
                        $internalUserProfiles->card_id = $param1;

                        if (!$internalUserProfiles->save()) {
                            DB::rollBack();
                            return response()->json(['status' => 0, 'message' => "خطا در ایجاد پروفایل مرکزی کاربر در پایگاه داده اطلاعاتی"]);
                        }
                    }

                    // Create a new wallet
                    $now = Carbon::now();
                    $nowTime = $now->timestamp;
                    $wallet = new WalletModel();
                    $wallet->user_id = Auth::user()->getAuthIdentifier();
                    $wallet->city_id = $request->city_id;
                    $wallet->credit = 0;
                    $wallet->created_at = $nowTime;
                    $wallet->updated_at = $nowTime;

                    if (!$wallet->save()) {
                        DB::rollBack();
                        return response()->json(['status' => 0, 'message' => "خطا در ایجاد کیف پول"]);
                    }

                    // Prepare response data
                    $city_key = CityModel::where('id', $request->city_id)->first();
                    $ucValue = $city_key->uc;
                    $city_name = CityModel::where('id', $request->city_id)->first()->name;

                    $responseData = $wallet->toArray();
                    $responseData['city'] = $city_name;
                    $responseData['uc'] = $ucValue;
                    $responseData['card_id'] = (string)$sql_srv[0]->Code;

                    $responseData['created_at'] = $nowTime;
                    $responseData['updated_at'] = $nowTime;

                    // Commit the transaction and return success response
                    if ($wallet) {
                        DB::commit();
                        return response()->json(['status' => 1, 'message' => 'کیف پول با موفقیت ساخته شد', 'data' => ['wallet' => $responseData]]);
                    } else {
                        DB::rollBack();
                        return response()->json(['status' => 0, 'message' => 'خطا در ایجاد کیف پول کاربر']);
                    }

                } else {
                    // Handle existing card scenario
                    $internalUserProfiles = InternalUserProfilesModel::where('user_id', Auth::user()->getAuthIdentifier())
                        ->where('city_id', $city->id)
                        ->where('uc', $city->uc)
                        ->first();

                    if (!$internalUserProfiles) {
                        $internalUserProfiles = new InternalUserProfilesModel();
                        $internalUserProfiles->city_id = $city->id;
                        $internalUserProfiles->user_id = Auth::user()->getAuthIdentifier();
                        $internalUserProfiles->uc = $city->uc;
                        $internalUserProfiles->card_id = $sql_srv[0]->Code;

                        if (!$internalUserProfiles->save()) {
                            return response()->json(['status' => 0, 'message' => "خطا در ایجاد پروفایل مرکزی کاربر در پایگاه داده اطلاعاتی"]);
                        }
                    }

                    // Create a new wallet for existing user
                    $now = Carbon::now();
                    $nowTime = $now->timestamp;
                    $wallet = new WalletModel();
                    $wallet->user_id = Auth::user()->getAuthIdentifier();
                    $wallet->city_id = $request->city_id;
                    $wallet->credit = 0;
                    $wallet->created_at = $nowTime;
                    $wallet->updated_at = $nowTime;
                    $wallet->save();

                    // Prepare response data
                    $city_key = CityModel::where('id', $request->city_id)->first();
                    $ucValue = $city_key->uc;

                    $city_name = CityModel::where('id', $request->city_id)->first()->name;

                    $responseData = $wallet->toArray();
                    $responseData['city'] = $city_name;
                    $responseData['uc'] = $ucValue;
                    $responseData['card_id'] = (string)$sql_srv[0]->Code;

                    $responseData['created_at'] = $nowTime;
                    $responseData['updated_at'] = $nowTime;

                    return response()->json([
                        'status' => 1,
                        'message' => 'کیف پول با موفقیت ایجاد شد',
                        'data' => $responseData
                    ]);
                }
            } catch (\Exception $e) {
                return response()->json(['status' => 0, 'message' => 'خطا در اتصال به سرور مرکزی', 'error' => $e->getMessage()]);
            }
        } else {
            // Log error for unsuccessful API key authentication
            ErrorLogsModel::insert([
                'type' => 1,
                'description' => "Insert User Wallet | API key authentication failed",
                'ip_address' => $request->ip()
            ]);
            return response()->json(['status' => 0, 'message' => "Service authentication error", 'code' => 500], 200);
        }
    }


    /**
     * Verify the user's wallet based on the API key and return wallet details.
     *
     * @param Request $request
     * @return \Illuminate\Http\JsonResponse
     */
    function verifyWallet(Request $request)
    {
        // Check if the API key is valid
        $verifyApiKey = ApikeyModel::where('apikey', $request->header('apikey'))->first();

        if ($verifyApiKey) {
            // Retrieve the wallet associated with the authenticated user
            $wallet = WalletModel::filterByUserId(Auth::user()->getAuthIdentifier());
            if (count($wallet) > 0) {
                $cities = [];
                $cities_wihtoutHost = [];
                $provinces = [];
                $ucPerCity = []; // Dictionary to hold UC values for each city
                $city_namePerCity = [];
                $user_card_id_per_city = []; // Dictionary to hold card_ids for each city

                // Iterate over each wallet entry to fetch city and province information
                foreach ($wallet as $key => $value) {
                    $value->created_at = Carbon::createFromFormat('Y-m-d H:i:s', $value->created_at)->timestamp;
                    $value->updated_at = Carbon::createFromFormat('Y-m-d H:i:s', $value->updated_at)->timestamp;


                    // Get the city model based on the city ID from the wallet
                    $cityModel = CityModel::where('id', $value->city_id)->first();
                    $cityModel_WithoutHost = CityModel::where('id', $value->city_id)->select('id', 'province_id', 'uc', 'name', 'isActivate', 'merchant_id', 'created_at', 'updated_at')->first();

                    // Add city to the list if not already included
                    if ($cityModel && !in_array($cityModel->id, array_column($cities, 'id'))) {
                        $cities[] = $cityModel;
                    }


                    // Add city to the list if not already included
                    if ($cityModel_WithoutHost && !in_array($cityModel_WithoutHost->id, array_column($cities_wihtoutHost, 'id'))) {
                        $cities_wihtoutHost[] = $cityModel_WithoutHost;
                    }
                    // Get the province model based on the province ID from the city model
                    $provinceModel = ProvinceModel::where('id', $cityModel->province_id)->first();

                    // Add province to the list if not already included
                    if ($provinceModel && !in_array($provinceModel->id, array_column($provinces, 'id'))) {
                        $provinces[] = $provinceModel;
                    }

                    // Initialize UC list for the city if not already set
                    if (!isset($ucPerCity[$cityModel->id])) {
                        $ucPerCity[$cityModel->id] = [];
                    }

                    // Initialize UC list for the city if not already set
                    if (!isset($city_namePerCity[$cityModel->id])) {
                        $city_namePerCity[$cityModel->id] = [];
                    }

                    // Initialize card ID list for the city if not already set
                    if (!isset($user_card_id_per_city[$cityModel->id])) {
                        $user_card_id_per_city[$cityModel->id] = [];
                    }
                }

                $all_lines = [];

                // Iterate over each unique city to fetch line information
                foreach ($cities as $city_key) {
                    $profile = InternalUserProfilesModel::where('user_id', Auth::user()->getAuthIdentifier())->where('city_id', $city_key->id)->first();


                    // Use the dynamic connection to query the database
                    if ($profile) {
                        $user_card_id = $profile->card_id;

                        // Store the card_id under the respective city ID
                        $user_card_id_per_city[$city_key->id][] = $user_card_id;

                        // Retrieve configuration for the user card
                        $uc = $profile->uc;
                        if ($uc) {
                            $ucValue = $uc;
                            // Add UC value to the list for the city
                            $ucPerCity[$city_key->id][] = $ucValue;
                            $city_namePerCity[$city_key->id][] = $city_key->name;

                            // Fetch lines associated with the user card
                            $lines = LinesModel::where('uc', $uc)->get();

                            // Process and format the lines
                            $lines = $lines->map(function ($line) {
                                $line->Idnumber = (int)$line->Idnumber;
                                $line->Code = (int)$line->Code;
                                $line->Price = (int)$line->Price;
                                return $line;
                            });

                            // Add additional information to each line
                            $lines = $lines->map(function ($line) use ($ucValue, $city_key) {
                                $line->uc = $ucValue; // Add uc value to each line
                                $line->city_id = $city_key->id; // Add city ID to each line
                                return $line;
                            });

                            // Merge lines into the all_lines array
                            $all_lines = array_merge($all_lines, $lines->toArray());
                        }
                    } else {
                        return response()->json(['status'=>0, 'message'=>'اطلاعات کاربر در سرور یافت نشد']);
                    }
                }

                if (empty($user_card_id_per_city)) {
                    // Error response if no card IDs are found
                    return ResponseHelper::systemErrorResponse(0, "User contact number not found in the system", [], 200, 890);
                }

                // Remove duplicate cities and provinces
                $uniqueCities = array_values(array_unique($cities_wihtoutHost, SORT_REGULAR));
                $uniqueProvinces = array_values(array_unique($provinces, SORT_REGULAR));

                // Prepare the card_id and UC information for each city
                $cardIdPerCity = [];
                foreach ($user_card_id_per_city as $cityId => $cardIds) {
                    $cardIdPerCity[$cityId] = implode(',', array_unique($cardIds));
                }

                $ucPerCityString = [];
                foreach ($ucPerCity as $cityId => $ucs) {
                    $ucPerCityString[$cityId] = implode(',', array_unique($ucs));
                }

                $cityName = [];
                foreach ($city_namePerCity as $cityId => $item) {
                    $cityName[$cityId] = implode(',', array_unique($item));
                }

                // Update each wallet with the corresponding UC and card_id
                foreach ($wallet as $walletEntry) {
                    $cityId = $walletEntry->city_id;
                    $walletEntry->uc = (int)$ucPerCityString[$cityId] ?? null;
                    $walletEntry->card_id = $cardIdPerCity[$cityId] ?? null; // Add card_id to each wallet entry
                    $walletEntry->city = $cityName[$cityId] ?? null; // Add card_id to each wallet entry
                }
                // Return successful response with wallet details
                return response()->json([
                    'status' => 1,
                    'message' => 'Wallet QR codes have been successfully created and you have a wallet.',
                    'data' => (object)[
                        'wallet' => $wallet, // Now includes card_id
                        'lines' => $all_lines,
                        'city' => $uniqueCities,
                        'province' => $uniqueProvinces
                    ]
                ]);

            } else {
                // Response if the user does not have a wallet
                return response()->json(['status' => 0, 'message' => 'You do not have a wallet, please create one.']);
            }
        } else {
            // Log an error and return an authentication error response
            ErrorLogsModel::insert([
                'type' => 1,
                'description' => "Get User Wallet | API key authentication unsuccessful!",
                'ip_address' => $request->ip()
            ]);
            return response()->json(['status' => 0, 'message' => "Service authentication error", 'code' => 500], 200);
        }
    }


    // Delete a program
    public function delete(Request $request)
    {
        if (!isset($request->id)) {
            return response()->json(['status' => 0, 'message' => 'شناسه الزامیست'], 400);
        }

        $wallet = WalletModel::where('id', $request->id)->first();
        if ($wallet) {
            $wallet->delete();
            return response()->json(['status' => 1, 'message' => 'کیف پول با موفقیت حذف شد'], 200);
        } else {
            return response()->json(['status' => 0, 'message' => 'کیف پول یافت نشد'], 404);
        }

    }

    public function deleteAll()
    {
        $wallet = WalletModel::where('user_id', Auth::user()->id)->delete();
        if ($wallet) {
            return response()->json(['status' => 1, 'message' => 'تمام کیف پول ها با موفقیت حذف شدند']);
        } else {
            return response()->json(['status' => 0, 'message' => 'خطا در حذف کیف پول ها']);
        }
    }


}
