<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Support\Str;
use Spatie\Activitylog\Traits\LogsActivity;
use Spatie\Activitylog\LogOptions;

class Company extends Model
{
    use HasFactory, SoftDeletes, LogsActivity;

    protected $fillable = [
        'parent_company_id',
        'name',
        'slug',
        'email',
        'phone',
        'address',
        'logo',
        'industry',
        'website',
        'description',
        'status',
        'established_date',
        'registration_number',
        'tax_id',
        'employee_count',
        'is_holding_company',
        'cash_balance',
        'runway_days',
        'credit_score',
        'total_assets',
        'total_liabilities',
        'revenue',
        'expenses_manual',
        'net_profit',
        'last_health_check',
        'health_status',
    ];

    protected $casts = [
        'established_date' => 'date',
        'last_health_check' => 'date',
        'employee_count' => 'integer',
        'runway_days' => 'integer',
        'credit_score' => 'integer',
        'is_holding_company' => 'boolean',
        'cash_balance' => 'decimal:2',
        'total_assets' => 'decimal:2',
        'total_liabilities' => 'decimal:2',
        'revenue' => 'decimal:2',
        'expenses_manual' => 'decimal:2',
        'net_profit' => 'decimal:2',
    ];

    protected static function boot()
    {
        parent::boot();

        static::creating(function ($company) {
            if (empty($company->slug)) {
                $company->slug = Str::slug($company->name);
            }

            // Ensure only one holding company exists
            if ($company->is_holding_company) {
                $existingHolding = self::where('is_holding_company', true)->first();
                if ($existingHolding) {
                    throw new \Exception('A holding company already exists. Only one holding company is allowed.');
                }
            }
        });

        static::updating(function ($company) {
            // Prevent changing is_holding_company if another holding company exists
            if ($company->isDirty('is_holding_company') && $company->is_holding_company) {
                $existingHolding = self::where('is_holding_company', true)
                    ->where('id', '!=', $company->id)
                    ->first();
                if ($existingHolding) {
                    throw new \Exception('A holding company already exists. Only one holding company is allowed.');
                }
            }
        });
    }

    public function getActivitylogOptions(): LogOptions
    {
        return LogOptions::defaults()
            ->logOnly(['name', 'status', 'email', 'phone'])
            ->logOnlyDirty()
            ->dontSubmitEmptyLogs();
    }

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

    public function departments()
    {
        return $this->hasMany(Department::class);
    }

    public function employees()
    {
        return $this->hasMany(Employee::class);
    }

    public function parentCompany()
    {
        return $this->belongsTo(Company::class, 'parent_company_id');
    }

    public function subsidiaries()
    {
        return $this->hasMany(Company::class, 'parent_company_id');
    }

    public function loansAsLender()
    {
        return $this->hasMany(IntercompanyLoan::class, 'lender_company_id');
    }

    public function loansAsBorrower()
    {
        return $this->hasMany(IntercompanyLoan::class, 'borrower_company_id');
    }

    public function profitSweepRules()
    {
        return $this->hasMany(ProfitSweepRule::class, 'subsidiary_id');
    }

    public function healthMetrics()
    {
        return $this->hasMany(CompanyHealthMetric::class);
    }

    public function complianceAlerts()
    {
        return $this->hasMany(ComplianceAlert::class);
    }

    public function expenses()
    {
        return $this->hasMany(Expense::class);
    }

    public function scopeActive($query)
    {
        return $query->where('status', 'active');
    }

    public function scopeSubsidiaries($query)
    {
        return $query->whereNotNull('parent_company_id');
    }

    public function scopeHoldingCompanies($query)
    {
        return $query->where('is_holding_company', true);
    }

    public function updateEmployeeCount()
    {
        $this->employee_count = $this->employees()->count();
        $this->save();
    }

    public function calculateCreditScore()
    {
        $score = 500;

        if ($this->runway_days > 180) $score += 100;
        elseif ($this->runway_days > 90) $score += 50;
        elseif ($this->runway_days < 30) $score -= 100;

        $debtRatio = $this->total_assets > 0 ? ($this->total_liabilities / $this->total_assets) : 0;
        if ($debtRatio < 0.3) $score += 100;
        elseif ($debtRatio > 0.7) $score -= 100;

        $overdueLoans = $this->loansAsBorrower()->where('status', 'defaulted')->count();
        $score -= ($overdueLoans * 50);

        $this->credit_score = max(300, min(850, $score));
        $this->save();

        return $this->credit_score;
    }

    public function updateHealthStatus()
    {
        if ($this->runway_days === null || $this->cash_balance <= 0) {
            $this->health_status = 'critical';
        } elseif ($this->runway_days < 30) {
            $this->health_status = 'poor';
        } elseif ($this->runway_days < 90) {
            $this->health_status = 'fair';
        } elseif ($this->runway_days < 180) {
            $this->health_status = 'good';
        } else {
            $this->health_status = 'excellent';
        }

        $this->last_health_check = now();
        $this->save();

        return $this->health_status;
    }

    /**
     * Return the system holding company, creating it if it doesn't exist.
     * This centralizes the single holding company so regular companies cannot be marked as holding.
     */
    public static function systemHolding(): self
    {
        $holding = self::where('is_holding_company', true)->first();
        if ($holding) return $holding;

        return self::create([
            'name' => config('app.name') . ' Holding',
            'email' => null,
            'status' => 'active',
            'is_holding_company' => true,
        ]);
    }

    public function getNetWorthAttribute()
    {
        return $this->total_assets - $this->total_liabilities;
    }
}
