<?php

namespace NioModules\WdBank\Services;

use App\Helpers\NioHash;
use App\Models\UserAccount;
use App\Models\WithdrawMethod;
use NioModules\WdBank\WdBankModule;
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\ValidationException;

class UserAccountService
{
    public function getWithdrawMethod()
    {
        return WithdrawMethod::where('slug', WdBankModule::SLUG)->first();
    }

    public function form($request)
    {
        $method = $this->getWithdrawMethod();

        if (filled($method)) {
            $fallback = isset($method->currencies[0]) ? $method->currencies[0] : '';

            return [
                'action' => route('user.withdraw.account.' . WdBankModule::SLUG . '.save'),
                'currencies' => $method->currencies,
                'countries' => filtered_countries($method),
                'default' => data_get($method->config, 'meta.currency', $fallback),
                'quickAdd' => $request->get('quick_added', false),
                'method' => $method,
            ];
        }

        throw ValidationException::withMessages(['unavailable' => __('Method not found.')]);
    }

    private function isRequired($config, $field)
    {
        return (data_get($config, $field . '.req') == 'yes' && data_get($config, $field . '.show') == 'yes') ? true : false;
    }

    public function getFormData($request)
    {
        $formConfig = data_get($this->getWithdrawMethod(), 'config.form');
        $data = [];

        $validate = Validator::make($request->all(), [
            "acc-type" => ['required'],
            "acc-name" => ($this->isRequired($formConfig, 'acc_name')) ? ['required'] : ['nullable'],
            "acc-number" => ['required'],
            "country" => ($this->isRequired($formConfig, 'country')) ? ['required'] : ['nullable'],
            "currency" => ($this->isRequired($formConfig, 'currency')) ? ['required'] : ['nullable'],
            "bank-name" => ['required'],
            "bank-branch" => ($this->isRequired($formConfig, 'bank_branch')) ? ['required'] : ['nullable'],
            "bank-address" => ($this->isRequired($formConfig, 'bank_address')) ? ['required'] : ['nullable'],
            "sortcode" => ($this->isRequired($formConfig, 'sortcode')) ? ['required'] : ['nullable'],
            "routing" => ($this->isRequired($formConfig, 'routing')) ? ['required'] : ['nullable'],
            "swift" => ($this->isRequired($formConfig, 'swift')) ? ['required'] : ['nullable'],
            "iban" => ($this->isRequired($formConfig, 'iban')) ? ['required'] : ['nullable'],
            "wdm-label" => ['nullable', 'string'],
        ], [
            "acc-type.required" => __('Choose "Account Type" of your bank account.'),
            "country.required" => __('Please select your "Bank Location" (country).'),
            "currency.required" => __('Select "Bank Currency" of your bank account.'),
            "acc-name.required" => __('Enter the "Account Name" of your bank account and it should match with account.'),
            "acc-number.required" => __('Enter the "Account Number" of your bank account and make sure it is correct.'),
            "bank-name.required" => __('Enter the "Bank Name" of your account.'),
            "bank-branch.required" => __('Enter the "Branch Name" of your bank.'),
            "bank-address.required" => __('Enter the "Bank Adddress" of your bank.'),
            "sortcode.required" => __('Enter the "Sort Code" of your bank.'),
            "routing.required" => __('Enter the "Routing Number" of your bank.'),
            "swift.required" => __('Enter the "Swift / BIC" code of your bank.'),
            "iban.required" => __('Enter the "IBAN Number" of your bank.')
        ]);

        if ($validate->fails()) {
            $allError = $validate->errors()->toArray();
            $errorChunk = array_chunk($allError, 1, true);

            $error = [
                'type' => 'warning',
                'message' => __('The given data was invalid.'),
                'errors' => (isset($errorChunk[0])) ? $errorChunk[0] : $validate->errors()->first(),
            ];
            return $data = (object) ['status' => false, 'data' => $error];
        }

        $number = ($request->get('acc-number')) ? strip_tags($request->get('acc-number')) : rand(1001, 9999);
        $formData = [
            'name' => ($request->get('wdm-label')) ? strip_tags($request->get('wdm-label')) : 'AC-' . substr(sprintf('%04s', auth()->user()->id), -4, 4) . str_end($number, true),
            'config' => [
                'acc_type' => ($request->get('acc-type')) ? strip_tags($request->get('acc-type')) : '',
                'country' => ($request->get('country')) ? strip_tags($request->get('country')) : '',
                'currency' => ($request->get('currency')) ? strip_tags($request->get('currency')) : '',
                'acc_name' => ($request->get('acc-name')) ? strip_tags($request->get('acc-name')) : '',
                'acc_no' => ($request->get('acc-number')) ? strip_tags($request->get('acc-number')) : '',
                'bank_name' => ($request->get('bank-name')) ? strip_tags($request->get('bank-name')) : '',
                'bank_branch' => ($request->get('bank-branch')) ? strip_tags($request->get('bank-branch')) : '',
                'bank_address' => ($request->get('bank-address')) ? strip_tags($request->get('bank-address')) : '',
                'sortcode' => ($request->get('sortcode')) ? strip_tags($request->get('sortcode')) : '',
                'routing' => ($request->get('routing')) ? strip_tags($request->get('routing')) : '',
                'swift' => ($request->get('swift')) ? strip_tags($request->get('swift')) : '',
                'iban' => ($request->get('iban')) ? strip_tags($request->get('iban')) : '',
            ]
        ];

        return $data = (object) ['status' => true, 'data' => $formData];
    }

    public function userAccount($hash)
    {
        $id = NioHash::toID($hash);
        $userAccount = UserAccount::where('id', $id)->where('slug', WdBankModule::SLUG)->where('user_id', auth()->user()->id)->first();

        return $userAccount;
    }

    public function save($input)
    {
        if ($input->status === true) {
            $account = new UserAccount();
            $account->fill([
                'user_id' => auth()->user()->id,
                'slug' => WdBankModule::SLUG,
                'name' => $input->data['name'],
                'config' => $input->data['config']
            ]);
            $account->save();

            return $account;
        }

        if (is_array($input->data['errors'])) {
            throw ValidationException::withMessages($input->data['errors']);
        }
    }

    public function update($hash, $input)
    {
        if ($input->status === true) {
            $account = $this->userAccount($hash);

            if (blank($account)) {
                throw ValidationException::withMessages(['acc' => [0 => __('Invalid Account'), 1 => __('Sorry, account may invalid or not found.')]]);
            }

            $account->update([
                'user_id' => auth()->user()->id,
                'slug' => WdBankModule::SLUG,
                'name' => $input->data['name'],
                'config' => $input->data['config']
            ]);

            return $account;
        }

        if (is_array($input->data['errors'])) {
            throw ValidationException::withMessages($input->data['errors']);
        }
    }

    public function delete($hash)
    {
        $account = $this->userAccount($hash);

        if (blank($account)) {
            throw ValidationException::withMessages(['acc' => [0 => __('Invalid Account'), 1 => __('Sorry, account may invalid or not found.')]]);
        }

        $account->delete();
    }
}
