<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Relations\HasMany;
use App\Models\Currency;
use App\Models\User;

class Company extends Model
{
    protected $table = 'companies';

    /**
     * Subscription / access-control fields — assign only via forceFill() in trusted admin code.
     *
     * @var list<string>
     */
    public const PRIVILEGED_ATTRIBUTES = [
        'status',
        'subscription_plan_id',
        'licence_expire_on',
        'trial_ends_at',
        'package_type',
        'total_users',
        'is_initialized',
        'admin_id',
    ];

    protected $fillable = [
        'name',
        'short_name',
        'logo',
        'email',
        'phone',
        'website',
        'address',
        'gstin',
        'timezone',
    ];

    protected $casts = [
        'trial_ends_at' => 'datetime',
        'licence_expire_on' => 'date',
        'is_initialized' => 'boolean',
    ];

    public function users(): HasMany
    {
        return $this->hasMany(User::class, 'company_id');
    }

    public function subscriptionPlan(): \Illuminate\Database\Eloquent\Relations\BelongsTo
    {
        return $this->belongsTo(SubscriptionPlan::class, 'subscription_plan_id');
    }

    public function subscriptionPayments(): \Illuminate\Database\Eloquent\Relations\HasMany
    {
        return $this->hasMany(SubscriptionPayment::class);
    }

    public function subscriptionRequests(): \Illuminate\Database\Eloquent\Relations\HasMany
    {
        return $this->hasMany(SubscriptionRequest::class);
    }

    public function currency()
    {
        return $this->belongsTo(Currency::class);
    }

    /**
     * Access gate: company status only (auto-suspend sets status=suspended).
     */
    public function isSubscriptionActive(): bool
    {
        return $this->isAccessAllowed();
    }

    public function isAccessAllowed(): bool
    {
        return $this->status === 'active';
    }

    public function isLicenceExpired(): bool
    {
        return $this->licence_expire_on !== null && $this->licence_expire_on->isPast();
    }

    public function daysUntilLicenceExpiry(): ?int
    {
        if (! $this->licence_expire_on) {
            return null;
        }

        return (int) now()->startOfDay()->diffInDays($this->licence_expire_on->copy()->startOfDay(), false);
    }

    public function isInExpiryWarningWindow(): bool
    {
        if (! $this->licence_expire_on) {
            return false;
        }

        $days = $this->daysUntilLicenceExpiry();

        return $days !== null && $days <= 30;
    }

    public function employeeSeatLimit(): ?int
    {
        $plan = $this->subscriptionPlan;
        if (! $plan) {
            return $this->defaultFreePlanSeatLimit();
        }

        if ($plan->is_custom) {
            return $plan->employee_limit;
        }

        return $plan->employee_limit;
    }

    /**
     * When a company has no plan FK, apply the default Free plan seat cap (never treat as unlimited by accident).
     */
    protected function defaultFreePlanSeatLimit(): ?int
    {
        $free = SubscriptionPlan::query()
            ->where('default', 'yes')
            ->orderBy('id')
            ->first();

        if (! $free) {
            $free = SubscriptionPlan::query()
                ->whereRaw('LOWER(name) = ?', ['free'])
                ->orderBy('id')
                ->first();
        }

        return $free?->employee_limit;
    }

    public function activeEmployeeCount(): int
    {
        return User::query()
            ->where('company_id', $this->id)
            ->forTenantDirectory()
            ->where('status', User::STATUS_ACTIVE)
            ->count();
    }

    public function canAddEmployees(int $count = 1): bool
    {
        $limit = $this->employeeSeatLimit();
        if ($limit === null) {
            return true;
        }

        return ($this->activeEmployeeCount() + $count) <= $limit;
    }

    /**
     * All paid/free plans include the full product. Feature rows are legacy only.
     */
    public function hasPlanFeature(string $featureKey): bool
    {
        return true;
    }

    /**
     * Resolve a company by public short_name (case-insensitive).
     */
    public static function findByShortName(?string $shortName): ?self
    {
        $key = strtolower(trim((string) $shortName));
        if ($key === '') {
            return null;
        }

        return static::query()
            ->whereRaw('LOWER(short_name) = ?', [$key])
            ->first();
    }

    /**
     * Normalize short_name for storage (lowercase trimmed).
     */
    public static function normalizeShortName(?string $shortName): ?string
    {
        $key = strtolower(trim((string) $shortName));

        return $key === '' ? null : $key;
    }
}
