<?php

namespace App\Models;

use App\Services\Billing\DunningSchedule;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;

/**
 * Eine Rückstands-Episode: von der ersten gescheiterten Abbuchung bis zur
 * Begleichung oder zur Sperre.
 */
class DunningCase extends Model
{
    protected $fillable = [
        'subscription_id', 'stripe_invoice_id', 'level',
        'opened_at', 'next_step_at', 'settled_at', 'fee_invoice_ids', 'notified_levels', 'note',
    ];

    protected function casts(): array
    {
        return [
            'level' => 'integer',
            'opened_at' => 'datetime',
            'next_step_at' => 'datetime',
            'settled_at' => 'datetime',
            'fee_invoice_ids' => 'array',
            'notified_levels' => 'array',
        ];
    }

    public function subscription(): BelongsTo
    {
        return $this->belongsTo(Subscription::class);
    }

    /**
     * Die Cloud, um die es in diesem Fall geht — und nur diese.
     *
     * EINE Stelle für die Frage, weil Sperre und Freigabe sie beide stellen und
     * zwei Antworten darauf der Weg wären, auf dem sie auseinanderlaufen: eine
     * Cloud, die abgeschaltet wird und nie zurückkommt.
     *
     * Über die BESTELLUNG, nicht über `subscriptions.instance_id`. Die Spalte
     * gibt es, aber OpenSubscription füllt sie nicht — auf dieser Installation
     * war sie am 31.7.2026 bei drei von fünf Verträgen leer. Eine Sperre, die
     * daran hängt, wäre für die meisten Kunden ein stiller Nulleffekt gewesen:
     * nie abgeschaltet, nie eine Meldung. `order_id` war bei keinem Vertrag und
     * keiner Instanz leer.
     */
    public function instance(): ?Instance
    {
        $subscription = $this->subscription;

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

        return $subscription->instance
            ?? Instance::query()->where('order_id', $subscription->order_id)->first();
    }

    /** Läuft noch — weder beglichen noch von Hand geschlossen. */
    public function isOpen(): bool
    {
        return $this->settled_at === null;
    }

    public function isSuspended(): bool
    {
        return $this->level >= DunningSchedule::SUSPENDED;
    }
}
