<?php

namespace App\Filament\Widgets;

use App\Models\Initiative;
use App\Models\InitiativeProject;
use App\Models\PerformanceWallet;
use App\Models\ProjectCharter;
use BezhanSalleh\FilamentShield\Traits\HasWidgetShield;
use Filament\Widgets\Concerns\InteractsWithPageFilters;
use Filament\Widgets\StatsOverviewWidget as BaseWidget;
use Filament\Widgets\StatsOverviewWidget\Stat;

class PerformanceDashboardStatsOverview extends BaseWidget
{
    use HasWidgetShield;
    use InteractsWithPageFilters;

    protected static ?int $sort = 1;

    protected static bool $isLazy = false;

    protected static ?string $pollingInterval = null;

    public function getHeading(): string
    {
        return __('pages.projects_dashboard').' - '.__('performance_dashboard.total_wallets');
    }

    protected function getStats(): array
    {
        // Get filter values
        $selectedYear = $this->filters['year'] ?? null;
        $selectedDepartmentId = $this->filters['department_id'] ?? null;
        $selectedWalletId = $this->filters['performance_wallet_id'] ?? null;
        $selectedInitiativeId = $this->filters['initiative_id'] ?? null;

        // Get counts
        $walletsCount = $this->getWalletsCount($selectedDepartmentId, $selectedWalletId);
        $initiativesCount = $this->getInitiativesCount($selectedDepartmentId, $selectedWalletId, $selectedInitiativeId);
        $projectsCount = $this->getProjectsCount($selectedYear, $selectedDepartmentId, $selectedWalletId, $selectedInitiativeId);

        // Calculate average completion percentages
        $avgWalletProgress = $this->getAverageWalletProgress($selectedDepartmentId, $selectedWalletId);
        $avgInitiativeProgress = $this->getAverageInitiativeProgress($selectedDepartmentId, $selectedWalletId, $selectedInitiativeId);
        $avgProjectProgress = $this->getAverageProjectProgress($selectedYear, $selectedDepartmentId, $selectedWalletId, $selectedInitiativeId);

        return [
            Stat::make(__('performance_dashboard.total_wallets'), $walletsCount)
                ->description($selectedWalletId ? __('performance_dashboard.selected_wallet') : __('performance_dashboard.total_wallets_description'))
                ->descriptionIcon('heroicon-m-briefcase')
                ->color('primary'),

            Stat::make(__('performance_dashboard.total_initiatives'), $initiativesCount)
                ->description($this->getInitiativeDescription($selectedDepartmentId, $selectedWalletId, $selectedInitiativeId))
                ->descriptionIcon('heroicon-m-rocket-launch')
                ->color('info'),

            Stat::make(__('performance_dashboard.total_projects'), $projectsCount)
                ->description($this->getProjectDescription($selectedDepartmentId, $selectedWalletId, $selectedInitiativeId))
                ->descriptionIcon('heroicon-m-document-text')
                ->color('success'),

            Stat::make(__('performance_dashboard.avg_wallet_progress'), number_format($avgWalletProgress, 1).'%')
                ->description($selectedWalletId ? __('performance_dashboard.selected_wallet_progress') : __('performance_dashboard.avg_wallet_progress_description'))
                ->descriptionIcon('heroicon-m-chart-pie')
                ->color($this->getProgressColor($avgWalletProgress)),

            Stat::make(__('performance_dashboard.avg_initiative_progress'), number_format($avgInitiativeProgress, 1).'%')
                ->description($this->getInitiativeProgressDescription($selectedDepartmentId, $selectedWalletId, $selectedInitiativeId))
                ->descriptionIcon('heroicon-m-chart-bar')
                ->color($this->getProgressColor($avgInitiativeProgress)),

            Stat::make(__('performance_dashboard.avg_project_progress'), number_format($avgProjectProgress, 1).'%')
                ->description($this->getProjectProgressDescription($selectedDepartmentId, $selectedWalletId, $selectedInitiativeId))
                ->descriptionIcon('heroicon-m-chart-bar-square')
                ->color($this->getProgressColor($avgProjectProgress)),
        ];
    }

    private function getWalletsCount(?int $selectedDepartmentId, ?int $selectedWalletId): int
    {
        if ($selectedWalletId) {
            return 1; // Only the selected wallet
        }

        $query = PerformanceWallet::query();

        if ($selectedDepartmentId) {
            $query->whereHas('performanceCard', function ($q) use ($selectedDepartmentId) {
                $q->where('department_id', $selectedDepartmentId);
            });
        }

        return $query->count();
    }

    private function getInitiativesCount(?int $selectedDepartmentId, ?int $selectedWalletId, ?int $selectedInitiativeId = null): int
    {
        $query = Initiative::query();

        if ($selectedInitiativeId) {
            $query->where('id', $selectedInitiativeId);
        } elseif ($selectedWalletId) {
            $query->where('performance_wallet_id', $selectedWalletId);
        } elseif ($selectedDepartmentId) {
            $query->whereHas('performanceWallet.performanceCard', function ($q) use ($selectedDepartmentId) {
                $q->where('department_id', $selectedDepartmentId);
            });
        }

        return $query->count();
    }

    private function getProjectsCount(?int $selectedYear, ?int $selectedDepartmentId, ?int $selectedWalletId, ?int $selectedInitiativeId = null): int
    {
        $query = InitiativeProject::query();

        // Apply year filter by checking related project charter start_date
        if ($selectedYear) {
            $query->whereHas('projectCharter', function ($q) use ($selectedYear) {
                $q->where(function ($subQuery) use ($selectedYear) {
                    $subQuery->whereYear('start_date', $selectedYear)
                        ->orWhereYear('expected_end_date', $selectedYear);
                });
            });
        }

        if ($selectedInitiativeId) {
            $query->where('initiative_id', $selectedInitiativeId);
        } elseif ($selectedWalletId) {
            $query->whereHas('initiative', function ($q) use ($selectedWalletId) {
                $q->where('performance_wallet_id', $selectedWalletId);
            });
        } elseif ($selectedDepartmentId) {
            $query->whereHas('initiative.performanceWallet.performanceCard', function ($q) use ($selectedDepartmentId) {
                $q->where('department_id', $selectedDepartmentId);
            });
        }

        return $query->count();
    }

    private function getAverageWalletProgress(?int $selectedDepartmentId, ?int $selectedWalletId): float
    {
        $query = PerformanceWallet::with(['performanceCard']);

        if ($selectedWalletId) {
            $query->where('id', $selectedWalletId);
        } elseif ($selectedDepartmentId) {
            $query->whereHas('performanceCard', function ($q) use ($selectedDepartmentId) {
                $q->where('department_id', $selectedDepartmentId);
            });
        }

        $wallets = $query->get();

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

        $totalProgress = 0;
        foreach ($wallets as $wallet) {
            if ($wallet->performanceCard) {
                $totalProgress += $wallet->performanceCard->overall_progress;
            }
        }

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

    private function getAverageInitiativeProgress(?int $selectedDepartmentId, ?int $selectedWalletId, ?int $selectedInitiativeId = null): float
    {
        $query = Initiative::query();

        if ($selectedInitiativeId) {
            $query->where('id', $selectedInitiativeId);
        } elseif ($selectedWalletId) {
            $query->where('performance_wallet_id', $selectedWalletId);
        } elseif ($selectedDepartmentId) {
            $query->whereHas('performanceWallet.performanceCard', function ($q) use ($selectedDepartmentId) {
                $q->where('department_id', $selectedDepartmentId);
            });
        }

        $initiatives = $query->get();

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

        $totalProgress = 0;
        foreach ($initiatives as $initiative) {
            $totalProgress += $initiative->overall_progress;
        }

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

    private function getAverageProjectProgress(?int $selectedYear, ?int $selectedDepartmentId, ?int $selectedWalletId, ?int $selectedInitiativeId = null): float
    {
        $query = InitiativeProject::with('projectCharter');

        // Apply year filter
        if ($selectedYear) {
            $query->whereHas('projectCharter', function ($q) use ($selectedYear) {
                $q->where(function ($subQuery) use ($selectedYear) {
                    $subQuery->whereYear('start_date', $selectedYear)
                        ->orWhereYear('expected_end_date', $selectedYear);
                });
            });
        }

        if ($selectedInitiativeId) {
            $query->where('initiative_id', $selectedInitiativeId);
        } elseif ($selectedWalletId) {
            $query->whereHas('initiative', function ($q) use ($selectedWalletId) {
                $q->where('performance_wallet_id', $selectedWalletId);
            });
        } elseif ($selectedDepartmentId) {
            $query->whereHas('initiative.performanceWallet.performanceCard', function ($q) use ($selectedDepartmentId) {
                $q->where('department_id', $selectedDepartmentId);
            });
        }

        $projects = $query->get();
        $projectsWithCharters = $projects->filter(fn ($project) => $project->projectCharter !== null);

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

        $totalProgress = 0;
        foreach ($projectsWithCharters as $project) {
            $totalProgress += $project->projectCharter->project_progress;
        }

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

    private function getInitiativeDescription(?int $selectedDepartmentId, ?int $selectedWalletId, ?int $selectedInitiativeId): string
    {
        if ($selectedInitiativeId) {
            return __('performance_dashboard.selected_initiative');
        } elseif ($selectedWalletId) {
            return __('performance_dashboard.initiatives_in_wallet');
        } else {
            return __('performance_dashboard.total_initiatives_description');
        }
    }

    private function getProjectDescription(?int $selectedDepartmentId, ?int $selectedWalletId, ?int $selectedInitiativeId): string
    {
        if ($selectedInitiativeId) {
            return __('performance_dashboard.projects_in_initiative');
        } elseif ($selectedWalletId) {
            return __('performance_dashboard.projects_in_wallet');
        } else {
            return __('performance_dashboard.total_projects_description');
        }
    }

    private function getInitiativeProgressDescription(?int $selectedDepartmentId, ?int $selectedWalletId, ?int $selectedInitiativeId): string
    {
        if ($selectedInitiativeId) {
            return __('performance_dashboard.selected_initiative_progress');
        } elseif ($selectedWalletId) {
            return __('performance_dashboard.initiatives_progress_in_wallet');
        } else {
            return __('performance_dashboard.avg_initiative_progress_description');
        }
    }

    private function getProjectProgressDescription(?int $selectedDepartmentId, ?int $selectedWalletId, ?int $selectedInitiativeId): string
    {
        if ($selectedInitiativeId) {
            return __('performance_dashboard.projects_progress_in_initiative');
        } elseif ($selectedWalletId) {
            return __('performance_dashboard.projects_progress_in_wallet');
        } else {
            return __('performance_dashboard.avg_project_progress_description');
        }
    }

    private function getTotalProjectCosts(): float
    {
        return ProjectCharter::sum('total_cost') ?? 0;
    }

    private function getProgressColor(float $progress): string
    {
        return match (true) {
            $progress >= 80 => 'success',
            $progress >= 60 => 'warning',
            $progress >= 40 => 'info',
            default => 'danger',
        };
    }

    public function getColumns(): int
    {
        return 3;
    }
}
