<?php

namespace App\Models;

use App\Enums\PlanTier;
use Database\Factories\PlanFactory;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\Cache;

class Plan extends Model
{
    /** @use HasFactory<PlanFactory> */
    use HasFactory;

    protected $fillable = [
        'name',
        'stripe_price_id_monthly',
        'stripe_price_id_annual',
        'max_fuel_types',
        'email_enabled',
        'email_frequency',
        'push_enabled',
        'push_frequency',
        'whatsapp_enabled',
        'whatsapp_daily_limit',
        'whatsapp_scheduled_updates',
        'sms_enabled',
        'sms_daily_limit',
        'ai_predictions',
        'price_threshold',
        'score_alerts',
        'active',
    ];

    /**
     * Resolve the active plan for a user.
     * Falls back to the free plan when no active Cashier subscription exists.
     */
    public static function resolveForUser(User $user): self
    {
        $cache = Cache::supportsTags() ? Cache::tags(['plans']) : Cache::store();

        $planId = $cache->remember(
            "plan_for_user_{$user->id}",
            3600,
            function () use ($user): ?int {
                $priceId = null;

                if (method_exists($user, 'subscriptions')) {
                    $subscription = $user->subscriptions()->active()->first();
                    $priceId = $subscription?->stripe_price ?? null;
                }

                if ($priceId) {
                    $plan = static::where(fn ($q) => $q
                        ->where('stripe_price_id_monthly', $priceId)
                        ->orWhere('stripe_price_id_annual', $priceId))
                        ->where('active', true)
                        ->first();

                    if ($plan) {
                        return $plan->id;
                    }
                }

                return static::where('name', PlanTier::Free->value)->value('id');
            }
        );

        return static::findOrFail($planId);
    }

    /**
     * Resolve the active subscription cadence for a user.
     * Returns 'monthly' | 'annual', or null if the user has no paid subscription.
     */
    public static function resolveCadenceForUser(User $user): ?string
    {
        $cache = Cache::supportsTags() ? Cache::tags(['plans']) : Cache::store();

        return $cache->remember(
            "plan_cadence_for_user_{$user->id}",
            3600,
            function () use ($user): ?string {
                if (! method_exists($user, 'subscriptions')) {
                    return null;
                }

                $priceId = $user->subscriptions()->active()->value('stripe_price');

                if ($priceId === null) {
                    return null;
                }

                $plan = static::where('stripe_price_id_monthly', $priceId)
                    ->orWhere('stripe_price_id_annual', $priceId)
                    ->first();

                if ($plan === null) {
                    return null;
                }

                if ($plan->stripe_price_id_monthly === $priceId) {
                    return 'monthly';
                }

                if ($plan->stripe_price_id_annual === $priceId) {
                    return 'annual';
                }

                return null;
            }
        );
    }

    protected static function booted(): void
    {
        static::saved(function (): void {
            if (Cache::supportsTags()) {
                Cache::tags(['plans'])->flush();
            }
        });
    }

    protected function casts(): array
    {
        return [
            'max_fuel_types' => 'integer',
            'email_enabled' => 'boolean',
            'push_enabled' => 'boolean',
            'whatsapp_enabled' => 'boolean',
            'whatsapp_daily_limit' => 'integer',
            'whatsapp_scheduled_updates' => 'integer',
            'sms_enabled' => 'boolean',
            'sms_daily_limit' => 'integer',
            'ai_predictions' => 'boolean',
            'price_threshold' => 'boolean',
            'score_alerts' => 'boolean',
            'active' => 'boolean',
        ];
    }

    /** User-facing display label for this plan (e.g. basic → "Daily"). */
    public function displayName(): string
    {
        $tier = PlanTier::tryFrom((string) $this->name) ?? PlanTier::Free;

        return $tier->label();
    }
}
