<?php

namespace App\Http\Controllers\Member;

use App\Http\Controllers\Admin\MarzbanController;
use App\Models\VpsDetail;
use App\Models\Information;
use Illuminate\Http\Request;
use Illuminate\Support\Carbon;
use App\Http\Controllers\Controller;
use App\Models\VpsCategory;
use App\Models\VpsCountry;
use App\Models\VpsProxies;
use App\Models\VpsSubscription;
use Illuminate\Http\JsonResponse;
use Illuminate\Validation\Rule;
use Illuminate\Support\Str;

class MemberProductController extends Controller
{
    public function index(Request $request)
    {
        $user_id = auth()->user()->id;
        $information = Information::where(function ($query) {
            $query->where('expires_at', '>', Carbon::now('Asia/Jakarta'))
                ->orWhereNull('expires_at');
        })
            ->where('is_product', 1)
            ->get();
        $vps_category = VpsCategory::orderBy('seq', 'asc')->get();
        $vps_country = VpsCountry::orderBy('seq', 'asc')->get();
        $vps_proxies = VpsProxies::orderBy('seq', 'asc')->get();
        $vps_subscription = VpsSubscription::join('vps_details', 'vps_details.id', '=', 'vps_subscriptions.vps_details_id')
            ->join('vps', 'vps.id', '=', 'vps_details.vps_id')
            ->join('vps_countries', 'vps_countries.id', '=', 'vps.vps_country_id')
            ->join('vps_proxies', 'vps_proxies.id', '=', 'vps_details.vps_proxies_id')
            ->join('vps_categories', 'vps_categories.id', '=', 'vps_details.vps_category_id')
            ->join('users', 'users.id', '=', 'vps_subscriptions.user_id')
            ->select(
                'vps_subscriptions.*',
                'vps.name as vps_name',
                'vps_proxies.name as vps_proxies_name',
                'vps_details.vps_category_id',
                'vps_categories.name as vps_category_name',
                'users.email as email',
                'vps_details.max_session as vps_max_session',
                'vps_details.price_hour as vps_price_hour',
                'vps_countries.code as vps_country_code',
                'vps_countries.name as vps_country_name',
            )->get();
        $vps_subscription_group = [];
        foreach ($vps_subscription as $value) {
            $vps_subscription_group[$value->vps_category_id][] = $value;
        }

        return view('member.product', compact(
            'information',
            'vps_category',
            'vps_country',
            'vps_proxies',
            'vps_subscription',
            'vps_subscription_group'
        ));
    }

    public function list(Request $request)
    {
        $category = $request->category;
        $proxies = $request->proxies;
        $country = $request->country;
        $information = Information::where(function ($query) {
            $query->where('expires_at', '>', Carbon::now('Asia/Jakarta'))
                ->orWhereNull('expires_at');
        })
            ->where('is_product', 1)
            ->get();
        $vps_category = VpsCategory::orderBy('seq', 'asc')->get();
        $vps_country = VpsCountry::orderBy('seq', 'asc')->get();
        $vps_proxies = VpsProxies::orderBy('seq', 'asc')->get();
        $vps_detail = VpsDetail::join('vps', 'vps.id', '=', 'vps_details.vps_id')
            ->join('vps_categories', 'vps_categories.id', '=', 'vps_details.vps_category_id')
            ->join('vps_proxies', 'vps_proxies.id', '=', 'vps_details.vps_proxies_id')
            ->join('vps_countries', 'vps_countries.id', '=', 'vps.vps_country_id')
            ->whereNull('vps_details.deleted_at')
            ->whereRaw('LOWER(vps_categories.name) = LOWER(?)', [$category])
            ->whereRaw('LOWER(vps_proxies.name) = LOWER(?)', [$proxies])
            ->whereRaw('LOWER(vps_countries.code) = LOWER(?)', [$country])
            ->select(
                'vps_details.id',
                'vps_categories.name AS vps_category_name',
                'vps_proxies.name AS vps_proxies_name',
                'vps.name AS vps_name',
                'vps_countries.code AS vps_country_code',
                'vps_countries.name AS vps_country_name',
                'vps_details.price',
                'vps_details.price_hour',
                'vps_details.quota',
                'vps_details.quota_used',
                'vps.speed',
                'vps_details.max_session'
            )
            ->get();
        return view('member.product_list', compact(
            'information',
            'vps_category',
            'vps_country',
            'vps_proxies',
            'vps_detail'
        ));
    }

    public function show(Request $request): JsonResponse
    {
        $user_id = auth()->user()->id;
        $id = $request->id;
        if (empty($id)) {
            $code = 400;
            $message = 'Bad Request';
            return response()->json([
                'response' => null,
                'metadata' => [
                    'code' => $code,
                    'message' => $message
                ]
            ], $code);
        }
        $vps_subscription = VpsSubscription::join('vps_details', 'vps_details.id', '=', 'vps_subscriptions.vps_details_id')
            ->join('vps', 'vps.id', '=', 'vps_details.vps_id')
            ->join('vps_categories', 'vps_categories.id', '=', 'vps_details.vps_category_id')
            ->join('vps_proxies', 'vps_proxies.id', '=', 'vps_details.vps_proxies_id')
            ->join('vps_countries', 'vps_countries.id', '=', 'vps.vps_country_id')
            ->where('vps_subscriptions.id', '=', $id)
            ->where('vps_subscriptions.user_id', '=', $user_id)
            ->select(
                'vps_subscriptions.*',
                'vps_details.vps_id',
                'vps_categories.name AS vps_category_name',
                'vps_proxies.name AS vps_proxies_name',
                'vps.name AS vps_name',
                'vps.hostname AS vps_hostname',
                'vps_countries.code AS vps_country_code',
                'vps_countries.name AS vps_country_name',
                'vps_details.price',
                'vps_details.price_hour',
                'vps_details.quota',
                'vps_details.quota_used',
                'vps.speed',
                'vps_details.max_session'
            )
            ->first();
        $requestMarzban = new Request(['id' => $vps_subscription->vps_id, 'username' => $vps_subscription->username]);
        $marzbanController = new MarzbanController();
        $accounts = $marzbanController->usersGetByUsername($requestMarzban);
        $accounts = $accounts->getData();
        $vps_subscription->accounts = $accounts->response->links;
        $vps_subscription->used_traffic = $marzbanController->formatBytes($accounts->response->used_traffic);
        $code = 200;
        $message = 'OK';
        return response()->json([
            'response' => $vps_subscription,
            'metadata' => [
                'code' => $code,
                'message' => $message
            ]
        ], $code);
    }

    public function store(Request $request): JsonResponse
    {
        $request->validate([
            'create_account_id' => 'required',
            'create_account_username' => [
                'required',
                'min:4',
                'max:15',
                Rule::unique('vps_subscriptions', 'username'),
            ],
        ]);
        $vps_detail = VpsDetail::join('vps_proxies', 'vps_proxies.id', '=', 'vps_details.vps_proxies_id')
            ->where('vps_details.id', $request->create_account_id)
            ->select(
                'vps_details.*',
                'vps_proxies.name as vps_proxies_name'
            )
            ->first();
        $user_id = auth()->user()->id;
        $email = auth()->user()->email;
        $password = (string) Str::uuid();
        $expire = 0;
        $data_limit = Str::replace(',', '.', $vps_detail->data_limit);
        $data_limit = $data_limit > 0 ? ($data_limit * 1024 * 1024 * 1024) : 0;
        $marzbanController = new MarzbanController();
        $request_marzban  = new Request([
            'account_proxies' => Str::lower($vps_detail->vps_proxies_name),
            'id' => $vps_detail->vps_id,
            'username' => $request->create_account_username,
            'password' => $password,
            'expire' => $expire,
            'data_limit' => $data_limit,
            'data_limit_reset_strategy' => $vps_detail->data_limit_reset_strategy,
            'note' => $email,
        ]);
        $insert = $marzbanController->usersAdd($request_marzban)->getData();
        if ($insert->metadata->code != 200) {
            return response()->json([
                'errors' => $insert->response,
                'message' => $insert->response->detail,
            ], $insert->metadata->code);
        }
        $balance = $vps_server->price_hour ?? 20;
        $config = '';
        $pay_at = Carbon::now('Asia/Jakarta');
        VpsSubscription::create(
            [
                'user_id' => $user_id,
                'vps_details_id' => $request->create_account_id,
                'username' => $request->create_account_username,
                'password' => $password,
                'balance' => $balance,
                'config' => $config,
                'pay_at' => $pay_at,
            ]
        );
        $code = 200;
        $message = 'OK';
        return response()->json([
            'response' => null,
            'metadata' => [
                'code' => $code,
                'message' => $message
            ]
        ], $code);
    }

    public function uuid(Request $request): JsonResponse
    {
        $request->validate([
            'id' => 'required',
        ]);
        $user_id = auth()->user()->id;
        $vps_subscription = VpsSubscription::join('vps_details', 'vps_details.id', '=', 'vps_subscriptions.vps_details_id')
            ->join('vps_proxies', 'vps_proxies.id', '=', 'vps_details.vps_proxies_id')
            ->where('vps_subscriptions.id', '=', $request->id)
            ->where('vps_subscriptions.user_id', '=', $user_id)
            ->select('vps_subscriptions.*', 'vps_details.vps_id', 'vps_proxies.name as vps_proxies_name')
            ->first();
        $code = 404;
        $message = 'Not Found';
        $password = null;
        if ($vps_subscription) {
            $marzbanController = new MarzbanController();
            $request_marzban  = new Request([
                'id' => $vps_subscription->vps_id,
                'username' => $vps_subscription->username,
                'account_proxies' => Str::lower($vps_subscription->vps_proxies_name),
            ]);
            $res = $marzbanController->usersUUID($request_marzban);
            $res = $res->getData();
            $password = $res->response;
            $code = 200;
            $message = 'OK';
            $vps_subscription = VpsSubscription::find($vps_subscription->id);
            $vps_subscription->password = $password;
            $vps_subscription->save();
        }
        return response()->json([
            'response' => $password,
            'metadata' => [
                'code' => $code,
                'message' => $message
            ]
        ], $code);
    }

    public function destroy(Request $request): JsonResponse
    {
        $request->validate([
            'id' => 'required',
        ]);
        $user_id = auth()->user()->id;
        $vps_subscription = VpsSubscription::join('vps_details', 'vps_details.id', '=', 'vps_subscriptions.vps_details_id')
            ->where('vps_subscriptions.id', '=', $request->id)
            ->where('vps_subscriptions.user_id', '=', $user_id)
            ->select('vps_subscriptions.*', 'vps_details.vps_id')
            ->first();
        $code = 404;
        $message = 'Not Found';
        if ($vps_subscription) {
            VpsSubscription::find($vps_subscription->id)?->delete();
            $marzbanController = new MarzbanController();
            $request_marzban  = new Request([
                'id' => $vps_subscription->vps_id,
                'username' => $vps_subscription->username,
            ]);
            $marzbanController->usersDelete($request_marzban);
            $code = 200;
            $message = 'OK';
        }
        return response()->json([
            'metadata' => [
                'code' => $code,
                'message' => $message
            ]
        ], $code);
    }
}
