<?php

namespace App\Http\Controllers\Admin;

use App\StripePacakge;
use App\Transactions;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Validator;
use App\Packages;
use App\Categories;
use App\Http\Controllers\AdminController;
use App\Excesses;
use App\PackagePrices;
use App\Facilities;
use App\PackageFacilities;
use App\Aws\FileSystem;
use App\WebsiteFaqs;
use App\Media;
use Stripe;
use Session;
use App\Subscription;

use App\GocardlessSubscriptions;
use App\GocardlessCustomers;
use App\Repository\PackagesRepository;
use Illuminate\Support\Str;
use App\SubscriptionFacilities;
use App\Helpers\Functions;
use \GoCardlessPro\Services\SubscriptionsService;

class PackagesController extends AdminController
{

    private $action = "packages";
    private $folder = "packages";
    private $title = "Packages";
    private $heading = "Package";
    private $stripe;

    protected $gocardless;
    public function __construct()
    {
        $this->middleware('auth');

        $this->breadcrumbs = $this->getBreadcrumbs();
        $this->breadcrumbs[1]['link'] = "admin/" . $this->action;
        $this->breadcrumbs[1]['name'] = $this->title;
        $this->stripe = new \Stripe\StripeClient(
            env('STRIPE_SECRET')
        );
        $access_token = getenv('GOCARDLESS_TOKEN');
        $this->gocardless = new \GoCardlessPro\Client(
            array(
                'access_token' => $access_token,
                'environment' => getenv('GOCARDLESS_ENV')
            )
        );
    }

    public function index()
    {
        $model = Packages::get();
        $data["pageHeader"] = false;
        $data["model"] = $model;
        $data["action"] = $this->action;
        $data["folder"] = $this->folder;
        $data["heading"] = $this->heading;
        $data["title"] = $this->title;
        $data["SubTitle"] = "List";
        $data['breadcrumbs'] = $this->breadcrumbs;
        return view('admin/' . $this->folder . '/index', $data);
    }

    public function create(Request $request)
    {
        $data["pageHeader"] = false;
        $data["model"] = new Packages();
        $data["title"] = $this->title;
        $data["subTitle"] = "Create";
        $data["faqs"] = array();
        $data["prices"] = array();
        $data["action"] = $this->action;
        $data["folder"] = $this->folder;
        $data["heading"] = $this->heading;

        $data["categories"] = Categories::pluck('title', 'id');
        $data["excesses"] = Excesses::where("status", 1)->orderBy("position", "asc")->get();

        $data["facilities"] = Facilities::where("status", 1)->orderBy("position", "asc")->get();
        $this->breadcrumbs[2]['link'] = "#_";
        $this->breadcrumbs[2]['name'] = "Create";

        $data["packageFacilities"] = array();


        $data['breadcrumbs'] = $this->breadcrumbs;
        return view('admin/' . $this->folder . '/create', $data);
    }

    public function save(Request $request)
    {
        $rules = [
            'title' => 'required|max:255',
            //'description' => 'required|max:200'
        ];
        $input = $request->all();
        $message = [];
        $validator = Validator::make($input, $rules, $message);
        $header = 200;
        $response = array();
        if ($validator->fails()) {
            $errors = $validator->errors();
            $response['errors'] = $errors;
            $response['error'] = true;
            $header = 402;
            //return redirect()->back()->withErrors($validator->errors())->withInput();
        } else {
            $prices = !empty($input["prices"]) ? $input["prices"] : array();
            $facilities = !empty($input["facilities"]) ? $input["facilities"] : array();

            $file = !empty($input["file"]) ? $input["file"] : null;
            $slugify = slugify($input["title"]);
            unset($input["_token"]);
            unset($input["prices"]);
            unset($input["facilities"]);
            if (!isset($input["popular"])) {
                $input["popular"] = 0;
            }
            if (empty($input["position"])) {
                $input["position"] = 0;
            }
            $input["code"] = $slugify;
            if (!empty($request->image) && $request->image != null) {
                $media_id = Media::getMediaID($request->image);
                $input["image"] = $request->image;
                $input["image_media_id"] = $media_id;
            }
            if (!empty($request->file) && $request->file != null) {
                $destination = "uploads/packages/downloads";
                $fileName = $input["code"];
                $fileName = FileSystem::storeFile($fileName, $request->file, $destination);
                $input["file"] = $fileName;
            }
            $model = new Packages();
            $input["created_at"] = date("Y-m-d H:i:s");
            $id = $model->insertGetId($input);
            //Packages::where("id", $id)->update(array("code" => $slugify));
            $this->insertPrices($id, $prices);
            $this->insertFacilities($id, $facilities);
            $this->createStripePricing(21, $prices, $input, $facilities);
            Session::flash('success', $this->heading . ' added successfully!');
            //return redirect('admin/' . $this->action);
        }
        return response()->json($response, $header);
    }

    public function savefaqs(Request $request)
    {
        $input = $request->all();

        $rules = [
            'title' => 'required'
        ];

        $messages = [];

        $validator = Validator::make($input, $rules, $messages);
        $response = array();

        if ($validator->fails()) {
            $errors = $validator->errors();
            $response['errors'] = $errors;
            $response['error'] = true;
            $header = 402;
        } else {
            unset($input["_token"]);

            $response['error'] = false;
            $header = 200;

            $response['input'] = $input;
        }

        return response()->json($response, $header);
    }

    public function insertPrices($id, $prices)
    {
        foreach ($prices as $type => $excesses) {
            foreach ($excesses as $excess_id => $excess) {
                $arr = array("package_id" => $id, "excess_id" => $excess_id, "type" => $type, "price" => $excess['price'], "vat" => $excess['vat']);
                PackagePrices::insertGetId($arr);
            }
        }
    }
    public function insertFacilities($id, $facilities)
    {
        foreach ($facilities as $facility_id => $facility) {
            // && isset($facility["has_price"]) && !empty($facility["price"])
            if (isset($facility["available"])) {

                if (isset($facility["has_price"])) {
                    $hasPrice = 1;
                    $price = !empty($facility["price"]) ? $facility["price"] : 0;
                } else {
                    $hasPrice = 0;
                    $price = null;
                }

                $arr = array("package_id" => $id, "facility_id" => $facility_id, "hasPrice" => $hasPrice, "price" => $price);
                PackageFacilities::insertGetId($arr);
            }
        }
    }

    public function createStripePricing($package_id, $pricing, $package_data, $facilities)
    {
        
        \Stripe\Stripe::setApiKey(env("STRIPE_SECRET"));
        $stripe = new \Stripe\StripeClient(env("STRIPE_SECRET"));
        $data = array();
        $i = 0;
        foreach ($pricing as $type => $excesses) {
            foreach ($excesses as $excess_id => $excess) {
                $product_id = "product-" . $package_id . "-" . $type . "-" . $excess_id;
                $planId = "plan-" . $package_id . "-" . $type . "-" . $excess_id;
                $excess_data = Excesses::where('id', $excess_id)->first();
                $data[] = $product_id;
                try {
                    $stripe_product = $stripe->products->retrieve($product_id, []);
                } catch (\Stripe\Exception\InvalidRequestException $e) {
                    $stripe_product = $stripe->products->create([
                        'name' => $package_data['title'] . ' ' . $excess_data->title . ' ' . $type,
                        'id' => $product_id,
                        'description' => $package_data['shortDescription'],
                        'active' => true
                    ]);
                }
                $stripe_pricing = $stripe->prices->create([
                    'unit_amount' => bcdiv($excess['price'], 1, 2) * 100,
                    'currency' => 'gbp',
                    'recurring' => ['interval' => substr($type, 0, -2)],
                    'product' => $stripe_product['id']
                ]);

                // $stripe->plans->create([
                //     'amount' => bcdiv($excess['price'], 1, 2) * 100,
                //     'currency' => 'gbp',
                //     'interval' => 'month',
                //     'product' => $stripe_product['id'],
                //     'active' => true,
                //     'id' => $planId,
                // ]);

                StripePacakge::create([
                    'package_id' => $package_id,
                    'excess_id' => $excess_id,
                    'plan_id' => $planId,
                    'plan_name' => $package_data['title'],
                    'product_id' => $product_id,
                    'pricing' => $excess['price'],
                    'pricing_id' => $stripe_pricing['id']
                ]);
            }
        }
        if (count($facilities) > 0) {
            foreach ($facilities as $key => $facility) {
                $facility_data = Facilities::where('id', $facility['available'])->first();
                if ($facility['price'] > 0) {
                    $addon_product_id = "product-" . $package_id . "-facility_id-" . $key;
                    $addon_plan_id = "plan-" . $package_id . "-facility_id-" . $key;
                    //try {
                    //$stripe_product_addon = $stripe->products->retrieve($product_id, []);
                    //} catch (\Stripe\Exception\InvalidRequestException $e) {
                    $stripe_product_addon = $stripe->products->create([
                        'name' => $package_data['title'] . ' (' . $facility_data->title . ')',
                        'id' => $addon_product_id,
                        'description' => $package_data['shortDescription'],
                        'active' => true
                    ]);
                    //}
                    $stripe_pricing_addon = $stripe->prices->create([
                        'unit_amount' => bcdiv($facility['price'], 1, 2) * 100,
                        'currency' => 'gbp',
                        'recurring' => ['interval' => 'month'],
                        'product' => $stripe_product_addon['id']
                    ]);

                    // $stripe->plans->create([
                    //     'amount' => bcdiv($facility['price'], 1, 2) * 100,
                    //     'currency' => 'gbp',
                    //     'interval' => 'month',
                    //     'product' => $stripe_product_addon['id'],
                    //     'active' => true,
                    //     'id' => $addon_plan_id,
                    // ]);

                    // StripePacakge::create([
                    //     'package_id' => $package_id,
                    //     'excess_id' => '',
                    //     'plan_id' => $addon_plan_id,
                    //     'plan_name' => $package_data['title'],
                    //     'product_id' => $addon_product_id,
                    //     'pricing' => $facility['price'],
                    //     'pricing_id' => $stripe_pricing_addon['id']
                    // ]);
                }
            }


        }
        dd($data);
        return array('package_id' => $package_id, 'pricing' => $pricing);
    }

    public function updateStripePricing($package_id, $pricing)
    {

        \Stripe\Stripe::setApiKey(env("STRIPE_SECRET"));
        $stripe = new \Stripe\StripeClient(env("STRIPE_SECRET"));
        $packages = StripePacakge::where('package_id', $package_id)->get();

        if ($packages) {
            foreach ($packages as $package) {
                if (array_key_exists($package['excess_id'], $pricing['monthly'])) {
                    $price = $pricing['monthly'][$package['excess_id']]['price'];
                    $vat = $pricing['monthly'][$package['excess_id']]['vat'];
                    $total = $price + (($price * $vat) / 100);
                    //Delete Old Pricing Plan
                    $deleteStripe = $stripe->plans->delete($package['plan_id'], []);

                    //Create New Pricing Plan with Update Price
                    $stripe->plans->create([
                        'amount' => bcdiv($total, 1, 2) * 100,
                        'currency' => 'gbp',
                        'interval' => 'month',
                        'product' => $package['product_id'],
                        'active' => true,
                        'id' => $package['plan_id'],
                    ]);
                    //Reterive all subscription users form Database

                    $subscriptions = Subscription::where('stripe_plan', $package['plan_id'])->get();
                    //Loop All subscriptions users
                    foreach ($subscriptions as $subscription) {
                        //Verify with stripe subscription based on users
                        $subscription_stripe = \Stripe\Subscription::retrieve($subscription['stripe_id']);
                        //Update subscription with new pricing plan
                        $charge[] = \Stripe\Subscription::update($subscription['stripe_id'], [
                            'cancel_at_period_end' => false,
                            'proration_behavior' => 'create_prorations',
                            'billing_cycle_anchor' => 'unchanged',
                            'items' => [
                                [
                                    'id' => $subscription_stripe->items->data[0]->id,
                                    'price' => $subscription_stripe->items->data[0]->plan->id,
                                ],
                            ],
                        ]);
                    }
                } else {
                    if (array_key_exists($package['excess_id'], $pricing['yearly'])) {
                        $price = $pricing['monthly'][$package['excess_id']]['price'];
                        $vat = $pricing['monthly'][$package['excess_id']]['vat'];
                        $total = $price + (($price * $vat) / 100);
                        //Delete Old Pricing Plan
                        $stripe->plans->delete($package['plan_id'], []);
                        //Create New Pricing Plan with Update Price
                        $stripe->plans->create([
                            'amount' => bcdiv($total, 1, 2) * 100,
                            'currency' => 'gbp',
                            'interval' => 'month',
                            'product' => $package['product_id'],
                            'active' => true,
                            'id' => $package['plan_id'],
                        ]);
                        //Reterive all subscription users form Database
                        $subscriptions = Subscription::where('stripe_plan', $package['plan_id'])->get();
                        //Loop All subscriptions users
                        foreach ($subscriptions as $subscription) {
                            //Verify with stripe subscription based on users
                            $subscription_stripe = \Stripe\Subscription::retrieve($subscription['stripe_id']);
                            //Update subscription with new pricing plan
                            $charge[] = \Stripe\Subscription::update($subscription['stripe_id'], [
                                'cancel_at_period_end' => false,
                                'proration_behavior' => 'create_prorations',
                                'billing_cycle_anchor' => 'unchanged',
                                'items' => [
                                    [
                                        'id' => $subscription_stripe->items->data[0]->id,
                                        'price' => $subscription_stripe->items->data[0]->plan->id,
                                    ],
                                ],
                            ]);
                        }
                    }
                }
            }
        }
        return array('charge' => $charge, 'package_id' => $package_id, 'pricing' => $pricing);
    }

    public function updateGoCardlessPricing($package_id, $pricing, $excess_id = null, $type = null, $package_title = null)
    {
        //dd([$package_id, $pricing, $excess_id = null, $type = null, $package_title = null]);
        $transactions = Transactions::where('paymentMethod', 'direct_debit')->where('package_id', $package_id)->get();
        if ($transactions) {
            foreach ($transactions as $transaction) {
                $cardlessSubscription = GocardlessSubscriptions::where('id', $transaction['subscription_id'])->first();
                if (array_key_exists($transaction['excess_id'], $pricing['monthly'])) {
                    $price = $pricing['monthly'][$transaction['excess_id']]['price'];
                    $vat = $pricing['monthly'][$transaction['excess_id']]['vat'];
                    $total = $price + (($price * $vat) / 100);
                    //d(["name" => $package_title,"amount" => bcdiv($total, 1, 2) * 100,"metadata" => ["subscription_number" => $transaction['invoiceNumber']]],1);
                    $charge[] = $this->gocardless->subscriptions()->update($cardlessSubscription['subscription'], [
                        "params" => [
                            "name" => $package_title,
                            "amount" => bcdiv($total, 1, 2) * 100,
                            "metadata" => [
                                "subscription_number" => $transaction['invoiceNumber']
                            ]
                        ]
                    ]);
                    Transactions::where('paymentMethod', 'direct_debit')->where('package_id', $package_id)->update([
                        'price' => $price,
                        'total' => $total,
                        'vat' => $vat
                    ]);
                } elseif (array_key_exists($transaction['excess_id'], $pricing['yearly'])) {
                    $price = $pricing['monthly'][$transaction['excess_id']]['price'];
                    $vat = $pricing['monthly'][$transaction['excess_id']]['vat'];
                    $total = $price + (($price * $vat) / 100);

                    $charge[] = $this->gocardless->subscriptions()->update($cardlessSubscription['subscription'], [
                        "params" => [
                            "name" => $package_title,
                            "amount" => bcdiv($total, 1, 2) * 100,
                            "metadata" => [
                                "subscription_number" => $transaction['invoiceNumber']
                            ]
                        ]
                    ]);

                    Transactions::where('paymentMethod', 'direct_debit')->where('package_id', $package_id)->update([
                        'price' => $price,
                        'total' => $total,
                        'vat' => $vat
                    ]);
                }
            }
        }

        return array('charge' => $charge, 'package_id' => $package_id, 'pricing' => $pricing);
    }


    public function createGoCardlessPricing($package_id, $pricing, $excess_id = null, $type = null, $package_title = null)
    {
        //dd([$package_id, $pricing, $excess_id = null, $type = null, $package_title = null]);
        $transactions = Transactions::where('paymentMethod', 'direct_debit')->where('package_id', $package_id)->get();
        if ($transactions) {
            foreach ($transactions as $transaction) {
                $cardlessSubscription = GocardlessSubscriptions::where('id', $transaction['subscription_id'])->first();
                if (array_key_exists($transaction['excess_id'], $pricing['monthly'])) {
                    $price = $pricing['monthly'][$transaction['excess_id']]['price'];
                    $vat = $pricing['monthly'][$transaction['excess_id']]['vat'];
                    $total = $price + (($price * $vat) / 100);
                    //d(["name" => $package_title,"amount" => bcdiv($total, 1, 2) * 100,"metadata" => ["subscription_number" => $transaction['invoiceNumber']]],1);
                    $charge[] = $this->gocardless->subscriptions()->update($cardlessSubscription['subscription'], [
                        "params" => [
                            "name" => $package_title,
                            "amount" => bcdiv($total, 1, 2) * 100,
                            "metadata" => [
                                "subscription_number" => $transaction['invoiceNumber']
                            ]
                        ]
                    ]);
                    Transactions::where('paymentMethod', 'direct_debit')->where('package_id', $package_id)->update([
                        'price' => $price,
                        'total' => $total,
                        'vat' => $vat
                    ]);
                } elseif (array_key_exists($transaction['excess_id'], $pricing['yearly'])) {
                    $price = $pricing['monthly'][$transaction['excess_id']]['price'];
                    $vat = $pricing['monthly'][$transaction['excess_id']]['vat'];
                    $total = $price + (($price * $vat) / 100);

                    $charge[] = $this->gocardless->subscriptions()->update($cardlessSubscription['subscription'], [
                        "params" => [
                            "name" => $package_title,
                            "amount" => bcdiv($total, 1, 2) * 100,
                            "metadata" => [
                                "subscription_number" => $transaction['invoiceNumber']
                            ]
                        ]
                    ]);

                    Transactions::where('paymentMethod', 'direct_debit')->where('package_id', $package_id)->update([
                        'price' => $price,
                        'total' => $total,
                        'vat' => $vat
                    ]);
                }
            }
        }

        return array('charge' => $charge, 'package_id' => $package_id, 'pricing' => $pricing);
    }
    public function edit($id)
    {
        $model = Packages::find($id);

        $prices = array();
        $facilities = array();

        foreach ($model->prices as $price) {
            $prices[$price->type][$price->excess_id]["price"] = $price->price;
            $prices[$price->type][$price->excess_id]["vat"] = $price->vat;
        }


        foreach ($model->facilities as $facility) {
            $facilities[$facility->facility_id]["has_price"] = $facility->hasPrice;
            $facilities[$facility->facility_id]["price"] = $facility->price;
        }

        $data["faqs"] = WebsiteFaqs::where("type", $this->action)->where("type_id", $id)->get();
        $data["prices"] = $prices;
        $data["packageFacilities"] = $facilities;
        //$data["prices"] = isset($model->prices) ? $model->prices : array();
        $data["model"] = $model;
        $data["pageHeader"] = false;
        $data["action"] = $this->action;
        $data["folder"] = $this->folder;
        $data["heading"] = $this->heading;
        $data["subTitle"] = "Edit";
        $data["title"] = $this->title;
        $data["id"] = $id;
        $data["categories"] = Categories::pluck('title', 'id');
        $data["excesses"] = Excesses::where("status", 1)->orderBy("position", "asc")->get();
        $data["facilities"] = Facilities::where("status", 1)->orderBy("position", "asc")->get();
        $this->breadcrumbs[2]['link'] = "#_";
        $this->breadcrumbs[2]['name'] = "Edit";
        $data['breadcrumbs'] = $this->breadcrumbs;
        return view('admin/' . $this->folder . '/edit', $data);
    }

    public function update($id, Request $request)
    {
        \Stripe\Stripe::setApiKey(env("STRIPE_SECRET"));
        $rules = [
            'title' => 'required|max:255',
            'file' => 'mimes:pdf|max:2048'
        ];
        $input = $request->all();

        $message = [];
        $validator = Validator::make($input, $rules, $message);
        $header = 200;
        $response = array();
        if ($validator->fails()) {
            $errors = $validator->errors();
            $response['errors'] = $errors;
            $response['error'] = true;
            $header = 402;
            //return redirect()->back()->withErrors($validator->errors())->withInput();
        } else {
            $prices = !empty($input["prices"]) ? $input["prices"] : array();
            $facilities = !empty($input["facilities"]) ? $input["facilities"] : array();
            $file = !empty($input["file"]) ? $input["file"] : null;
            $faqs = !empty($input["faqs"]) ? $input["faqs"] : null;
            WebsiteFaqs::saveFaqs("packages", $id, $faqs);
            unset($input["file"]);
            unset($input["faqs"]);
            unset($input["_token"]);
            unset($input["prices"]);
            unset($input["facilities"]);
            if (!isset($input["status"])) {
                $input["status"] = 0;
            }
            if (!isset($input["popular"])) {
                $input["popular"] = 0;
            }
            $slugify = slugify($input["title"]);
            $input["code"] = $slugify;
            $input["updated_at"] = date("Y-m-d H:i:s");
            if (!empty($request->image) && $request->image != null) {
                $media_id = Media::getMediaID($request->image);
                $input["image"] = $request->image;
                $input["image_media_id"] = $media_id;
            }
            if (!empty($request->file) && $request->file != null) {
                $destination = "uploads/packages/downloads";
                $fileName = $input["code"];
                $fileName = FileSystem::storeFile($fileName, $request->file, $destination);
                $input["file"] = $fileName;
            }
            $update_pricing = $this->updateStripePricing($id, $prices);
            $goCardless_pricing = $this->updateGoCardlessPricing($id, $prices, null, null, $input['title']);
            Packages::where('id', $id)->update($input);
            PackagePrices::where('package_id', $id)->delete();
            PackageFacilities::where('package_id', $id)->delete();
            $this->insertPrices($id, $prices);
            $this->insertFacilities($id, $facilities);
            Session::flash('success', $this->heading . ' updated successfully!');
        }

        return response()->json($response, $header);
    }

    public function delete($id)
    {
        PackagePrices::where('package_id', $id)->delete();
        PackageFacilities::where('package_id', $id)->delete();
        Packages::where('id', $id)->delete();
        Session::flash('error', $this->heading . ' deleted successfully!');
        return redirect('admin/' . $this->action);
    }

    public function show($id)
    {

        $q = new Packages();
        $data['model'] = $q->find($id);
        $data["title"] = $this->title;

        $this->breadcrumbs[2]['link'] = "#_";
        $this->breadcrumbs[2]['name'] = $this->title;

        $data['breadcrumbs'] = $this->breadcrumbs;

        return view('admin/' . $this->folder . '/show', $data);
    }

    public function deleteStripeProduct()
    {
        \Stripe\Stripe::setApiKey(env("STRIPE_SECRET"));
        $stripe = new \Stripe\StripeClient(env("STRIPE_SECRET"));

        $products = $stripe->products->all();
        foreach ($products as $product) {
            $stripe->products->delete($product['id'], []);
        }
    }
}