<?php

namespace App\Http\Controllers;

use App\Models\Affiliate;
use App\Models\Country;
use App\Models\License;
use App\Ninja\Mailers\ContactMailer;
use App\Ninja\Repositories\AccountRepository;
use App\Libraries\CurlUtils;
use Auth;
use Cache;
use CreditCard;
use Omnipay;
use Session;
use URL;
use Utils;
use Validator;
use View;
use Request;

class NinjaController extends BaseController
{
    /**
     * @var AccountRepository
     */
    protected $accountRepo;

    /**
     * @var ContactMailer
     */
    protected $contactMailer;

    /**
     * NinjaController constructor.
     *
     * @param AccountRepository $accountRepo
     * @param ContactMailer     $contactMailer
     */
    public function __construct(AccountRepository $accountRepo, ContactMailer $contactMailer)
    {
        $this->accountRepo = $accountRepo;
        $this->contactMailer = $contactMailer;
    }

    /**
     * @param array     $input
     * @param Affiliate $affiliate
     *
     * @return array
     */
    private function getLicensePaymentDetails(array $input, Affiliate $affiliate)
    {
        $country = Country::find($input['country_id']);

        $data = [
            'firstName' => $input['first_name'],
            'lastName' => $input['last_name'],
            'email' => $input['email'],
            'number' => $input['card_number'],
            'expiryMonth' => $input['expiration_month'],
            'expiryYear' => $input['expiration_year'],
            'cvv' => $input['cvv'],
            'billingAddress1' => $input['address1'],
            'billingAddress2' => $input['address2'],
            'billingCity' => $input['city'],
            'billingState' => $input['state'],
            'billingPostcode' => $input['postal_code'],
            'billingCountry' => $country->iso_3166_2,
            'shippingAddress1' => $input['address1'],
            'shippingAddress2' => $input['address2'],
            'shippingCity' => $input['city'],
            'shippingState' => $input['state'],
            'shippingPostcode' => $input['postal_code'],
            'shippingCountry' => $country->iso_3166_2,
        ];

        $card = new CreditCard($data);

        return [
            'amount' => $affiliate->price,
            'card' => $card,
            'currency' => 'USD',
            'returnUrl' => URL::to('license_complete'),
            'cancelUrl' => URL::to('/'),
        ];
    }

    /**
     * @return $this|\Illuminate\Contracts\View\View
     */
    public function show_license_payment()
    {
        if (\Request::has('return_url')) {
            session(['return_url' => \Request::input('return_url')]);
        }

        if (\Request::has('affiliate_key')) {
            if ($affiliate = Affiliate::where('affiliate_key', '=', \Request::input('affiliate_key'))->first()) {
                session(['affiliate_id' => $affiliate->id]);
            }
        }

        if (\Request::has('product_id')) {
            session(['product_id' => \Request::input('product_id')]);
        } elseif (! Session::has('product_id')) {
            session(['product_id' => PRODUCT_ONE_CLICK_INSTALL]);
        }

        if (! Session::get('affiliate_id')) {
            return Utils::fatalError();
        }

        if (Utils::isNinjaDev() && \Request::has('test_mode')) {
            session(['test_mode' => \Request::input('test_mode')]);
        }

        $account = $this->accountRepo->getNinjaAccount();
        $account->load('account_gateways.gateway');
        $accountGateway = $account->getGatewayByType(GATEWAY_TYPE_CREDIT_CARD);
        $gateway = $accountGateway->gateway;
        $acceptedCreditCardTypes = $accountGateway->getCreditcardTypes();

        $affiliate = Affiliate::find(Session::get('affiliate_id'));

        $data = [
            'showBreadcrumbs' => false,
            'hideHeader' => true,
            'url' => 'license',
            'amount' => $affiliate->price,
            'client' => false,
            'contact' => false,
            'gateway' => $gateway,
            'account' => $account,
            'accountGateway' => $accountGateway,
            'acceptedCreditCardTypes' => $acceptedCreditCardTypes,
            'countries' => Cache::get('countries'),
            'currencyId' => 1,
            'currencyCode' => 'USD',
            'paymentTitle' => $affiliate->payment_title,
            'paymentSubtitle' => $affiliate->payment_subtitle,
            'showAddress' => true,
        ];

        return View::make('payments.stripe.credit_card', $data);
    }

    /**
     * @return \Illuminate\Contracts\View\View
     */
    public function do_license_payment()
    {
        $testMode = Session::get('test_mode') === 'true';

        $rules = [
            'first_name' => 'required',
            'last_name' => 'required',
            'email' => 'required',
            'card_number' => 'required',
            'expiration_month' => 'required',
            'expiration_year' => 'required',
            'cvv' => 'required',
            'address1' => 'required',
            'city' => 'required',
            'state' => 'required',
            'postal_code' => 'required',
            'country_id' => 'required',
        ];

        $validator = Validator::make(Request::all(), $rules);

        if ($validator->fails()) {
            return redirect()->to('license')
                ->withErrors($validator)
                ->withInput();
        }

        $account = $this->accountRepo->getNinjaAccount();
        $account->load('account_gateways.gateway');
        $accountGateway = $account->getGatewayByType(GATEWAY_TYPE_CREDIT_CARD);

        try {
            $affiliate = Affiliate::find(Session::get('affiliate_id'));

            if ($testMode) {
                $ref = 'TEST_MODE';
            } else {
                $details = self::getLicensePaymentDetails(Request::all(), $affiliate);

                $gateway = Omnipay::create($accountGateway->gateway->provider);
                $gateway->initialize((array) $accountGateway->getConfig());
                $response = $gateway->purchase($details)->send();

                $ref = $response->getTransactionReference();

                if (! $response->isSuccessful() || ! $ref) {
                    $this->error('License', $response->getMessage(), $accountGateway);

                    return redirect()->to('license')->withInput();
                }
            }

            $licenseKey = Utils::generateLicense();

            $license = new License();
            $license->first_name = \Request::input('first_name');
            $license->last_name = \Request::input('last_name');
            $license->email = \Request::input('email');
            $license->transaction_reference = $ref;
            $license->license_key = $licenseKey;
            $license->affiliate_id = Session::get('affiliate_id');
            $license->product_id = Session::get('product_id');
            $license->save();

            $data = [
                'message' => $affiliate->payment_subtitle,
                'license' => $licenseKey,
                'hideHeader' => true,
                'productId' => $license->product_id,
                'price' => $affiliate->price,
            ];

            $name = "{$license->first_name} {$license->last_name}";
            $this->contactMailer->sendLicensePaymentConfirmation($name, $license->email, $affiliate->price, $license->license_key, $license->product_id);

            if (Session::has('return_url')) {
                $data['redirectTo'] = Session::get('return_url')."?license_key={$license->license_key}&product_id=".Session::get('product_id');
                $data['message'] = 'Redirecting to ' . Session::get('return_url');
            }

            return View::make('public.license', $data);
        } catch (\Exception $e) {
            $this->error('License-Uncaught', false, $accountGateway, $e);

            return redirect()->to('license')->withInput();
        }
    }

    /**
     * @return string
     */
    public function claim_license()
    {
        $licenseKey = \Request::input('license_key');
        $productId = \Request::input('product_id', PRODUCT_ONE_CLICK_INSTALL);

        // add in dashes
        if (strlen($licenseKey) == 20) {
            $licenseKey = sprintf('%s-%s-%s-%s-%s',
                substr($licenseKey, 0, 4),
                substr($licenseKey, 4, 4),
                substr($licenseKey, 8, 4),
                substr($licenseKey, 12, 4),
                substr($licenseKey, 16, 4));
        }

        $license = License::where('license_key', '=', $licenseKey)
                    ->where('is_claimed', '<', 10)
                    ->where('product_id', '=', $productId)
                    ->first();

        if ($license) {
            if ($license->transaction_reference != 'TEST_MODE') {
                $license->is_claimed = $license->is_claimed + 1;
                $license->save();
            }

            if ($productId == PRODUCT_INVOICE_DESIGNS) {
                return file_get_contents(storage_path() . '/invoice_designs.txt');
            } else {
                return $license->created_at->format('Y-m-d');
            }
        } else {
            return RESULT_FAILURE;
        }
    }

    private function error($type, $error, $accountGateway = false, $exception = false)
    {
        $message = '';
        if ($accountGateway && $accountGateway->gateway) {
            $message = $accountGateway->gateway->name . ': ';
        }
        $message .= $error ?: trans('texts.payment_error');
        Session::flash('error', $message);
        Utils::logError("Payment Error [{$type}]: " . ($exception ? Utils::getErrorString($exception) : $message), 'PHP', true);
    }

    public function hideWhiteLabelMessage()
    {
        $user = Auth::user();
        $company = $user->account->company;

        $company->plan = null;
        $company->save();

        return RESULT_SUCCESS;
    }

    public function purchaseWhiteLabel()
    {
        if (Utils::isNinja()) {
            return redirect('/');
        }

        $user = Auth::user();
        $account = $user->account;
        $url = NINJA_APP_URL . '/buy_now';
        $contactKey = $user->primaryAccount()->account_key;

        $data = [
            'account_key' => NINJA_LICENSE_ACCOUNT_KEY,
            'contact_key' => $contactKey,
            'product_id' => PRODUCT_WHITE_LABEL,
            'first_name' => $user->first_name,
            'last_name' => $user->last_name,
            'email' => $user->email,
            'name' => $account->name,
            'address1' => $account->address1,
            'address2' => $account->address2,
            'city' => $account->city,
            'state' => $account->state,
            'postal_code' => $account->postal_code,
            'country_id' => $account->country_id,
            'vat_number' => $account->vat_number,
            'return_link' => true,
        ];

        if ($url = CurlUtils::post($url, $data)) {
            return redirect($url);
        } else {
            return redirect()->back()->withError(trans('texts.error_refresh_page'));
        }
    }
}
