<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Casts\Attribute;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Support\Facades\Storage;

/**
 * One row per tenant account — the unit everything in the SaaS layer hangs
 * off of. The platform's own root company (ABIC_E-Learning) is row one,
 * seeded by CreateRootCompanySeeder, and owns whatever data existed before
 * multi-tenancy was introduced.
 */
class Company extends Model
{
    use HasFactory;

    protected $guarded = ['id'];

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

    public function logoPath(): Attribute
    {
        $logo = asset('assets/images/logo-new.png');

        if ($this->logo && Storage::exists($this->logo->src)) {
            $logo = Storage::url($this->logo->src);
        }

        return Attribute::make(
            get: fn() => $logo,
        );
    }

    public function owner(): BelongsTo
    {
        return $this->belongsTo(User::class, 'owner_user_id');
    }

    public function users(): HasMany
    {
        return $this->hasMany(User::class);
    }

    public function domains(): HasMany
    {
        return $this->hasMany(Domain::class);
    }

    public function setting(): HasMany
    {
        return $this->hasMany(Setting::class);
    }

    public function subscriptions(): HasMany
    {
        return $this->hasMany(CompanySubscription::class);
    }

    /**
     * The most recent subscription that hasn't been superseded by a newer
     * one (i.e. not 'cancelled') — deliberately NOT filtered to only
     * 'active' ones. recomputeStatus() needs to find this same row
     * whether or not SyncCompanyStatuses has already flipped its bookkeeping
     * status to 'expired' moments earlier in the same run; the dates on
     * the row are the source of truth, not that flag.
     */
    public function currentSubscription(): ?CompanySubscription
    {
        return $this->subscriptions()->whereIn('status', ['active', 'expired'])->latest('started_at')->first();
    }

    public function isPending(): bool
    {
        return $this->status === 'pending';
    }

    public function isActive(): bool
    {
        return $this->status === 'active';
    }

    public function isSuspended(): bool
    {
        return $this->status === 'suspended';
    }

    public function isExpired(): bool
    {
        return $this->status === 'expired';
    }

    /**
     * True for anything but 'active' — pending, suspended, and expired all
     * mean the same thing to EnforceCompanyReadOnly: log in and look
     * around, but nothing can be written.
     */
    public function isReadOnly(): bool
    {
        return !$this->isActive();
    }

    /**
     * A root-admin override, independent of subscription dates. Stays in
     * effect until reactivate() is called explicitly — the scheduled sync
     * job skips any company in this state rather than silently recomputing
     * it back to 'active' or 'expired' on its own.
     */
    public function suspend(): void
    {
        $this->update(['status' => 'suspended']);
    }

    /**
     * Clears a manual suspension (or just re-checks a pending/expired
     * company) by recomputing from whatever subscription is actually in
     * force — never blindly forces 'active', since reactivating a company
     * whose subscription already ended should land on 'expired', not
     * quietly skip past it.
     */
    public function reactivate(): void
    {
        $this->recomputeStatus();
    }

    /**
     * The single place that decides pending vs. active vs. expired, from
     * the current subscription's own start/end dates. Never touches a
     * 'suspended' company on its own — callers that want to end a
     * suspension go through reactivate() so that's an explicit choice.
     */
    public function recomputeStatus(): void
    {
        $subscription = $this->currentSubscription();

        if (!$subscription) {
            $this->update(['status' => 'pending']);

            return;
        }

        $now = now();

        if ($subscription->started_at && $now->lt($subscription->started_at)) {
            $this->update(['status' => 'pending']);
        } elseif ($subscription->expires_at && $now->gt($subscription->expires_at)) {
            $this->update(['status' => 'expired']);
        } else {
            $this->update(['status' => 'active']);
        }
    }

    /**
     * Bootstrap badge class for whichever of the four statuses this is —
     * kept here rather than duplicated across every view that shows one.
     */
    public function statusBadgeClass(): string
    {
        return match ($this->status) {
            'active' => 'bg-success',
            'pending' => 'bg-info text-dark',
            'suspended' => 'bg-warning text-dark',
            'expired' => 'bg-danger',
            default => 'bg-secondary',
        };
    }
}
