<?php

namespace App\Filament\Widgets\Executive;

use App\Models\Attendance;
use App\Models\AttendanceCorrection;
use App\Models\EarlyLeaveRequest;
use App\Models\LateArrivalRequest;
use App\Models\User;
use Carbon\Carbon;
use Filament\Widgets\StatsOverviewWidget as BaseWidget;
use Filament\Widgets\StatsOverviewWidget\Stat;

class ExecutiveStatsWidget extends BaseWidget
{
    protected static ?string $pollingInterval = '60s';

    protected static ?int $sort = 1;

    protected int | string | array $columnSpan = 'full';

    protected function getStats(): array
    {
        $today = now()->toDateString();
        $thisMonth = now()->month;
        $thisYear = now()->year;
        $lastMonth = now()->subMonth();

        // Total active employees
        $totalEmployees = User::where('is_active', true)
            ->whereDoesntHave('roles', fn ($q) => $q->where('name', 'super_admin'))
            ->count();

        // Attendance rate this month
        $totalWorkDays = $this->getTotalWorkDays($thisMonth, $thisYear);
        $expectedAttendances = $totalEmployees * $totalWorkDays;
        $actualAttendances = Attendance::whereMonth('date', $thisMonth)
            ->whereYear('date', $thisYear)
            ->whereIn('status', ['present', 'late', 'wfh', 'business_trip'])
            ->whereHas('user', fn ($q) => $q->whereDoesntHave('roles', fn ($r) => $r->where('name', 'super_admin')))
            ->count();
        
        $attendanceRate = $expectedAttendances > 0 
            ? round(($actualAttendances / $expectedAttendances) * 100, 1) 
            : 0;

        // Punctuality rate (present vs late)
        $presentCount = Attendance::whereMonth('date', $thisMonth)
            ->whereYear('date', $thisYear)
            ->where('status', 'present')
            ->whereHas('user', fn ($q) => $q->whereDoesntHave('roles', fn ($r) => $r->where('name', 'super_admin')))
            ->count();
        
        $lateCount = Attendance::whereMonth('date', $thisMonth)
            ->whereYear('date', $thisYear)
            ->where('status', 'late')
            ->whereHas('user', fn ($q) => $q->whereDoesntHave('roles', fn ($r) => $r->where('name', 'super_admin')))
            ->count();

        $totalCheckIns = $presentCount + $lateCount;
        $punctualityRate = $totalCheckIns > 0 
            ? round(($presentCount / $totalCheckIns) * 100, 1) 
            : 0;

        // Pending requests (all types)
        $pendingCorrections = AttendanceCorrection::where('status', 'pending')->count();
        $pendingLateArrival = LateArrivalRequest::where('status', 'pending')->count();
        $pendingEarlyLeave = EarlyLeaveRequest::where('status', 'pending')->count();
        $totalPendingRequests = $pendingCorrections + $pendingLateArrival + $pendingEarlyLeave;

        // Average work hours this month
        $totalWorkMinutes = Attendance::whereMonth('date', $thisMonth)
            ->whereYear('date', $thisYear)
            ->whereNotNull('work_duration')
            ->whereHas('user', fn ($q) => $q->whereDoesntHave('roles', fn ($r) => $r->where('name', 'super_admin')))
            ->sum('work_duration');

        $attendanceWithWorkDuration = Attendance::whereMonth('date', $thisMonth)
            ->whereYear('date', $thisYear)
            ->whereNotNull('work_duration')
            ->whereHas('user', fn ($q) => $q->whereDoesntHave('roles', fn ($r) => $r->where('name', 'super_admin')))
            ->count();

        $avgWorkHours = $attendanceWithWorkDuration > 0 
            ? round(($totalWorkMinutes / $attendanceWithWorkDuration) / 60, 1) 
            : 0;

        return [
            Stat::make('Total Karyawan Aktif', number_format($totalEmployees))
                ->description('Bulan ini')
                ->descriptionIcon('heroicon-m-users')
                ->color('info')
                ->chart($this->getEmployeeTrend())
                ->extraAttributes([
                    'class' => 'cursor-pointer',
                ]),

            Stat::make('Tingkat Kehadiran', $attendanceRate . '%')
                ->description($actualAttendances . ' dari ' . $expectedAttendances . ' kehadiran yang diharapkan')
                ->descriptionIcon($attendanceRate >= 90 ? 'heroicon-m-check-circle' : 'heroicon-m-exclamation-triangle')
                ->color($attendanceRate >= 90 ? 'success' : ($attendanceRate >= 70 ? 'warning' : 'danger'))
                ->chart($this->getAttendanceRateTrend())
                ->extraAttributes([
                    'class' => 'cursor-pointer',
                ]),

            Stat::make('Tingkat Ketepatan Waktu', $punctualityRate . '%')
                ->description($presentCount . ' tepat waktu, ' . $lateCount . ' terlambat')
                ->descriptionIcon($punctualityRate >= 90 ? 'heroicon-m-clock' : 'heroicon-m-exclamation-triangle')
                ->color($punctualityRate >= 90 ? 'success' : ($punctualityRate >= 80 ? 'warning' : 'danger'))
                ->chart($this->getPunctualityTrend())
                ->extraAttributes([
                    'class' => 'cursor-pointer',
                ]),

            Stat::make('Rata-rata Jam Kerja', $avgWorkHours . ' jam/hari')
                ->description($totalPendingRequests > 0 ? $totalPendingRequests . ' pengajuan menunggu' : 'Semua pengajuan selesai')
                ->descriptionIcon($totalPendingRequests > 0 ? 'heroicon-m-clock' : 'heroicon-m-check-circle')
                ->color($totalPendingRequests > 0 ? 'warning' : 'success')
                ->chart($this->getWorkHoursTrend())
                ->extraAttributes([
                    'class' => 'cursor-pointer',
                ]),
        ];
    }

    private function getEmployeeTrend(): array
    {
        $trend = [];
        for ($i = 6; $i >= 0; $i--) {
            $date = now()->subDays($i)->toDateString();
            $trend[] = User::whereDate('created_at', '<=', $date)
                ->where('is_active', true)
                ->whereDoesntHave('roles', fn ($q) => $q->where('name', 'super_admin'))
                ->count();
        }
        return $trend;
    }

    private function getAttendanceRateTrend(): array
    {
        $trend = [];
        for ($i = 6; $i >= 0; $i--) {
            $date = now()->subDays($i);
            $month = $date->month;
            $year = $date->year;
            
            $totalEmployees = User::where('is_active', true)
                ->whereDate('created_at', '<=', $date->toDateString())
                ->whereDoesntHave('roles', fn ($q) => $q->where('name', 'super_admin'))
                ->count();
            
            $workDays = $this->getTotalWorkDays($month, $year);
            $expected = $totalEmployees * $workDays;
            
            $actual = Attendance::whereMonth('date', $month)
                ->whereYear('date', $year)
                ->whereIn('status', ['present', 'late', 'wfh', 'business_trip'])
                ->whereHas('user', fn ($q) => $q->whereDoesntHave('roles', fn ($r) => $r->where('name', 'super_admin')))
                ->count();
            
            $rate = $expected > 0 ? round(($actual / $expected) * 100, 1) : 0;
            $trend[] = $rate;
        }
        return $trend;
    }

    private function getPunctualityTrend(): array
    {
        $trend = [];
        for ($i = 6; $i >= 0; $i--) {
            $date = now()->subDays($i);
            $present = Attendance::whereDate('date', $date->toDateString())
                ->where('status', 'present')
                ->whereHas('user', fn ($q) => $q->whereDoesntHave('roles', fn ($r) => $r->where('name', 'super_admin')))
                ->count();
            
            $late = Attendance::whereDate('date', $date->toDateString())
                ->where('status', 'late')
                ->whereHas('user', fn ($q) => $q->whereDoesntHave('roles', fn ($r) => $r->where('name', 'super_admin')))
                ->count();
            
            $total = $present + $late;
            $rate = $total > 0 ? round(($present / $total) * 100, 1) : 0;
            $trend[] = $rate;
        }
        return $trend;
    }

    private function getWorkHoursTrend(): array
    {
        $trend = [];
        for ($i = 6; $i >= 0; $i--) {
            $date = now()->subDays($i);
            $totalMinutes = Attendance::whereDate('date', $date->toDateString())
                ->whereNotNull('work_duration')
                ->whereHas('user', fn ($q) => $q->whereDoesntHave('roles', fn ($r) => $r->where('name', 'super_admin')))
                ->sum('work_duration');
            
            $count = Attendance::whereDate('date', $date->toDateString())
                ->whereNotNull('work_duration')
                ->whereHas('user', fn ($q) => $q->whereDoesntHave('roles', fn ($r) => $r->where('name', 'super_admin')))
                ->count();
            
            $avgHours = $count > 0 ? round(($totalMinutes / $count) / 60, 1) : 0;
            $trend[] = $avgHours;
        }
        return $trend;
    }

    private function getTotalWorkDays(int $month, int $year): int
    {
        $start = Carbon::create($year, $month, 1);
        $end = $start->copy()->endOfMonth();
        $workDays = 0;

        while ($start->lte($end)) {
            // Skip weekends (Saturday = 6, Sunday = 0)
            if ($start->dayOfWeek !== Carbon::SATURDAY && $start->dayOfWeek !== Carbon::SUNDAY) {
                $workDays++;
            }
            $start->addDay();
        }

        return $workDays;
    }
}
