<?php

namespace App\Http\Controllers\Api\v2;

use App\Components\Functions;
use App\Components\MomoServices;
use App\Components\ZaloPayServices;
use App\Jobs\ProcessMomoConfirmPayAppRequest;
use App\Models\CollectSpend;
use App\Models\Coupon;
use App\Models\MoneyInfo;
use App\Models\Notification;
use App\Models\Order;
use App\Models\Package;
use App\Models\RenterRoom;
use App\Models\Transaction;
use App\Models\UserPackage;
use App\User;
use Carbon\Carbon;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use Ramsey\Uuid\Uuid;

class PaymentController extends BaseController
{
    //
    /**
     * @api {post} v2/payment/momo/create-order-request Tạo đơn hàng
     * @apiName create-order-request
     * @apiGroup payment
     * @apiDescription Tạo đơn hàng momo
     *
     * @apiParam {String} partner_ref_id
     * @apiParam {String} partner_trans_id
     * @apiParam {String} token
     * @apiParam {String} coupon_code
     * @apiParam {String} package_id
     * @apiParam {String} month số tháng
     * @apiParam {String} rooms số phòng
     *
     * @apiSuccess {Number} status 1 hoặc 0. 1 là thành công, 0 là không thành công.
     * @apiSuccess {String} message  Tin nhắn hệ thống.
     * @apiSuccess {String} data
     */
    public function createOrderRequest(Request $request)
    {
        $coupon = $request->input('coupon_code');
        $packageId = $request->input('package_id');
        $month = $request->input('month', 1);
        $paymentType = 2; // 2 là momo
        $room = $request->input('rooms');
        $customerNumber = $request->input('customer_number');

        $package = Package::find($packageId);

        if (!$package) {
            return response([
                'status' => 0,
                'message' => 'Dữ liệu không hợp lệ'
            ]);
        }

        $currentPackage = UserPackage::where('user_id', $this->user->id)->first();
        if ($currentPackage) {
            if (!empty($packageId)) {

                if ($currentPackage->package_id > $packageId) {

                    return response([
                        'status' => 0,
                        'message' => 'Bạn không thể chọn gói thấp hơn gói sử dụng hiện tại'
                    ]);
                }
            }

        }

        $price = $package->price_per_month;
        $sum = $price * $month;

        $roomMore = $room - $package->number_rooms;
        $extra = ($roomMore / 10) * $package->price_10_rooms * $month;

        if ($extra > 0) {
            $sum += $extra;
        }


        $newSum = $sum;
        $couponItem = null;
        $discount = 0;
        $extraMonth = 0;

        if (!empty($coupon)) {

            $check = \DB::table('coupon_generates')->where('code', $coupon)->first();

            if (!$check) {
                return [
                    'status' => 0,
                    'message' => 'Coupon không tồn tại'
                ];
            }

            if ($check->is_active == 0) {
                return [
                    'status' => 0,
                    'message' => 'Coupon chưa được kích hoạt'
                ];
            }

            $couponId = $check->coupon_id;
            $couponItem = Coupon::find($couponId);
            if (!$couponItem) {
                return [
                    'status' => 0,
                    'message' => 'Không tìm thấy mã khuyến mại'
                ];
            }

            if (!empty($couponItem->from_date_expire)) {
                if ($couponItem->from_date_expire->greaterThan(Carbon::now())) {
                    return [
                        'status' => 0,
                        'message' => 'Coupon chưa thể sử dụng'
                    ];
                }
            }

            if (!empty($couponItem->end_date_expire)) {
                if ($couponItem->end_date_expire->lessThan(Carbon::now())) {
                    return [
                        'status' => 0,
                        'message' => 'Coupon đã quá hạn sử dụng'
                    ];
                }
            }

            $extraMonth = $couponItem->number_month_more;
            $discount = 0;

            if ($couponItem->type != 0) {
                if ($couponItem->type == 1) {
                    $discountPercent = $couponItem->percent_reduce;
                    $discount = $discountPercent * $sum / 100;
                    if ($discount > $couponItem->percent_reduce_max) {
                        if (!empty($couponItem->percent_reduce_max)) {
                            $discount = $couponItem->percent_reduce_max;
                        }
                    }
                } else if ($couponItem->type == 2) {
                    $discount = $couponItem->amount_reduce;
                }
            }

            $newSum = $sum - $discount;

            if ($newSum < 0) {
                $newSum = 0;
            }
        }

        $params = $request->only([
            'partner_ref_id',
            'partner_trans_id',
            'token'
        ]);
        $params['amount'] = $newSum;
        $params['customer_number'] = $customerNumber;
        $momoClient = new MomoServices();
        $holdMoney = $momoClient->createAppPayRequest($params);

        if (isset($holdMoney['status'])) {
            if ($holdMoney['status'] == 0) {
                $order = Order::create([
                    'value' => $holdMoney['amount'],
                    'package_id' => $packageId,
                    'user_id' => $this->user->id,
                    'name' => $this->user->name_text,
                    'phone' => $this->user->phone,
                    'status' => Order::PROCESSING,
                    'discount' => $discount,
                    'coupon_id' => !empty($couponItem) ? $couponItem->id : null,
                    'coupon_code' => $coupon,
                    'extra_month' => $extraMonth,
                    'month' => $month,
                    'rooms' => $room,
                    'payment_type' => $paymentType,

                    'wallet_trans_id' => $holdMoney['transid'],
                    'request_log' => $params,
                    'response_log' => $holdMoney,
                ]);
                $holdMoney['status'] = 1;
                $processOrder = $this->confirmMomo($order, $customerNumber);
                if ($processOrder['status']) {
                    return response([
                        'status' => 1,
                        'message' => 'Thanh toán thành công',
                        'data' => $processOrder['data']
                    ]);
                }

                return response([
                    'status' => 0,
                    'message' => 'Thanh toán thất bại'
                ]);
            }
        }

        return response($holdMoney);
    }

    /**
     * @api {post} v2/payment/momo/create-money-info-request Tạo thanh toán hóa đơn
     * @apiName create-money-info-request
     * @apiGroup payment
     * @apiDescription Tạo thanh toán hóa đơn momo
     *
     * @apiParam {String} partner_ref_id
     * @apiParam {String} partner_trans_id
     * @apiParam {String} token
     * @apiParam {String} money_info_id id hóa đơn
     * @apiParam {String} amount số tiền
     *
     * @apiSuccess {Number} status 1 hoặc 0. 1 là thành công, 0 là không thành công.
     * @apiSuccess {String} message  Tin nhắn hệ thống.
     * @apiSuccess {String} data
     */
    public function createMoneyInfoOrderRequest(Request $request)
    {
//        $transaction = Transaction::find(175474);
//        dd($this->confirmMomoTransaction($transaction, '1'));
        $moneyInfoId = $request->input('money_info_id');
        $amount = $request->input('amount');
        $customerNumber = $request->input('customer_number');
        $params = $request->only([
            'partner_ref_id',
            'partner_trans_id',
            'token'
        ]);
        $moneyInfo = MoneyInfo::find($moneyInfoId);
        if (!$moneyInfo) {
            return response([
                'status' => 0,
                'message' => 'Hóa đơn không tồn tại'
            ]);
        }

        if ($amount > $moneyInfo->remain) {
            return response([
                'status' => 0,
                'message' => 'Không được thanh toán vượt quá số tiền còn lại'
            ]);
        }
        $params['amount'] = $amount;
        $params['customer_number'] = $customerNumber;
        $params['description'] = 'Thanh toán hóa đơn thuê nhà';
        $momoClient = new MomoServices();
        $holdMoney = $momoClient->createAppPayRequest($params);
        if (isset($holdMoney['status'])) {
            if ($holdMoney['status'] == 0) {
                $transaction = Transaction::create([
                    'amount' => $holdMoney['amount'],
                    'user_id' => $this->user->id,
                    'hostel_id' => $moneyInfo->hostel_id,
                    'room_id' => $moneyInfo->room_id,
                    'wallet_trans_id' => $holdMoney['transid'],
                    'request_log' => $params,
                    'response_log' => $holdMoney,
                    'money_info_id' => $moneyInfoId,
                    'type' => CollectSpend::COLLECT
                ]);
                $holdMoney['status'] = 1;
                $processOrder = $this->confirmMomoTransaction($transaction, $customerNumber);

                if ($processOrder['status']) {

                    $renters = RenterRoom::where('room_id', $moneyInfo->room_id)->get();
                    $currentMoneyInfo = MoneyInfo::find($moneyInfo->id);
                    $remain = $currentMoneyInfo->remain;
                    $notiDate = $moneyInfo->date_action->format('m/Y');
                    $type = 'phòng';
                    if ($moneyInfo->type == MoneyInfo::VOUCHER_SERVICE) {
                        $type = 'dịch vụ';
                    }
                    $payload = json_encode([
                        'id' => $moneyInfo->id,
                        'type' => config('constants.TRANSACTION')
                    ]);
                    foreach ($renters as $renter) {
                        if ($remain > 0) {
                            Notification::create([
                                'image' => $this->user->image,
                                'to_user' => $renter->user_id,
                                'hostel_id' => $moneyInfo->hostel_id,
                                'room_id' => $moneyInfo->room_id,
                                'title' => 'Thông báo từ itro.vn',
                                'payload' => $payload,
                                'user_id' => $this->user->id,
                                'content' => 'Đã đóng ' . number_format($amount, 0, '.', '.') . ' đ tiền ' . $type . ' tháng ' . $notiDate . '. Số tiền còn lại phải đóng là ' . number_format($remain, 0, '.', '.') . 'đ',
                            ]);
                        } else {
                            Notification::create([
                                'image' => $this->user->image,
                                'to_user' => $renter->user_id,
                                'hostel_id' => $moneyInfo->hostel_id,
                                'room_id' => $moneyInfo->room_id,
                                'title' => 'Thông báo từ itro.vn',
                                'payload' => $payload,
                                'user_id' => $this->user->id,
                                'content' => 'Đã đóng đủ tiền ' . $type . ' tháng ' . $notiDate . '. Số tiền ' . number_format($currentMoneyInfo->pay, 0, '.', '.') . 'đ'
                            ]);
                        }
                    }
                    return response([
                        'status' => 1,
                        'message' => 'Thanh toán thành công',
                        'data' => $processOrder['data']
                    ]);
                }

                return response([
                    'status' => 0,
                    'message' => 'Thanh toán thất bại'
                ]);
            }
        }

        return response($holdMoney);

    }

    /**
     * @api {post} v2/payment/momo/create-money-infos-request Tạo thanh toán nhiều hóa đơn
     * @apiName create-money-infos-request
     * @apiGroup payment
     * @apiDescription Tạo thanh toán nhiều hóa đơn momo
     *
     * @apiParam {String} partner_ref_id
     * @apiParam {String} partner_trans_id
     * @apiParam {String} token
     * @apiParam {String} money_info_ids id các hóa đơn
     *
     * @apiSuccess {Number} status 1 hoặc 0. 1 là thành công, 0 là không thành công.
     * @apiSuccess {String} message  Tin nhắn hệ thống.
     * @apiSuccess {String} data
     */
    public function createMoneyInfosOrderRequest(Request $request)
    {
        $moneyInfoIds = $request->input('money_info_ids');
        $customerNumber = $request->input('customer_number');
        $amount = 0;
        foreach ($moneyInfoIds as $moneyInfoId) {
            $moneyInfo = MoneyInfo::find($moneyInfoId);
            if (!$moneyInfo) {
                return response([
                    'status' => 0,
                    'message' => 'Mã hóa đơn ' . $moneyInfoId . ' không tồn tại'
                ]);
            }
            $amount += $moneyInfo->remain;
        }

        if (empty($amount)) {
            return response([
                'status' => 0,
                'message' => 'Số tiền phải lớn hơn 0'
            ]);
        }
        $params = $request->only([
            'partner_ref_id',
            'partner_trans_id',
            'token'
        ]);
        $params['amount'] = $amount;
        $params['customer_number'] = $customerNumber;
        $params['description'] = 'Thanh toán hóa đơn thuê nhà';

        $momoClient = new MomoServices();
        $holdMoney = $momoClient->createAppPayRequest($params);
        if (isset($holdMoney['status'])) {
            $transactions = [];
            if ($holdMoney['status'] == 0) {

                foreach ($moneyInfoIds as $moneyInfoId) {
                    $moneyInfo = MoneyInfo::find($moneyInfoId);
                    $transaction = Transaction::create([
                        'amount' => $moneyInfo->remain,
                        'user_id' => $this->user->id,
                        'hostel_id' => $moneyInfo->hostel_id,
                        'room_id' => $moneyInfo->room_id,
                        'wallet_trans_id' => $holdMoney['transid'],
                        'request_log' => $params,
                        'response_log' => $holdMoney,
                        'money_info_id' => $moneyInfoId,
                        'type' => CollectSpend::COLLECT
                    ]);

                    $transactions[] = $transaction;

                }

                $holdMoney['status'] = 1;
                $processOrder = $this->confirmMomoTransactions($transactions, $customerNumber);

                if ($processOrder['status']) {
                    foreach ($moneyInfoIds as $moneyInfoId)
                    {
                        $renters = RenterRoom::where('room_id', $moneyInfo->room_id)->get();
                        $currentMoneyInfo = MoneyInfo::find($moneyInfoId);
                        $notiDate = $moneyInfo->date_action->format('m/Y');
                        $type = 'phòng';
                        if ($moneyInfo->type == MoneyInfo::VOUCHER_SERVICE) {
                            $type = 'dịch vụ';
                        }
                        $payload = json_encode([
                            'id' => $moneyInfo->id,
                            'type' => config('constants.TRANSACTION')
                        ]);
                        foreach ($renters as $renter) {
                            Notification::create([
                                'image' => $this->user->image,
                                'to_user' => $renter->user_id,
                                'hostel_id' => $currentMoneyInfo->hostel_id,
                                'room_id' => $currentMoneyInfo->room_id,
                                'title' => 'Thông báo từ itro.vn',
                                'payload' => $payload,
                                'user_id' => $this->user->id,
                                'content' => 'Đã đóng đủ tiền ' . $type . ' tháng ' . $notiDate . '. Số tiền ' . number_format($currentMoneyInfo->pay, 0, '.', '.') . 'đ'
                            ]);
                        }
                    }
                    return response([
                        'status' => 1,
                        'message' => 'Thanh toán thành công',
                        'data' => $processOrder['data']
                    ]);
                }
            }


            return response([
                'status' => 0,
                'message' => 'Thanh toán thất bại'
            ]);
        }

        return response([
            'status' => 0
        ]);

    }

    public function confirmMomoTransactions($transactions, $customerNumber)
    {
        $momoService = new MomoServices();
        try {
            \DB::beginTransaction();
            foreach ($transactions as $transaction) {
                $momoConfirmParam = [
                    'partner_ref_id' => strval($transaction->id),
                    'momo_trans_id' => strval($transaction->wallet_trans_id)
                ];


                $moneyInfo = $transaction->moneyInfo;
                CollectSpend::create([
                    'amount' => $transaction->amount,
                    'hostel_id' => $moneyInfo->hostel_id,
                    'room_id' => $moneyInfo->room_id,
                    'payment_method' => CollectSpend::BANK,
                    'date_action' => Carbon::now(),
                    'type' => CollectSpend::COLLECT,
                    'name' => $this->user->name,
                    'transaction_id' => $transaction->id,
                    'money_info_id' => $moneyInfo->id,
                    'contract_id' => $moneyInfo->contract_id
                ]);
                $remain = $moneyInfo->remain - $transaction->amount;
                $moneyInfo->pay = $moneyInfo->pay + $transaction->amount;
                $moneyInfo->remain = $remain;
                $moneyInfo->save();
                \DB::commit();
            }
            $success = true;
            $momoConfirmParam['request_type'] = 'capture';

        } catch (\Exception $exception) {
            \DB::rollBack();
            $success = false;
            $momoConfirmParam['request_type'] = 'revertAuthorize';
            $momoConfirmParam['description'] = 'Hoàn lại vì lỗi exception trong quá trình thanh toán';
        }


        $response = $momoService->confirmPayApp($momoConfirmParam);
        return [
            'status' => $success,
            'data' => $response
        ];
    }

    public function confirmMomo(Order $order, $customerNumber)
    {
        $momoConfirmParam = [
            'partner_ref_id' => strval($order->id),
            'momo_trans_id' => strval($order->wallet_trans_id)
        ];

        $momoService = new MomoServices();

        try {
            \DB::beginTransaction();
            if (empty($order->number_view_leads)) {
                $packageId = $order->package_id;
                $extraMonth = $order->month;

                $currentPackage = UserPackage::where('user_id', $order->user_id)->first();
                if ($currentPackage) {
                    if (!empty($packageId)) {

                        if ($currentPackage->package_id < $packageId) {
                            $currentPackage->package_id = $packageId;
                        }
                    }

                    $currentPackage->end_date = $currentPackage->end_date->addMonth($extraMonth);
                    $currentPackage->number_rooms = $order->rooms;
                    $currentPackage->save();
                }

                Functions::redeemCoupon($order->coupon_code, $order->user_id, $isOrder = true);
            } else {
                User::query()->where('id', $order->user_id)
                    ->increment('number_view_leads', $order->number_view_leads);
            }
            $order->status = Order::PROCESSED;
            $order->save();

            \DB::commit();
            $success = true;
            $momoConfirmParam['request_type'] = 'capture';

        } catch (\Exception $exception) {
            \DB::rollBack();
            $success = false;
            $momoConfirmParam['request_type'] = 'revertAuthorize';
            $momoConfirmParam['description'] = 'Hoàn lại vì lỗi exception trong quá trình thanh toán';
        }

        $response = $momoService->confirmPayApp($momoConfirmParam);
        return [
            'status' => $success,
            'data' => $response
        ];
    }

    public function confirmMomoTransaction(Transaction $transaction, $customerNumber)
    {
        $momoConfirmParam = [
            'partner_ref_id' => strval($transaction->id),
            'momo_trans_id' => strval($transaction->wallet_trans_id)
        ];

        $momoService = new MomoServices();

        try {
            \DB::beginTransaction();

            $moneyInfo = $transaction->moneyInfo;
            CollectSpend::create([
                'amount' => $transaction->amount,
                'hostel_id' => $moneyInfo->hostel_id,
                'room_id' => $moneyInfo->room_id,
                'payment_method' => CollectSpend::BANK,
                'date_action' => Carbon::now(),
                'type' => CollectSpend::COLLECT,
                'name' => $this->user->name,
                'transaction_id' => $transaction->id,
                'money_info_id' => $moneyInfo->id,
                'contract_id' => $moneyInfo->contract_id
            ]);
            $remain = $moneyInfo->remain - $transaction->amount;
            $moneyInfo->pay = $moneyInfo->pay + $transaction->amount;
            $moneyInfo->remain = $remain;
            $moneyInfo->save();
            \DB::commit();
            $success = true;
            $momoConfirmParam['request_type'] = 'capture';

        } catch (\Exception $exception) {
            \DB::rollBack();
            $success = false;
            $momoConfirmParam['request_type'] = 'revertAuthorize';
            $momoConfirmParam['description'] = 'Hoàn lại vì lỗi exception trong quá trình thanh toán';
        }


        $response = $momoService->confirmPayApp($momoConfirmParam);
        return [
            'status' => $success,
            'data' => $response
        ];
    }

    /**
     * @api {post} v2/payment/momo/create-app-pay-request Tạo yêu cầu thanh toán momo
     * @apiName /create-app-pay-request
     * @apiGroup payment
     * @apiParam {String} partner_ref_id
     * @apiParam {String} partner_trans_id
     * @apiParam {String} token
     * @apiParam {Number} amount
     * @apiParam {String} customer_number
     *
     *
     * @apiDescription Api Tạo yêu cầu thanh toán momo
     * @apiSuccess {Number} status 1 hoặc 0. 1 là thành công, 0 là không thành công.
     * @apiSuccess {String} message  Tin nhắn hệ thống.
     * @apiSuccess {String} data
     */
    public function createAppPayRequest(Request $request)
    {
        $momoClient = new MomoServices();
        $params = $request->all();

        $holdMoney = $momoClient->createAppPayRequest($params);
        if (isset($holdMoney['status'])) {
            if ($holdMoney['status'] == 0) {
                \App\Models_v2\Transaction::create([
                    'order_id' => $request->input('partner_ref_id'),
                    'user_id' => $this->user->id,
                    'wallet_trans_id' => $holdMoney['transid'],
                    'request_log' => $request->all(),
                    'response_log' => $holdMoney,
                    'type' => \App\Models_v2\Transaction::CHARGE,
                    'charge_from' => 'momo',
                    'amount' => $holdMoney['amount'] / config('constants.COIN_VND'),
                    'status' => \App\Models_v2\Transaction::STATUS_NOT_PROCESS
                ]);
                $holdMoney['status'] = 1;
            }
        }

        return response($holdMoney);
    }

    /**
     * @api {post} v2/payment/zalopay/create-order Tạo đơn hàng zalopay
     * @apiName /create-order
     * @apiGroup payment
     * @apiParam {String} amount
     *
     *
     * @apiDescription Api Tạo yêu cầu thanh toán momo
     * @apiSuccess {Number} status 1 hoặc 0. 1 là thành công, 0 là không thành công.
     * @apiSuccess {String} message  Tin nhắn hệ thống.
     * @apiSuccess {String} data
     */
    public function createZaloOrder(Request $request)
    {
        $zalopayClient = new ZaloPayServices();
        $params = $request->all();
        $params['app_user'] = $this->user->id;
        $orderResponse = $zalopayClient->createOrder($params);
        $status = 0;
        if (isset($orderResponse['returncode'])) {
            if ($orderResponse['returncode'] == 1) {
                $status = 1;
            }
        }

        return response([
            'status' => $status,
            'data' => $orderResponse
        ]);
    }

    public function confirmMomoAppPayRequest(Request $request)
    {
        $requestArr = $request->json()->all();
        \Log::info(json_encode($request->json()->all()));
        $status = $requestArr['status'];
        $momoTransId = $requestArr['momoTransId'];
        $amount = $requestArr['amount'];
        $message = $requestArr['message'];
        $partnerRefId = $requestArr['partnerRefId'];
        $hashString = "amount=$amount&message=$message&momoTransId=$momoTransId&partnerRefId=$partnerRefId&status=$status";
        $hash = hash_hmac('sha256', $hashString, null);

        dispatch_now(new ProcessMomoConfirmPayAppRequest([
            'partner_ref_id' => $partnerRefId,
            'momo_trans_id' => $momoTransId,
        ]));


        return response([
            "status" => $status,
            "message" => $message,
            "amount" => $amount,
            "partnerRefId" => $partnerRefId,
            "momoTransId" => $momoTransId,
            "signature" => $hash
        ]);
    }

}
