<?php

namespace App\Http\Controllers\Api;

use App\Constants\Status;
use App\Http\Controllers\Controller;
use App\Lib\Api\UserActionProcess;
use App\Lib\FormProcessor;
use App\Models\AutoPayment;
use App\Models\MobileOperator;
use App\Models\SetupUtilityBill;
use App\Models\TransactionCharge;
use App\Models\User;
use App\Models\UserAction;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Validator;

class AutoPaymentController extends Controller {
    public function index() {
        $notify[] = "Auto Payment";

        $user                 = auth()->user();
        $sendMoneyCharge      = TransactionCharge::where('slug', 'send_money')->first();
        $mobileRechargeCharge = TransactionCharge::where('slug', 'mobile_recharge')->first();
        $mobileOperators      = MobileOperator::active()->get();
        $utility              = SetupUtilityBill::active()->autoPayable()->with('form')->whereHas('form')->get();

        $utilityBill    = AutoPayment::active()->with('user:id,username,firstname,lastname,email,dial_code,mobile', 'setupUtilityBill')->where('user_id', auth()->id())->utilityBill()->get();
        $mobileRecharge = AutoPayment::active()->with(['user:id,username,firstname,lastname,email,dial_code,mobile'])->where('user_id', auth()->id())->mobileRecharge()->get();
        $sendMoney      = AutoPayment::active()->with(['user:id,username,firstname,lastname,email,dial_code,mobile', 'receiver:id,username,firstname,lastname,email,dial_code,mobile'])->where('user_id', auth()->id())->sendMoney()->get();
        return responseSuccess('pay_bill', $notify, [
            'otp_type'                     => otpType(),
            'current_balance'              => $user->balance,
            'send_money_charge'            => $sendMoneyCharge,
            'mobile_recharge_charge'       => $mobileRechargeCharge,
            'mobile_operators'             => $mobileOperators,
            'utility'                      => $utility,
            'auto_payment_pay_bill'        => $utilityBill,
            'auto_payment_mobile_recharge' => $mobileRecharge,
            'auto_payment_send_money'      => $sendMoney,
        ]);
    }

    public function payBillConfirm(Request $request) {
        $utility = SetupUtilityBill::active()->autoPayable()->whereHas('form')->find($request->utility_id);
        if (!$utility) {
            $notify[] = "Sorry, Utility bill not found";
            return responseError('validation_error', $notify);
        }

        $formData       = $utility->form->form_data;
        $formProcessor  = new FormProcessor();
        $validationRule = $formProcessor->valueValidation($formData);
        $userData       = $formProcessor->processFormData($request, $formData);

        $validator = Validator::make($request->all(), array_merge([
            'amount'       => 'required|gt:0',
            'utility_id'   => 'required',
            'otp_type'     => otpType(validation: true),
            'pin'          => 'required',
            'payment_days' => 'required|in:weekly,15days,monthly',
            'next_payment' => 'required|date|after_or_equal:today|date_format:Y-m-d',
        ], $validationRule));

        if ($validator->fails()) {
            return responseError('validation_error', $validator->errors());
        }

        $user = auth()->user();

        if (!Hash::check($request->pin, $user->password)) {
            $notify[] = 'Provided PIN does not correct';
            return responseError('validation_error', $notify);
        }

        $userAction          = new UserActionProcess();
        $userAction->user_id = $user->id;
        $userAction->act     = 'auto_payment_utility_bill';

        $userAction->details = [
            'amount'       => $request->amount,
            'utility_id'   => $utility->id,
            'user_data'    => $userData,
            'payment_type' => 'utility_bill',
            'payment_days' => $request->payment_days,
            'next_payment' => $request->next_payment,
            'done_route'   => 'api.auto.payment.pay.bill.done',
        ];

        if (count(otpType())) {
            $userAction->type = $request->otp_type;
        }

        $userAction->submit();
        $actionId = $userAction->action_id;

        if ($userAction->verify_api_otp) {
            $notify[] = 'Verify otp';
            return responseSuccess('verify_otp', $notify, [
                'action_id' => $actionId,
            ]);
        }

        return callApiMethod($userAction->next_route, $actionId);
    }

    public function payBillDone($actionId) {
        $user = auth()->user();

        $userAction = UserAction::where('user_id', $user->id)
            ->where('user_type', 'USER')
            ->where('is_api', Status::YES)
            ->where('is_used', Status::NO)
            ->where('id', $actionId)
            ->first();

        if (!$userAction) {
            $notify[] = "Sorry! Unable to process";
            return responseError('validation_error', $notify);
        }
        $details = $userAction->details;

        $userAction->is_used = Status::YES;
        $userAction->save();

        $autoPayment               = new AutoPayment();
        $autoPayment->user_id      = $userAction->user_id;
        $autoPayment->utility_id   = $details->utility_id;
        $autoPayment->user_data    = $details->user_data;
        $autoPayment->payment_type = $details->payment_type;
        $autoPayment->payment_days = $details->payment_days;
        $autoPayment->next_payment = $details->next_payment;
        $autoPayment->amount       = $details->amount;
        $autoPayment->save();

        $notify[] = 'Auto payment established for utility bill';
        return responseSuccess('auto_payment_utility_bill_done', $notify, [
            'auto_payment' => $autoPayment,
        ]);
    }

    public function sendMoneyConfirm(Request $request) {
        $validator = Validator::make($request->all(), array_merge([
            'amount'       => 'required|gt:0',
            'user'         => 'required',
            'otp_type'     => otpType(validation: true),
            'pin'          => 'required',
            'payment_days' => 'required|in:weekly,15days,monthly',
            'next_payment' => 'required|date|after_or_equal:today|date_format:Y-m-d',
        ]));

        if ($validator->fails()) {
            return responseError('validation_error', $validator->errors());
        }

        $user = auth()->user();

        if (!Hash::check($request->pin, $user->password)) {
            $notify[] = 'Provided PIN does not correct';
            return responseError('validation_error', $notify);
        }

        $receiver = User::where('id', '!=', auth()->id())->where(function ($query) use ($request) {
            $query->where('username', $request->user)->orWhereRaw("CONCAT(dial_code, mobile) = ?", [$request->user]);
        })->first();
        if (!$receiver) {
            $notify[] = 'Sorry! Receiver not found';
            return responseError('validation_error', $notify);
        }

        $sendMoneyCharge = TransactionCharge::where('slug', 'send_money')->first();
        if (!$sendMoneyCharge) {
            $notify[] = 'Sorry, Transaction charge not found';
            return responseError('validation_error', $notify);
        }

        if ($request->amount < $sendMoneyCharge->min_limit || $request->amount > $sendMoneyCharge->max_limit) {
            $notify[] = 'Please follow the send money limit';
            return responseError('validation_error', $notify);
        }

        $autoPaymentExits = AutoPayment::active()->where('user_id', $user->id)->where('payment_type', 'send_money')->where('receiver_id', $receiver->id)->first();
        if ($autoPaymentExits) {
            $notify[] = 'An auto payment to send money to this receiver already exists';
            return responseError('validation_error', $notify);
        }

        $userAction          = new UserActionProcess();
        $userAction->user_id = $user->id;
        $userAction->act     = 'send_money';

        $userAction->details = [
            'amount'       => $request->amount,
            'receiver_id'  => $receiver->id,
            'payment_days' => $request->payment_days,
            'payment_type' => 'send_money',
            'next_payment' => $request->next_payment,
            'done_route'   => 'api.auto.payment.send.money.done',
        ];

        if (count(otpType())) {
            $userAction->type = $request->otp_type;
        }

        $userAction->submit();
        $actionId = $userAction->action_id;

        if ($userAction->verify_api_otp) {
            $notify[] = 'Verify otp';
            return responseSuccess('verify_otp', $notify, [
                'action_id' => $actionId,
            ]);
        }
        return callApiMethod($userAction->next_route, $actionId);
    }

    public function sendMoneyDone($actionId) {
        $user = auth()->user();

        $userAction = UserAction::where('user_id', $user->id)
            ->where('user_type', 'USER')
            ->where('is_api', Status::YES)
            ->where('is_used', Status::NO)
            ->where('id', $actionId)
            ->first();

        if (!$userAction) {
            $notify[] = "Sorry! Unable to process";
            return responseError('validation_error', $notify);
        }
        $details = $userAction->details;

        $userAction->is_used = Status::YES;
        $userAction->save();

        $autoPayment               = new AutoPayment();
        $autoPayment->user_id      = $userAction->user_id;
        $autoPayment->payment_type = $details->payment_type;
        $autoPayment->payment_days = $details->payment_days;
        $autoPayment->next_payment = $details->next_payment;
        $autoPayment->amount       = $details->amount;
        $autoPayment->receiver_id  = $details->receiver_id;
        $autoPayment->save();

        $notify[] = 'Auto payment established for send money';
        return responseSuccess('auto_payment_send_money_done', $notify, [
            'auto_payment' => $autoPayment,
        ]);
    }

    public function mobileRechargeConfirm(Request $request) {
        $validator = Validator::make($request->all(), array_merge([
            'amount'       => 'required|gt:0',
            'mobile'       => 'required',
            'operator_id'  => 'required',
            'otp_type'     => otpType(validation: true),
            'pin'          => 'required',
            'payment_days' => 'required|in:weekly,15days,monthly',
            'next_payment' => 'required|date|after_or_equal:today|date_format:Y-m-d',
        ]));

        if ($validator->fails()) {
            return responseError('validation_error', $validator->errors());
        }

        $user = auth()->user();

        if (!Hash::check($request->pin, $user->password)) {
            $notify[] = 'Provided PIN does not correct';
            return responseError('validation_error', $notify);
        }

        $operator = MobileOperator::active()->find($request->operator_id);
        if (!$operator) {
            $notify[] = 'Sorry, Operator not found';
            return responseError('validation_error', $notify);
        }

        $mobileRechargeCharge = TransactionCharge::where('slug', 'mobile_recharge')->first();
        if (!$mobileRechargeCharge) {
            $notify[] = 'Sorry, Transaction charge not found';
            return responseError('validation_error', $notify);
        }

        if ($request->amount < $mobileRechargeCharge->min_limit || $request->amount > $mobileRechargeCharge->max_limit) {
            $notify[] = 'Please follow the mobile recharge limit';
            return responseError('validation_error', $notify);
        }

        $autoPaymentExits = AutoPayment::active()->where('user_id', $user->id)->where('payment_type', 'mobile_recharge')->where('operator_id', $operator->id)->whereJsonContains('user_data->mobile', $request->mobile)->first();
        if ($autoPaymentExits) {
            $notify[] = 'An auto payment for mobile recharge to this number already exists';
            return responseError('validation_error', $notify);
        }

        $userAction          = new UserActionProcess();
        $userAction->user_id = $user->id;
        $userAction->act     = 'mobile_recharge';

        $userAction->details = [
            'amount'       => $request->amount,
            'mobile'       => $request->mobile,
            'operator_id'  => $operator->id,
            'payment_days' => $request->payment_days,
            'next_payment' => $request->next_payment,
            'payment_type' => 'mobile_recharge',
            'done_route'   => 'api.auto.payment.mobile.recharge.done',
        ];

        if (count(otpType())) {
            $userAction->type = $request->otp_type;
        }

        $userAction->submit();
        $actionId = $userAction->action_id;

        if ($userAction->verify_api_otp) {
            $notify[] = 'Verify otp';
            return responseSuccess('validation_error', $notify, [
                'action_id' => $actionId,
            ]);
        }

        return callApiMethod($userAction->next_route, $actionId);
    }

    public function mobileRechargeDone($actionId) {
        $user       = auth()->user();
        $userAction = UserAction::where('user_id', $user->id)
            ->where('user_type', 'USER')
            ->where('is_api', Status::YES)
            ->where('is_used', Status::NO)
            ->where('id', $actionId)
            ->first();

        if (!$userAction) {
            $notify[] = 'Sorry! Unable to process';
            return responseError('validation_error', $notify);
        }
        $details = $userAction->details;

        $userAction->is_used = Status::YES;
        $userAction->save();

        $autoPayment               = new AutoPayment();
        $autoPayment->user_id      = $userAction->user_id;
        $autoPayment->payment_type = $details->payment_type;
        $autoPayment->payment_days = $details->payment_days;
        $autoPayment->next_payment = $details->next_payment;
        $autoPayment->amount       = $details->amount;
        $autoPayment->operator_id  = $details->operator_id;
        $autoPayment->user_data    = [
            'mobile' => $details->mobile,
        ];
        $autoPayment->save();

        $notify[] = 'Auto payment established for mobile recharge';
        return responseSuccess('auto_payment_mobile_recharge_done', $notify, [
            'auto_payment' => $autoPayment,
        ]);
    }

    public function remove($id) {
        $autoPayment = AutoPayment::where('user_id', auth()->id())->active()->find($id);

        if (!$autoPayment) {
            $notify[] = 'Auto payment not found';
            return responseError('validation_error', $notify);
        }

        $autoPayment->status = Status::DISABLE;
        $autoPayment->save();
        $notify[] = 'Auto payment remove successfully';
        return responseSuccess('auto_payment_remove', $notify);
    }
}
