<?php

namespace App\Models;

use App\Traits\HasSlugHistory;
use App\Traits\HasLocation;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Support\Facades\DB;

class Operator extends Model
{
    use HasFactory, HasSlugHistory, HasLocation, SoftDeletes;

    /**
     * The attributes that are mass assignable.
     *
     * @var array<string>
     */
    protected $fillable = [
        'name',
        'slug',
        'website',
        'description',
        'industry_sector',
        'founded_year',
        'employee_count',
        'annual_revenue',
        'market_cap',
        'stock_symbol',
        'headquarters_location',
        'geographic_presence',
        'company_type',
        'parent_company_id',
        'is_public',
        'is_active',
        'total_parks',
        'total_rides_manufactured',
        'total_rides_designed',
    ];

    /**
     * The attributes that should be cast.
     *
     * @var array<string, string>
     */
    protected $casts = [
        'founded_year' => 'integer',
        'employee_count' => 'integer',
        'annual_revenue' => 'decimal:2',
        'market_cap' => 'decimal:2',
        'is_public' => 'boolean',
        'is_active' => 'boolean',
        'total_parks' => 'integer',
        'total_rides_manufactured' => 'integer',
        'total_rides_designed' => 'integer',
    ];

    /**
     * Get the parks operated by this operator.
     */
    public function parks(): HasMany
    {
        return $this->hasMany(Park::class);
    }

    /**
     * Get the rides manufactured by this operator.
     */
    public function manufactured_rides(): HasMany
    {
        return $this->hasMany(Ride::class, 'manufacturer_id');
    }

    /**
     * Get the rides designed by this operator.
     */
    public function designed_rides(): HasMany
    {
        return $this->hasMany(Ride::class, 'designer_id');
    }

    /**
     * Get the parent company if this is a subsidiary.
     */
    public function parent_company(): BelongsTo
    {
        return $this->belongsTo(Operator::class, 'parent_company_id');
    }

    /**
     * Get the subsidiary companies.
     */
    public function subsidiaries(): HasMany
    {
        return $this->hasMany(Operator::class, 'parent_company_id');
    }

    /**
     * Update comprehensive statistics.
     */
    public function updateStatistics(): void
    {
        $this->total_parks = $this->parks()->count();
        $this->total_rides_manufactured = $this->manufactured_rides()->count();
        $this->total_rides_designed = $this->designed_rides()->count();
        $this->save();
    }

    /**
     * Get the operator's display name with role indicators.
     */
    public function getDisplayNameAttribute(): string
    {
        $roles = [];
        if ($this->total_parks > 0) $roles[] = 'Operator';
        if ($this->total_rides_manufactured > 0) $roles[] = 'Manufacturer';
        if ($this->total_rides_designed > 0) $roles[] = 'Designer';
        
        $roleText = empty($roles) ? '' : ' (' . implode(', ', $roles) . ')';
        return $this->name . $roleText;
    }

    /**
     * Get formatted website URL (ensures proper URL format).
     */
    public function getWebsiteUrlAttribute(): string
    {
        if (!$this->website) {
            return '';
        }

        $website = $this->website;
        if (!str_starts_with($website, 'http://') && !str_starts_with($website, 'https://')) {
            $website = 'https://' . $website;
        }

        return $website;
    }

    /**
     * Get company size category based on employee count.
     */
    public function getCompanySizeCategoryAttribute(): string
    {
        if (!$this->employee_count) return 'unknown';
        
        return match (true) {
            $this->employee_count <= 100 => 'small',
            $this->employee_count <= 1000 => 'medium',
            $this->employee_count <= 10000 => 'large',
            default => 'enterprise'
        };
    }

    /**
     * Get geographic presence level.
     */
    public function getGeographicPresenceLevelAttribute(): string
    {
        $countries = $this->parks()
            ->join('locations', 'parks.location_id', '=', 'locations.id')
            ->distinct('locations.country')
            ->count('locations.country');

        return match (true) {
            $countries <= 1 => 'regional',
            $countries <= 3 => 'national',
            default => 'international'
        };
    }

    /**
     * Get market influence score.
     */
    public function getMarketInfluenceScoreAttribute(): float
    {
        $score = 0;
        
        // Parks operated (40% weight)
        $score += min($this->total_parks * 10, 40);
        
        // Rides manufactured (30% weight)
        $score += min($this->total_rides_manufactured * 2, 30);
        
        // Revenue influence (20% weight)
        if ($this->annual_revenue) {
            $score += min(($this->annual_revenue / 1000000000) * 10, 20);
        }
        
        // Geographic presence (10% weight)
        $countries = $this->parks()
            ->join('locations', 'parks.location_id', '=', 'locations.id')
            ->distinct('locations.country')
            ->count('locations.country');
        $score += min($countries * 2, 10);
        
        return round($score, 1);
    }

    /**
     * Scope a query to only include active operators.
     */
    public function scopeActive($query)
    {
        return $query->where('is_active', true);
    }

    /**
     * Scope a query to only include park operators.
     */
    public function scopeParkOperators($query)
    {
        return $query->whereHas('parks');
    }

    /**
     * Scope a query to only include ride manufacturers.
     */
    public function scopeManufacturers($query)
    {
        return $query->whereHas('manufactured_rides');
    }

    /**
     * Scope a query to only include ride designers.
     */
    public function scopeDesigners($query)
    {
        return $query->whereHas('designed_rides');
    }

    /**
     * Scope a query to only include major operators (with multiple parks).
     */
    public function scopeMajorOperators($query, int $minParks = 3)
    {
        return $query->where('total_parks', '>=', $minParks);
    }

    /**
     * Scope a query to filter by industry sector.
     */
    public function scopeIndustrySector($query, string $sector)
    {
        return $query->where('industry_sector', $sector);
    }

    /**
     * Scope a query to filter by company size.
     */
    public function scopeCompanySize($query, string $size)
    {
        $ranges = [
            'small' => [1, 100],
            'medium' => [101, 1000],
            'large' => [1001, 10000],
            'enterprise' => [10001, PHP_INT_MAX]
        ];

        if (isset($ranges[$size])) {
            return $query->whereBetween('employee_count', $ranges[$size]);
        }

        return $query;
    }

    /**
     * Scope a query to filter by founded year range.
     */
    public function scopeFoundedBetween($query, int $startYear, int $endYear)
    {
        return $query->whereBetween('founded_year', [$startYear, $endYear]);
    }

    /**
     * Scope a query to filter by revenue range.
     */
    public function scopeRevenueBetween($query, float $minRevenue, float $maxRevenue)
    {
        return $query->whereBetween('annual_revenue', [$minRevenue, $maxRevenue]);
    }

    /**
     * Scope a query to filter by dual roles.
     */
    public function scopeDualRole($query, array $roles)
    {
        return $query->where(function ($q) use ($roles) {
            if (in_array('park_operator', $roles)) {
                $q->orWhereHas('parks');
            }
            if (in_array('ride_manufacturer', $roles)) {
                $q->orWhereHas('manufactured_rides');
            }
            if (in_array('ride_designer', $roles)) {
                $q->orWhereHas('designed_rides');
            }
        });
    }

    /**
     * Scope a query for optimized loading with counts.
     */
    public function scopeWithCounts($query)
    {
        return $query->withCount(['parks', 'manufactured_rides', 'designed_rides']);
    }

    /**
     * Get the route key for the model.
     */
    public function getRouteKeyName(): string
    {
        return 'slug';
    }
}