<?php

namespace App\Http\Controllers\User\Order;

use Exception;
use App\Models\User;
use Illuminate\Support\Facades\RateLimiter;
use App\Models\Order;
use App\Models\Service;
use Illuminate\Http\Request;
use App\Models\UserBalanceLog;
use App\Models\ServiceProvider;
use App\Models\ServiceCustomPrice;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Auth;
use App\Models\ServiceFavorite;
use App\Models\ServiceLog;
use GuzzleHttp\Client;
use Illuminate\Support\Facades\Validator;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Http\Exceptions\HttpResponseException;
use Illuminate\Support\Facades\Http;
use Jenssegers\Agent\Agent;
use Stevebauman\Location\Facades\Location;

class SingleController extends Controller {
	public function __construct(Request $request) {
        $this->user_agent = new Agent();
        $this->location = Location::get($request->ip());
	}
    public function get() {
        $components['categories'] = Service::distinct()->join('service_categories', 'services.category_id', '=', 'service_categories.id')->where('service_categories.status', '1')->oldest('category_name')->get(['category_id', 'service_categories.name AS category_name']);
        $components['categories_favorite'] = ServiceFavorite::where('user_id', Auth::id())->join('services', 'service_favorites.service_id', '=', 'services.id')->join('service_categories', 'services.category_id', '=', 'service_categories.id')->where('service_categories.status', '1')->oldest('category_name')->get(['category_id', 'service_categories.name AS category_name'])->unique('category_id');
        $components['breadcrumb'] = (object) [
            'first' => 'Pesan Baru',
            'second' => 'Pesanan'
        ];
        return view('user.order.single', $components);
    }
    public function post(PostRequest $request) {
        if ($request->ajax() == false) return abort('404');
        $check_user = $user = User::find(Auth::id());
        $input_data = [
            'user_id'             => $user->id,
            'service_id'          => escape_input($request->service),
            'target'              => escape_input($request->target),
            'quantity'            => fixed_amount($request->quantity),
            'price'               => 0,
            'profit'              => 0,
            'provider_id'         => 0,
            'provider_order_id'   => 0,
            'status'              => 'Pending',
            'ip_address'          => $request->ip(),
            'custom_comments'     => ($request->custom_comments <> '') ? escape_input(strip_tags($request->custom_comments)) : null,
            'username'            => ($request->username <> '') ? escape_input($request->username) : null,
            'provider_order_log'  => null,
            'provider_status_log' => null,
        ];
        $check_service = $service = Service::where('id', $input_data['service_id'])->where('status', '1')->first();
        if ($check_service == false) {
            return response()->json([
                'status'  => false, 
                'type'    => 'alert',
                'message' => 'Layanan tidak tersedia.'
            ]);
        }
        if ($service->type == 'Custom Comments') {
            $data_input['quantity'] = count(explode('\r\n', $input_data['custom_comments']));
            $validator = Validator::make($request->all(), [
                'custom_comments' => 'required',
            ], [], ['custom_comments' => 'Kustom Komentar']);
            if ($validator->fails()) {
                return response()->json([
                    'status'  => false, 
                    'type'    => 'validation',
                    'message' => $validator->errors()->toArray()
                ]);
            }
        }
        if ($service->type == 'Comment Likes') {
            $validator = Validator::make($request->all(), [
                'username' => 'required',
            ], [], ['username' => 'Username']);
            if ($validator->fails()) {
                return response()->json([
                    'status'  => false, 
                    'type'    => 'validation',
                    'message' => $validator->errors()->toArray()
                ]);
            }
        }
        $input_data['service_name'] = $service->name;
        $input_data['price'] = $service->price/1000 * $input_data['quantity'];
        $input_data['profit'] = $service->profit/1000 * $input_data['quantity'];
        $custom_price = ServiceCustomPrice::where([
            ['user_id', Auth::user()->id],
            ['service_id', $input_data['service_id']]
        ])->first();
        if ($custom_price == true AND $custom_price->price < $service->price) {
            $input_data['price'] = $input_data['quantity'] * ($custom_price->price / 1000);
            $input_data['profit'] = $input_data['quantity'] * ($custom_price->profit / 1000);
        }
        $check_provider = $provider = ServiceProvider::where([
            ['id', $service->provider_id],
            ['status', '1']
        ])->first();
        if ($check_provider == false) {
            return response()->json([
                'status'  => false, 
                'type'    => 'alert',
                'message' => 'Layanan tidak tersedia.'
            ]);
        } elseif ($input_data['quantity'] < $service->min) {
            return response()->json([
                'status'  => false, 
                'type'    => 'alert',
                'message' => 'Jumlah minimal adalah '.number_format($service->min,0,',','.').'.'
            ]);
        } elseif ($input_data['quantity'] > $service->max) {
            return response()->json([
                'status'  => false, 
                'type'    => 'alert',
                'message' => 'Jumlah maksimal adalah '.number_format($service->max,0,',','.').'.'
            ]);
        } elseif ($user->balance < $input_data['price']) {
            return response()->json([
                'status'  => false, 
                'type'    => 'alert',
                'message' => 'Saldo anda tidak mencukupi.'
            ]);
        } else {
            $input_data['provider_id'] = $service->provider_id;
            $order_response = false;
            if ($provider->name == 'MANUAL') {
                $order_response = true;
                $input_data['provider_id'] = $provider->id;
            } else {
                $provider_config = json_decode($provider->order_config, true);
                $parameter_values = [
                    'service'         => $service->provider_service_id,
                    'target'          => $input_data['target'],
                    'quantity'        => $input_data['quantity'],
                    'provider_id'     => $provider->provider_id,
                    'provider_key'    => $provider->provider_key,
                    'provider_secret' => $provider->provider_secret,
                    'custom_comments' => $input_data['custom_comments'],
                ];
                foreach ($provider_config['request'] as $key => $value) {
                    if ($key == 'action') {
                        $post_api['action'] = $value;
                    } else {
                        $post_api[$value] = $parameter_values[$key]; 
                    }
                }
                $post_api['username'] = $input_data['username'];
                try {
                    $curl = Http::withoutVerifying()->asForm()->post($provider_config['endpoint'], $post_api);
                    if ($curl->ok() == true) {
                        $curl_response = $curl->json();
                        $provider_order_id = '$curl_response'.$provider_config['response']['order_id'].'';
                        eval('$provider_order_id = '.$provider_order_id.';');
                        // $provider_order_id = deltonsz($curl_response, to_array(json_decode($provider_config['response']['order_id'])));
                        if (isset($provider_order_id)) {
                            $order_response = true;
                            $input_data['provider_order_id'] = $provider_order_id;
                            $input_data['provider_order_log'] = $curl;
                        }
                    } else {
                        return response()->json([
                            'status'  => false, 
                            'type'    => 'alert',
                            'message' => 'Layanan tidak tersedia.'
                        ]);
                    }
                } catch (Exception $error) {
                    return response()->json([
                        'status'  => false, 
                        'type'    => 'alert',
                        'message' => 'Layanan tidak tersedia.'
                    ]);
                }
            }
            if ($order_response == false) {
                if (isset($curl)) {
                    if (ServiceLog::where([
                        ['service_id', $service->id],
                        ['logs', $curl]
                    ])->count() == 0) {
                        $insert_log = ServiceLog::create([
                            'user_id'     => $user->id,
                            'service_id'  => $service->id,
                            'provider_id' => $service->provider_id,
                            'logs'        => $curl
                        ]);
                    }
                    $service->update([
                        'status' => '0'
                    ]);
                }
                return response()->json([
                    'status'  => false, 
                    'type'    => 'alert',
                    'message' => 'Layanan tidak tersedia.'
                ]);
            } else {
                if ($this->location) {
                    $input_data['location'] = $this->location->countryName.' - '.$this->location->regionName.' - '.$this->location->cityName.' ('.$this->user_agent->device().' - '.$this->user_agent->platform().'/'.$this->user_agent->version($this->user_agent->platform()).' - '.$this->user_agent->browser().'/'.$this->user_agent->version($this->user_agent->browser()).')';
                } else {
                    $input_data['location'] = '('.$this->user_agent->device().' - '.$this->user_agent->platform().'/'.$this->user_agent->version($this->user_agent->platform()).' - '.$this->user_agent->browser().'/'.$this->user_agent->version($this->user_agent->browser()).')';
                }
                $insert_data = Order::create($input_data);
                if ($insert_data == true) {
                    $first_balance = $user->balance;
                    $last_balance = $user->balance - $input_data['price'];
                    $cut_balance = $user->update([
                        'balance' => $last_balance,
                    ]);
                    $balance_log = UserBalanceLog::create([
                        'user_id'       => $input_data['user_id'],
                        'type'          => 'Minus',
                        'action'        => 'Order',
                        'amount'        => $input_data['price'],
                        'first_balance' => $first_balance,
                        'last_balance'  => $last_balance,
                        'description'   => 'Membuat Pesanan (Web - Tunggal) #'.$insert_data->id.'.',
                    ]);
                    if (json_decode($user->notification)->order == '1') {
                        $email_details = [
                            'content' => [
                                'id'         => $insert_data->id,
                                'service'    => $service->name,
                                'target'     => $input_data['target'],
                                'quantity'   => $input_data['quantity'],
                                'price'      => $input_data['price'],
                                'status'     => 'Pending',
                                'source'     => 'WEB',
                                'ip_address' => $request->ip(),
                            ],
                            'receiver' => [
                                'email' => $user->email,
                                'name'  => $user->full_name,
                            ]
                        ];
                        send_email($email_details, 'Informasi Pesanan - '.website_config('main')->website_name.'', 'user.mail.notification.order');
                    }
                    if (website_config('notification')->email <> '' AND website_config('notification')->order == '1') {
                        $email_details = [
                            'content' => [
                                'username'   => $user->username,
                                'full_name'  => $user->full_name,
                                'id'         => $insert_data->id,
                                'service'    => $service->name,
                                'target'     => $input_data['target'],
                                'quantity'   => $input_data['quantity'],
                                'price'      => $input_data['price'],
                                'status'     => 'Pending',
                                'source'     => 'WEB',
                                'ip_address' => $request->ip(),
                            ],
                            'receiver' => [
                                'email' => website_config('notification')->email,
                                'name'  => 'Admin',
                            ]
                        ];
                        send_email($email_details, 'Informasi Pesanan - '.website_config('main')->website_name.'', 'admin.mail.notification.order');
                    }
                    return response()->json([
                        'status'  => true, 
                        'last_balance' => number_format($check_user->balance,0,',','.'),
                        'message' => '
                            Pesanan anda akan segera diproses, berikut adalah data pesanan Anda.
                            <br /><b>ID Pesanan:</b> '.$insert_data->id.'
                            <br /><b>Layanan:</b> '.$check_service->name.'
                            <br /><b>Target:</b> '.$input_data['target'].'
                            <br /><b>Jumlah:</b> '.number_format($input_data['quantity'],0,',','.').'
                        '
                    ]);
                } else {
                    return response()->json([
                        'status'  => false, 
                        'type'    => 'alert',
                        'message' => 'Terjadi Kesalahan'
                    ]);
                }
            }
        }
    }
}


class PostRequest extends FormRequest {
	protected function prepareForValidation() {
		$this->merge([
			'quantity' => $this->quantity <> '' ? fixed_amount($this->quantity) : '',
		]);
	}
    protected function getValidatorInstance() {
        $instance = parent::getValidatorInstance();
        if ($instance->fails() == true) {
            throw new HttpResponseException(response()->json([
                'status'  => false, 
                'type'    => 'validation',
                'message' => parent::getValidatorInstance()->errors()
            ]));
        } else {
            if (RateLimiter::attempt('limit: '.Auth::user()->username, 1, function() {}, 30) == false) {
                $seconds = RateLimiter::availableIn('limit: '.Auth::user()->username);
                throw new HttpResponseException(response()->json([
                    'status'  => false, 
                    'type'    => 'alert',
                    'message' => 'Terlalu banyak permintaan.'
                ], 429)->header('retry-after', $seconds));
            }
            return parent::getValidatorInstance();
        }
        return parent::getValidatorInstance();
    }
    public function rules(Request $request) {
        return [
            'category'    => 'required|numeric|exists:service_categories,id',
            'service'     => 'required|numeric|exists:services,id',
            'target'      => 'required',
            'quantity'    => 'required|numeric|integer|min:0',
            'approval'    => 'required|in:1',
        ];
        
    }
    public function attributes() {
        return [
            'category'    => 'Kategori',
            'service'     => 'Layanan',
            'target'      => 'Target',
            'quantity'    => 'Jumlah',
            'approval'    => 'Persetujuan',
        ];
    }
}