<?php

namespace App\Models;

use App\Scopes\ViewPermissionScope;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Support\Facades\Auth;

class Initiative extends Model
{
    use HasFactory, \Znck\Eloquent\Traits\BelongsToThrough;

    protected $fillable = [
        'name',
        'start_date',
        'expected_end_date',
        'description',
        'expected_cost',
        'emergency_reserve',
        'performance_wallet_id',
        'created_by',
    ];

    protected $casts = [
        'start_date' => 'date',
        'expected_end_date' => 'date',
        'expected_cost' => 'decimal:2',
        'emergency_reserve' => 'decimal:2',
    ];

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

        static::creating(function ($model) {
            if (Auth::check()) {
                $model->created_by = Auth::id();
            }
        });
    }

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

    public function products(): BelongsToMany
    {
        return $this->belongsToMany(SekayaValue::class, 'initiative_products');
    }

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

    public function performanceCard(): \Znck\Eloquent\Relations\BelongsToThrough
    {
        return $this->belongsToThrough(PerformanceCard::class, PerformanceWallet::class);
    }

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

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

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

    /**
     * Get the overall progress of all projects in this initiative
     * Calculates weighted average based on project weights and their progress
     */
    public function getOverallProgressAttribute(): float
    {
        $projects = $this->projects()->with('projectCharter')->get();

        if ($projects->isEmpty()) {
            return 0;
        }

        $totalWeightedProgress = 0;
        $totalWeight = 0;

        foreach ($projects as $project) {
            if ($project->projectCharter && $project->weight > 0) {
                $projectProgress = $project->projectCharter->project_progress;
                $totalWeightedProgress += ($projectProgress * $project->weight);
                $totalWeight += $project->weight;
            }
        }

        // If no weights are assigned, return simple average
        if ($totalWeight == 0) {
            $projectsWithCharters = $projects->filter(function ($project) {
                return $project->projectCharter !== null;
            });

            if ($projectsWithCharters->isEmpty()) {
                return 0;
            }

            $totalProgress = $projectsWithCharters->sum(function ($project) {
                return $project->projectCharter->project_progress;
            });

            return $totalProgress / $projectsWithCharters->count();
        }

        return $totalWeightedProgress / $totalWeight;
    }

    /**
     * Get the estimated budget which is the sum of expected cost and emergency reserve
     */
    public function getEstimatedBudgetAttribute(): float
    {
        return ($this->expected_cost ?? 0) + ($this->emergency_reserve ?? 0);
    }

    /**
     * Get the total estimated cost of all related project charters
     */
    public function getTotalProjectChartersEstimatedCostAttribute(): float
    {
        return $this->projects()
            ->with('projectCharter')
            ->get()
            ->sum(function ($project) {
                return $project->projectCharter->estimated_cost ?? 0;
            });
    }

    /**
     * Get the actual cost based on all approved exchange requests for this initiative
     */
    public function getActualCostAttribute(): float
    {
        return $this->projects()
            ->with(['projectCharter.deliverables.completionReports.exchangeRequest'])
            ->get()
            ->sum(function ($project) {
                if (! $project->projectCharter) {
                    return 0;
                }

                return $project->projectCharter->deliverables
                    ->pluck('completionReports')
                    ->flatten()
                    ->pluck('exchangeRequest')
                    ->filter(function ($exchangeRequest) {
                        return $exchangeRequest && $exchangeRequest->status === \App\Models\ExchangeRequest::STATUS_APPROVED;
                    })
                    ->sum(function ($exchangeRequest) {
                        return $exchangeRequest->completionReport->value ?? 0;
                    });
            });
    }

    /**
     * Get the reserve status (always 0 as requested)
     */
    public function getReserveStatusAttribute(): float
    {
        return 0;
    }

    /**
     * Get the total expenses (actual cost + reserve status)
     */
    public function getTotalExpensesAttribute(): float
    {
        return $this->actual_cost + $this->reserve_status;
    }

    /**
     * Get the financial completion percentage based on actual cost vs expected cost
     */
    public function getFinancialCompletionPercentageAttribute(): float
    {
        if (! $this->expected_cost || $this->expected_cost <= 0) {
            return 0;
        }

        return min(100, ($this->actual_cost / $this->expected_cost) * 100);
    }

    // The view permission is now enforced globally via ViewPermissionScope.
}
