<?php

namespace App\Modules\Company\Subscription\Payments;

use App\Models\Company;
use App\Models\CompanySubscriptionPayments;
use App\Models\CompanySubscriptionRates;
use App\Models\CompanySubscriptions;

use App\Modules\Company\Subscription\Discount\Coupon;

use App\Traits\CreateUserActionTraits;
use App\Traits\UserTraits;
use App\Traits\ValidatorTraits;

use App\Jobs\Company\ProcessSendCompletedSetupEmail;
use App\Jobs\Company\ProcessSendEmailPurchaseSubscription;

use Illuminate\Support\Str;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Auth;

use Carbon\Carbon;
use Stripe;

class FirstSubscriptionPayment
{
    use ValidatorTraits, UserTraits, CreateUserActionTraits;
    public $coupon;

    public function __construct()
    {
        $this->coupon = new Coupon;
        Stripe\Stripe::setApiKey(config('stripe.secret_key'));
        // Stripe\Stripe::setApiKey(env('STRIPE_SECRET'));
    }

    public function getDiscountedValue($percentage, $amountToBePercentage)
    {
        return (float) ($percentage / 100) * $amountToBePercentage;
    }

    public function stripePayment($paymentPayload)
    {

        $invoiceNumber = 'IVN-' . Carbon::now()->format('Y-m-d-h-i-s') . '-' . Str::random(10);
        //
        try {
            DB::beginTransaction();
            //check  if company has subscription
            $companySubscriptionDetails = $this->fetchCompanySubscription($paymentPayload->companyID);

            if ($companySubscriptionDetails) {
                // Update if company has payment details
                $customer = \Stripe\Customer::update(

                    $companySubscriptionDetails->customer_id,
                    [
                        'email' => $paymentPayload->currentUserEmailAddress,
                        'source' => $paymentPayload->stripeToken,
                        "metadata" => ["company_id" => $paymentPayload->companyID],
                    ]
                );
                $stripeCustomerID = $companySubscriptionDetails->customer_id;

            } else {
                $customer = \Stripe\Customer::create([
                    'email' => $paymentPayload->currentUserEmailAddress,
                    'source' => $paymentPayload->stripeToken,
                    "metadata" => ["company_id" => $paymentPayload->companyID],
                ]);
                $stripeCustomerID = $customer->id;
            }

            //Stripe charge payment
            if ($paymentPayload->amountToPay <= 0) {
                // Big discount, negative amount due
                $stripePaymentTransaction = (object) [
                    'id' => 'no-charge-transaction',
                    'status' => 'succeeded',
                    'receipt_url' => '',
                ];
            } else {
                $stripePaymentTransaction = \Stripe\Charge::create([
                    'customer' => $stripeCustomerID,
                    'amount' => $paymentPayload->amountToPay * 100,
                    'currency' => 'usd',
                    'receipt_email' => $paymentPayload->currentUserEmailAddress,
                ]);
            }

            //NOTE: Before m save calculate mona ang remaining balance
            if (($stripePaymentTransaction && $stripePaymentTransaction->status == "succeeded")) {

                $companySubscriptionData = array(
                    'subscription_rate_id' => $paymentPayload->subcriptionRateID,
                    'company_id' => $paymentPayload->companyID,
                    'customer_id' => $stripeCustomerID,
                    'invoice_no' => $invoiceNumber,
                    'date_subscribed' => $paymentPayload->dateTransacted,
                    'current_month_paid' => $paymentPayload->monthlySubscriptionDuration ? $paymentPayload->monthlySubscriptionDuration : $paymentPayload->subcriptionDurationDate, //monthly duratioon for monthly mode
                    'duration' => $paymentPayload->subcriptionDurationDate,
                    'mode_of_payment' => $paymentPayload->mode,
                    'rate' => $paymentPayload->subscriptionRatePrice,
                    'discount' => $paymentPayload->totalDiscount,
                    'total_paid' => $paymentPayload->amountToPay,
                    'amount_paid' => $paymentPayload->amountToPay,
                    'previous_bill' => 0,
                    'current_bill' => $paymentPayload->subscriptionRatePrice,
                    'amount_due' => $paymentPayload->amountDue,
                    'penalty_charge' => 0,
                );

                $companySubscriptionTransaction = $this->createCompanySubscription($paymentPayload->companyID, $companySubscriptionData);

                $paymentDetails = array(
                    'charge_id' => $stripePaymentTransaction->id,
                    'company_subscription_id' => $companySubscriptionTransaction->id,
                    'subscription_rate_id' => $paymentPayload->subcriptionRateID,
                    'company_id' => $paymentPayload->companyID,
                    'customer_id' => $stripeCustomerID,
                    'user_id' => $paymentPayload->currentUserID,
                    'invoice_no' => $invoiceNumber,
                    'mode_of_payment' => $paymentPayload->mode,
                    'rate' => $paymentPayload->subscriptionRatePrice,
                    'duration' => $paymentPayload->subcriptionDurationDate,
                    'discount' => $paymentPayload->companyDiscount,
                    'coupon_discount' => $paymentPayload->couponDiscount,
                    'total_discounted_amount' =>  $paymentPayload->totalDiscount,
                    'amount_paid' => $paymentPayload->amountToPay,
                    'month_paid' => $paymentPayload->subcriptionDurationDate,
                    'current_bill' => $paymentPayload->subscriptionRatePrice,
                    'previous_bill' => 0,
                    'penalty_charge' => 0,
                    'balance' => $paymentPayload->amountDue, //equal to amount due
                    'type' => 'subscribe',
                    'total_paid' => $paymentPayload->amountToPay,
                );
                $subscriptionPaymentTransaction = $this->createSubscriptionPayment($paymentDetails);
            }

            $saveUserAction = $this->createUserAction('Subscribed the ' . $paymentPayload->subcriptionRateName . ' subscription plan');

            if ($companySubscriptionTransaction && $subscriptionPaymentTransaction) {
                DB::commit();

                $currentUser = $this->getCurrentUser();

                $user_data = [
                    'title' => 'ConX Purchase Subscription Confirmation',
                    'email' => $paymentPayload->currentUserEmailAddress,
                    'currentUser' => $currentUser->first_name . ' ' . $currentUser->last_name,
                    'amountPaid' => round($paymentPayload->amountToPay, 2),
                    'duration' => date("F j, Y", strtotime($paymentPayload->subcriptionDurationDate))
                ];

                ProcessSendCompletedSetupEmail::dispatch(Auth::user()->email_address)->onConnection('jobs_emails')->onQueue('sendemail');

                ProcessSendEmailPurchaseSubscription::dispatch($paymentPayload->currentUserEmailAddress, $user_data)->onConnection('jobs_emails')->onQueue('sendemail');

                /* Add usage on coupon code */
                if ($paymentPayload->couponDiscount && $paymentPayload->couponData) {
                    $companyUsageData = array(
                        'couponID' => $paymentPayload->couponData->id,
                        'companyID' => $paymentPayload->companyID,
                    );

                    $this->coupon->addUsageOnCouponDiscount($companyUsageData);
                }

                return [
                    'result' => $stripePaymentTransaction->status,
                    'invoice_no' => $invoiceNumber,
                    'receipt_url' => $stripePaymentTransaction->receipt_url,
                    'rate_name' => $paymentPayload->subcriptionRateName,
                    'note' => 'Successfully Purchased Subscription!',
                ];
            } else {
                DB::rollBack();
            }

        } catch (Error $e) {
            http_response_code(500);
            echo json_encode(['error' => $e->getMessage()]);
        }
    }

    public function fetchCompanySubscription($id)
    {
        return CompanySubscriptions::where('company_id', $id)->first();
    }

    public function createCompanySubscription($companyID, $data)
    {
        return CompanySubscriptions::create($data);
    }

    public function createSubscriptionPayment($data)
    {
        return CompanySubscriptionPayments::create($data);
    }

}
