<?php

namespace App\Http\Controllers\Api\v1;

use App\Components\Functions;
use App\Models\CollectSpend;
use App\Models\Contract;
use App\Models\HostelFee;
use App\Models\MoneyDetail;
use App\Models\MoneyInfo;
use App\Models\PaymentOnlineTransaction;
use App\Models\RenterRoom;
use App\Models\Transaction;
use Carbon\Carbon;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Validator;

class PaymentOnlineController extends BaseController
{
    public function getUnpaidByPhone(Request $request) {
        $phone = $request->input('phone');

        $contract = Contract::where('phone', $phone)->where('status', Contract::VALIDATED)->first();
        $roomId = $contract->room_id;
        $contractId = $contract->id;
        $moneyInfos = MoneyInfo::query()
            ->when(!empty($roomId), function ($q) use ($roomId) {
                $q->where('room_id', $roomId);
            })
            ->when(!empty($contractId), function ($q) use ($contractId) {
                $q->where('contract_id', $contractId);
            })
            ->where('remain', '<>', 0)->with(['details'])->get();

        $bills = [];
        foreach ($moneyInfos as $moneyInfo) {
            $billItemAmount = 0;
            $feeItem = [
                'name' => $moneyInfo->money_info_name,
                'total' => 0,
                'items' => []
            ];
            foreach ($moneyInfo->details as $detail) {
                $amountBill = !empty($detail->sum_amount) ? $detail->sum_amount : $detail->amount;
                $billItemAmount += $amountBill;

                $feeItem['items'][] = [
                    'name' => $detail->name,
                    'amount' => $amountBill
                ];
            }
            $feeItem['total'] = $billItemAmount;

            $bills[] = $feeItem;
        }

        return response()->json($bills);
    }

    public function checkInvoice(Request $request) {
        if (!$request->phone) {
            return response([
                'status' => 610,
                'message' => 'Số điện thoại không được để trống'
            ]);
        }

        if (!$request->checkSum) {
            return response([
                'status' => 620,
                'message' => 'checkSum không được để trống'
            ]);
        }

        if (!$this->validateCheckSum($request->phone, $request->checkSum)) {
            return response([
                'status' => 700,
                'message' => 'Dữ liệu không được xác thực'
            ]);
        }

        $phone = $request->input('phone');
        $contract = Contract::where('phone', $phone)->where('status', Contract::VALIDATED)->first();
        if (!$contract) {
            return response([
                'status' => 800,
                'message' => 'Không tìm thấy hợp đồng với số điện thoại trên'
            ]);
        }

        $roomId = $contract->room_id;
        $contractId = $contract->id;

        $items = MoneyInfo::query()
            ->when(!empty($roomId), function ($q) use ($roomId) {
                $q->where('room_id', $roomId);
            })
            ->when(!empty($contractId), function ($q) use ($contractId) {
                $q->where('contract_id', $contractId);
            })
            ->where('remain', '<>', 0);

        $sum = clone $items;
        $pay = clone $items;
        $remain = clone $items;
        $discount = clone $items;

        $ids = $items->get()->pluck('id')->toArray();
        $details = MoneyDetail::query()->whereIn('money_info_id', $ids)->get();

        $retVal = [];
        $userArr = [];

        $sum = 0;
        $pay = $pay->sum('pay');
        $remain = $remain->sum('remain');
        $discount = $discount->sum('discount');

        foreach ($details as $detail) {
            $sum += !empty($detail->sum_amount) ? $detail->sum_amount : $detail->amount;
            $retVal['items'][] = [
                'id' => $detail->hostel_fee_id,
                'name' => $detail->name,
                'price' => (in_array(optional($detail->hostelFee)->type, [
                    HostelFee::ELECTRIC,
                    HostelFee::WATER
                ])) ? -1 : $detail->value,
                'start_index' => intval($detail->start_index),
                'end_index' => intval($detail->end_index),
                'qty' => intval($detail->qty_text_2),
                'amount' => !empty($detail->sum_amount) ? $detail->sum_amount : $detail->amount,
                'type' => !empty($detail->hostelFee) ? $detail->hostelFee->type : HostelFee::OTHER

            ];
        }

        if ($contract) {
            $users = RenterRoom::selectRaw('users.*')->join('users', 'users.id', '=', 'renter_rooms.user_id')
                ->where('renter_rooms.contract_id', $contract->id)->get();

            foreach ($users as $user) {
                $userArr[] = [
                    'id' => $user->id,
                    'name' => $user->name,
                    'phone' => $user->phone,
                    'email' => $user->email
                ];
            }

        }

        $retVal['name'] = 'Hoá đơn chưa thanh toán hết phòng ' . $contract->room->name;
        $retVal['config_note'] = Functions::getConfigNote($contract->hostel);
        $retVal['hostel_name'] = $contract->hostel ? $contract->hostel->name : null;
        $retVal['room_name'] = $contract->room->name;
        $retVal['room_id'] = $contract->room->id;
        $retVal['amount'] = intval($sum);
        $retVal['pay'] = intval($pay);
        $retVal['remain'] = intval($remain);
        $retVal['discount'] = intval($discount);
        $retVal['users'] = $userArr;
        $retVal['ids'] = $ids;

        $retVal['contract'] = [
            'id' => $contract->id,
            'name' => $contract->name
        ];
        if ($contract->bed) {
            $retVal['bed'] = [
                'id' => $contract->bed->id,
                'name' => $contract->bed->name
            ];
        }

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

    private function validateCheckSum($phone, $checkSumEncode) {
        $partners = config('invoice_partner.partners');
        foreach ($partners as $partner) {
            $hash = $partner['code'] . '|' . $phone . '|' . $partner['secret'];
            if ($checkSumEncode == md5($hash)) {
                return true;
            }
        }

        return false;
    }

    public function saveTransaction(Request $request) {
        if (!$request->phone) {
            return response([
                'status' => 610,
                'message' => 'Số điện thoại không được để trống'
            ]);
        }

        if (!$request->checkSum) {
            return response([
                'status' => 620,
                'message' => 'Check sum không được để trống'
            ]);
        }

        if (!$request->merchant_code) {
            return response([
                'status' => 630,
                'message' => 'merchant code không được để trống'
            ]);
        }

        if (!$request->transaction_no) {
            return response([
                'status' => 640,
                'message' => 'transaction no không được để trống'
            ]);
        }

        if (!$request->bank_code) {
            return response([
                'status' => 650,
                'message' => 'bank code không được để trống'
            ]);
        }

        if (!$request->amount) {
            return response([
                'status' => 660,
                'message' => 'amount không được để trống'
            ]);
        }

        if (!$this->validateCheckSum($request->phone, $request->checkSum)) {
            return response([
                'status' => 700,
                'message' => 'Check sum không chính xác'
            ]);
        }

        $contract = Contract::where('phone', $request->get('phone'))->where('status', Contract::VALIDATED)->first();

        if (!$contract) {
            return response([
                'status' => 800,
                'message' => 'Không tìm thấy hợp đồng với số điện thoại trên'
            ]);
        }

        \DB::beginTransaction();
        try {
            $data = $request->all();
            $transaction = PaymentOnlineTransaction::create([
                'phone' => $request->get('phone'),
                'merchant_code' => $request->get('merchant_code'),
                'transaction_no' => $request->get('transaction_no'),
                'bank_code' => $request->get('bank_code'),
                'pay_date' => $request->get('pay_date'),
                'amount' => $request->get('amount'),
                'payload' => json_encode($data),
            ]);

            if (!$transaction) {
                return response([
                    'status' => 0,
                    'message' => 'Cập nhật thanh toán không thành công'
                ]);
            }

            $roomId = $contract->room_id;
            $contractId = $contract->id;

            $items = MoneyInfo::query()
                ->when(!empty($roomId), function ($q) use ($roomId) {
                    $q->where('room_id', $roomId);
                })
                ->when(!empty($contractId), function ($q) use ($contractId) {
                    $q->where('contract_id', $contractId);
                })
                ->where('remain', '<>', 0);

            $ids = $items->get()->pluck('id')->toArray();
            $this->createPayment($ids);
             \DB::commit();

            return response([
                'status' => 1,
                'message' => 'Cập nhật thanh toán thành công'
            ]);
        } catch (\Exception $exception) {
            \DB::rollBack();

            return response([
                'status' => 0,
                'message' => 'Cập nhật thanh toán không thành công'
            ]);
        }
    }

    private function createPayment($ids) {
        $dateAction = Carbon::now()->format('d/m/Y');
        $payer = "";
        $paymentMethod = 3;

        if (empty($ids) || !is_array($ids)) {
            return false;
        }

        $moneyInfos = MoneyInfo::query()
            ->with([
                'hostel',
                'room'
            ])
            ->whereIn('id', $ids)
            ->get();

        if (empty($dateAction)) {
            $dateAction = Carbon::now()->toDateString();
        } else {
            $dateAction = Carbon::createFromFormat('d/m/Y', $dateAction)->toDateString();
        }

        foreach ($moneyInfos as $moneyInfo) {
            $amount = $moneyInfo->amount - $moneyInfo->discount - $moneyInfo->pay;
            if ($amount == 0) {
                continue;
            }
            $moneyInfo->remain = 0;
            $moneyInfo->pay = $moneyInfo->amount - $moneyInfo->discount;
            $moneyInfo->save();

            $moneyInfoId = $moneyInfo->id;
            $hostelId = $moneyInfo->hostel_id;
            $userId = NULL;
            $roomId = $moneyInfo->room_id;

            $transaction = Transaction::create([
                'amount' => $amount,
                'hostel_id' => $hostelId,
                'date_action' => $dateAction,
                'user_id' => $userId,
                'money_info_id' => $moneyInfoId,
                'type' => CollectSpend::COLLECT,
                'payer' => $payer
            ]);

            CollectSpend::create([
                'amount' => $amount,
                'hostel_id' => $hostelId,
                'room_id' => $roomId,
                'payment_method' => $paymentMethod,
                'date_action' => $dateAction,
                'user_id' => $userId,
                'money_info_id' => $moneyInfoId,
                'type' => CollectSpend::COLLECT,
                'transaction_id' => $transaction->id,
                'payer' => $payer
            ]);
        }
    }
}
