<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;

/**
 * LeadershipPosition Model
 *
 * Represents a leadership position within an organization's hierarchy.
 * Positions can have parent-child relationships to form the organizational
 * structure.
 *
 * @property int $id
 * @property int $organization_id
 * @property string $title
 * @property string $hierarchy_level
 * @property int|null $parent_position_id
 * @property string|null $description
 * @property \Illuminate\Support\Carbon|null $created_at
 * @property \Illuminate\Support\Carbon|null $updated_at
 * @property \Illuminate\Support\Carbon|null $deleted_at
 */
class LeadershipPosition extends Model
{
    use HasFactory, SoftDeletes;

    /**
     * The hierarchy levels available for leadership positions.
     */
    const HIERARCHY_LEVELS = [
        'bod' => 'Board of Directors',
        'chairman' => 'Chairman',
        'ceo' => 'Chief Executive Officer',
        'c_suite' => 'C-Suite',
        'middle_management' => 'Middle Management',
        'first_line_management' => 'First-Line Management',
        'frontline' => 'Frontline Employees',
    ];

    /**
     * The attributes that are mass assignable.
     *
     * @var array<int, string>
     */
    protected $fillable = [
        'organization_id',
        'title',
        'hierarchy_level',
        'parent_position_id',
        'description',
    ];

    /**
     * The attributes that should be cast.
     *
     * @var array<string, string>
     */
    protected $casts = [
        'created_at' => 'datetime',
        'updated_at' => 'datetime',
    ];

    /**
     * Get the organization that owns the position.
     *
     * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
     */
    public function organization()
    {
        return $this->belongsTo(Organization::class);
    }

    /**
     * Get the parent position (the position this one reports to).
     *
     * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
     */
    public function parentPosition()
    {
        return $this->belongsTo(LeadershipPosition::class, 'parent_position_id');
    }

    /**
     * Get the child positions (positions that report to this one).
     *
     * @return \Illuminate\Database\Eloquent\Relations\HasMany
     */
    public function childPositions()
    {
        return $this->hasMany(LeadershipPosition::class, 'parent_position_id');
    }

    /**
     * Get all assignments for this position.
     *
     * @return \Illuminate\Database\Eloquent\Relations\HasMany
     */
    public function assignments()
    {
        return $this->hasMany(LeadershipAssignment::class, 'leadership_position_id');
    }

    /**
     * Get the current assignment for this position.
     *
     * @return \Illuminate\Database\Eloquent\Relations\HasOne
     */
    public function currentAssignment()
    {
        return $this->hasOne(LeadershipAssignment::class, 'leadership_position_id')
            ->where('is_current', true)
            ->latest();
    }

    /**
     * Get the leadership history records for this position.
     *
     * @return \Illuminate\Database\Eloquent\Relations\HasMany
     */
    public function leadershipHistories()
    {
        return $this->hasMany(LeadershipHistory::class);
    }

    /**
     * Check if this position is an ancestor of another position.
     * Used to prevent circular reporting relationships.
     *
     * @param LeadershipPosition $position
     * @return bool
     */
    public function isAncestorOf(LeadershipPosition $position): bool
    {
        $current = $position;
        while ($current->parent_position_id) {
            if ($current->parent_position_id === $this->id) {
                return true;
            }
            $current = $current->parentPosition;
        }
        return false;
    }

    /**
     * Check if this position would create a circular relationship
     * if set as the parent of another position.
     *
     * @param LeadershipPosition $position
     * @return bool
     */
    public function wouldCreateCircularRelationship(LeadershipPosition $position): bool
    {
        // A position cannot be its own parent
        if ($this->id === $position->id) {
            return true;
        }

        // Check if this position is a descendant of the target position
        return $position->isAncestorOf($this);
    }

    /**
     * Get the hierarchy level label.
     *
     * @return string
     */
    public function getHierarchyLevelLabelAttribute(): string
    {
        return self::HIERARCHY_LEVELS[$this->hierarchy_level] ?? $this->hierarchy_level;
    }

    /**
     * Get the current assignee's name.
     *
     * @return string|null
     */
    public function getCurrentAssigneeNameAttribute(): ?string
    {
        return $this->currentAssignment?->user?->name;
    }

    /**
     * Get the full hierarchy path from root to this position.
     *
     * @return array
     */
    public function getHierarchyPath(): array
    {
        $path = [$this];
        $current = $this;

        while ($current->parent_position_id) {
            $current = $current->parentPosition;
            if ($current) {
                array_unshift($path, $current);
            } else {
                break;
            }
        }

        return $path;
    }

    /**
     * Scope to get positions by hierarchy level.
     *
     * @param \Illuminate\Database\Eloquent\Builder $query
     * @param string $level
     * @return \Illuminate\Database\Eloquent\Builder
     */
    public function scopeByHierarchyLevel($query, string $level)
    {
        return $query->where('hierarchy_level', $level);
    }

    /**
     * Scope to get root positions (positions without parents).
     *
     * @param \Illuminate\Database\Eloquent\Builder $query
     * @return \Illuminate\Database\Eloquent\Builder
     */
    public function scopeRootPositions($query)
    {
        return $query->whereNull('parent_position_id');
    }
}
