<?php

namespace App\Livewire\Dashboard;

use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Date;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use App\Models\UsageLog;
use Exception;
use Illuminate\Http\Request;
use Livewire\Component;
use Stripe\StripeClient;

class Dashboard extends Component
{
    public $message;

    public $usageLog;

    public $subscription;

    public $plans;

    public $showStripeBilling = false;

    public function paymentStatus(Request $request)
    {
        $status = $request->route('status');
        $request->fullUrl();
        if ($status == 'success') {
            $this->syncSubscription();
            return to_route('dashboard')->with('status', 'success');
        }
        if ($status == 'cancel') {
            return to_route('dashboard')->with('status', 'cancel');
        }
    }

    private function checkForSubscriptionStatus(): bool
    {
        $redirect = false;
        $user = auth()->user();
        $userId = $user->id;
        if ($user->subscribed()) {
            $subscription = $user->subscriptions()
                // ->where(['stripe_status' => 'active'])
                ->orderByDesc('updated_at')
                ->first();
            if ($subscription !== null) {
                $subscriptionId = $subscription->stripe_id;
                $cacheKey = "stripe_check_executed_user_{$userId}_{$subscriptionId}";
                if (! Cache::has($cacheKey)) {
                    try {
                        $stripe = new StripeClient(config('cashier.secret'));
                        $subscriptionData = $stripe->subscriptions->retrieve($subscriptionId, []);
                        if ($subscriptionData !== null) {
                            $items = $subscriptionData->items->data[0];
                            if ($items !== null) {
                                $cancel_at_period_end = $subscriptionData->cancel_at_period_end;
                                $ends_at = $items->current_period_end;
                                $cancel_at = $subscriptionData->cancel_at;
                                $canceled_at = $subscriptionData->canceled_at;
                                $status = $subscriptionData->status;
                                if ($cancel_at_period_end) {
                                    $final_ends_at = Date::createFromTimestamp($cancel_at)->toDateTimeString();
                                } elseif ($cancel_at === null && $canceled_at !== null && $status === 'canceled' && $cancel_at_period_end === false) {
                                    // $final_ends_at = Carbon::createFromTimestamp($canceled_at)->toDateTimeString();
                                    $final_ends_at = Date::now()->subDays(2)->toDateTimeString();
                                    $redirect = true;
                                } elseif ($status === 'active' && $cancel_at !== null) {
                                    $final_ends_at = Date::createFromTimestamp($cancel_at)->toDateTimeString();
                                } else {
                                    $final_ends_at = null;
                                }

                                DB::table('subscriptions')
                                    ->where('stripe_id', $subscriptionId)
                                    ->update([
                                        'stripe_status' => $status,
                                        'ends_at' => $final_ends_at,
                                        'updated_at' => Date::now()->toDateTimeString(),
                                    ]);
                            }
                        }
                        Cache::put($cacheKey, true, now()->addMinute());
                    } catch (Exception $exception) {
                        Log::error($exception->getMessage());
                    }
                }

            }
        }

        return $redirect;
    }

    private function syncSubscription(): void
    {
        $user = auth()->user();
        $userId = $user->id;
        if ($user->hasStripeId()) {
            $stripe = new StripeClient(config('cashier.secret'));
            $subscriptions = $stripe->subscriptions->all(['limit' => 1]);
            if (! $subscriptions->isEmpty()) {
                $data = $subscriptions->data[0];
                $items = $subscriptions->data[0]->items->data[0];

                $type = 'default';
                $subscriptionId = $items->subscription;
                $status = $data->status;
                $cancel_at_period_end = $data->cancel_at_period_end;
                $quantity = $items->quantity;
                $stripe_price = $items->price->id;
                $stripe_product = $items->price->product;
                $ends_at = $items->current_period_end;
                $subscriptionItemId = $items->id;
                $final_ends_at = $cancel_at_period_end ? Date::createFromTimestamp($ends_at)->toDateTimeString() : null;

                try {
                    if ($status === 'active') {
                        $subscriptionsTable = DB::table('subscriptions')->where(['stripe_id' => $subscriptionId])->first();
                        if ($subscriptionsTable == null) {
                            $subscriptionsTable = DB::table('subscriptions')->insert([
                                'user_id' => $userId,
                                'type' => $type,
                                'stripe_id' => $subscriptionId,
                                'stripe_status' => $status,
                                'stripe_price' => $stripe_price,
                                'quantity' => $quantity,
                                'ends_at' => $final_ends_at,
                                'created_at' => Date::now()->toDateTimeString(),
                                'updated_at' => Date::now()->toDateTimeString(),
                            ]);

                            $subscriptionsTable = DB::table('subscriptions')->where(['stripe_id' => $subscriptionId])->first();
                            $subID = $subscriptionsTable->id;
                            $subscriptionItemsTable = DB::table('subscription_items')->where(['stripe_id' => $subscriptionItemId])->first();
                            if ($subscriptionItemsTable == null) {
                                $subscriptionItemsTable = DB::table('subscription_items')->insert([
                                    'subscription_id' => $subID,
                                    'stripe_id' => $subscriptionItemId,
                                    'stripe_product' => $stripe_product,
                                    'stripe_price' => $stripe_price,
                                    'quantity' => $quantity,
                                    'created_at' => Date::now()->toDateTimeString(),
                                    'updated_at' => Date::now()->toDateTimeString(),
                                ]);
                            }
                        }
                    }
                } catch (Exception $exception) {
                    Log::error($exception->getMessage());
                }
            }
        }
    }

    public function mount(Request $request)
    {
        if ($this->checkForSubscriptionStatus()) {
            return to_route('dashboard');
        }
        try {
            $status = $request->session()->get('status');
            if (isset($status)) {
                if ($status == 'success') {
                    $this->message = ['type' => 'success', 'message' => 'Order completed successfully.'];
                } else {
                    $this->message = ['type' => 'error', 'message' => 'Order cancelled.'];
                }
                $request->session()->forget('status');
            }
        } catch (Exception) {

        }

        $plans = config('app.plans', []);
        if (! empty($plans) && isset($plans[0]) && is_array($plans[0]) && isset($plans[0]['product_id']) && auth()->user()->subscribedToProduct($plans[0]['product_id'])) {
            try {
                $result = auth()->user()->subscriptions()->where(['stripe_status' => 'active'])->orderByDesc('updated_at')->first();
                if ($result != null) {
                    $userPriceID = $result['items'][0]['stripe_price'];
                    $subscriptionEnd = $result['ends_at'];

                    $planName = null;

                    foreach (config('app.plans') as $plan) {
                        if ($plan['pricing_id'] === $userPriceID) {
                            $planName = $plan['name'];
                            $this->showStripeBilling = $plan['accept_stripe'];
                            break;
                        }
                    }
                    $this->subscription['name'] = $planName;
                    $this->subscription['ends_at'] = $subscriptionEnd;
                }

            } catch (Exception $e) {
                Log::error($e->getMessage());
            }
        }

        $usageLog = UsageLog::query()->where('user_id', auth()->user()->id)->first();
        $this->usageLog = [
            'emails_created_count' => $usageLog->emails_created_count ?? 0,
            'emails_received_count' => $usageLog->emails_received_count ?? 0,
        ];
    }

    public function render()
    {
        return view('livewire.dashboard.dashboard')->layout('components.layouts.dashboard')->with('message', $this->message);
    }
}
