<?php

namespace App\Filament\Resources\Learning\Attendances\Pages;

use App\Enums\NotifStyle;
use App\Filament\Resources\Learning\Attendances\AttendanceResource;
use App\Filament\Support\SystemNotification;
use App\Models\Attendance;
use App\Models\ClassSession;
use App\Models\Course;
use App\Models\CourseSchedule;
use App\Models\User;
use App\Settings\GeneralSettings;
use Filament\Forms\Concerns\InteractsWithForms;
use Filament\Forms\Contracts\HasForms;
use Filament\Resources\Pages\Page;
use Filament\Tables\Columns\TextColumn;
use Filament\Tables\Concerns\InteractsWithTable;
use Filament\Tables\Contracts\HasTable;
use Filament\Tables\Filters\SelectFilter;
use Filament\Tables\Table;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Auth;
use Livewire\Attributes\Computed;

class ManageAttendances extends Page implements HasForms, HasTable
{
    use InteractsWithForms, InteractsWithTable;

    protected static string $resource = AttendanceResource::class;

    protected static ?string $title = 'Presensi';

    protected static ?string $navigationLabel = 'Presensi';

    protected string $view = 'filament.resources.learning.attendances.index';

    #[Computed]
    public function heading(): string
    {
        return SystemNotification::getByKey('labels.attendance_section.title');
    }

    #[Computed]
    public function description(): string
    {
        return SystemNotification::getByKey('labels.attendance_section.description');
    }

    #[Computed]
    public function historyHeading(): string
    {
        return SystemNotification::getByKey('labels.attendance_history.title');
    }

    #[Computed]
    public function historyDescription(): string
    {
        return SystemNotification::getByKey('labels.attendance_history.description');
    }

    #[Computed]
    public function emptyHeading(): string
    {
        return SystemNotification::getByKey('labels.empty_attendance.title');
    }

    #[Computed]
    public function emptyDescription(): string
    {
        return SystemNotification::getByKey('labels.empty_attendance.description');
    }

    #[Computed]
    public function sectionIcon(): string
    {
        return SystemNotification::getNotifStyle() === NotifStyle::Cheerful
            ? 'heroicon-o-hand-raised'
            : 'heroicon-o-clipboard-document-check';
    }

    #[Computed]
    public function historyIcon(): string
    {
        return SystemNotification::getNotifStyle() === NotifStyle::Cheerful
            ? 'heroicon-o-clock'
            : 'heroicon-o-archive-box';
    }

    public function getSchedules()
    {
        /** @var User|null $user */
        $user = Auth::user();
        $student = $user->student;

        if (! $student) {
            return collect();
        }

        return ClassSession::query()
            ->where(function ($query) use ($student) {
                $query->whereDate('date', now())
                    ->orWhere(function ($q) use ($student) {
                        $q->whereDate('date', '<', now())
                            ->where('is_sent_to_lecturer', false)
                            ->whereDoesntHave('attendances', fn ($aq) => $aq->where('student_id', $student->id));
                    });
            })
            ->with(['course', 'attendances' => function ($q) use ($student) {
                $q->where('student_id', $student->id);
            }])
            ->orderBy('start_time')
            ->get();
    }

    #[Computed]
    public function scheduleCards()
    {
        return $this->getSchedules()
            ->map(function ($schedule) {
                $attendance = $schedule->attendances?->first();
                $isAttended = $attendance !== null;
                $isSent = $schedule->is_sent_to_lecturer;

                $now = now();
                $startTime = now()->setTimeFrom($schedule->start_time);
                $canAttend = $now->greaterThanOrEqualTo($startTime) && ! $isSent;

                $statusLabel = 'Belum Presensi';
                $statusColor = 'warning';
                $statusIcon = 'heroicon-o-clock';

                if ($isAttended) {
                    $statusLabel = 'Hadir';
                    $statusColor = 'success';
                    $statusIcon = 'heroicon-o-check-circle';
                } elseif ($isSent) {
                    $statusLabel = 'Terkirim';
                    $statusColor = 'danger';
                    $statusIcon = 'heroicon-o-paper-airplane';
                } elseif (! $canAttend) {
                    $statusLabel = 'Belum Dimulai';
                    $statusColor = 'gray';
                    $statusIcon = 'heroicon-o-lock-closed';
                }

                return (object) [
                    'id' => $schedule->id,
                    'course_name' => $schedule->course?->name,
                    'lecturer_name' => $schedule->course?->lecturer ?? 'Belum Ditentukan',
                    'time_range' => $schedule->start_time?->format('H:i').' - '.$schedule->end_time?->format('H:i'),
                    'is_attended' => $isAttended,
                    'is_sent_to_lecturer' => $isSent,
                    'can_attend' => $canAttend && ! $isAttended,
                    'status_label' => $statusLabel,
                    'status_color' => $statusColor,
                    'status_icon' => $statusIcon,
                    'attended_at' => $isAttended ? $attendance?->attended_at?->format('H:i') : null,
                    // Pre-calculated classes
                    'card_classes' => Arr::toCssClasses([
                        'fi-card flex flex-col justify-between rounded-xl border transition duration-200 group relative',
                        'bg-white dark:bg-gray-900 border-gray-200 dark:border-gray-700 shadow-sm hover:shadow-md' => ! $isAttended,
                        'bg-primary-50/30 dark:bg-primary-900/10 border-primary-500 shadow-md ring-1 ring-primary-500' => $isAttended,
                    ]),
                    'title_classes' => Arr::toCssClasses([
                        'text-lg font-bold leading-tight flex items-center gap-2 transition-colors',
                        'text-gray-950 dark:text-white group-hover:text-primary-600 dark:group-hover:text-primary-400' => ! $isAttended,
                        'text-primary-900 dark:text-primary-100' => $isAttended,
                    ]),
                    'lecturer_wrapper_classes' => Arr::toCssClasses([
                        'flex items-center gap-1.5',
                        'text-gray-500 dark:text-gray-400' => ! $isAttended,
                        'text-primary-600 dark:text-primary-400' => $isAttended,
                    ]),
                    'icon_wrapper_classes' => Arr::toCssClasses([
                        'w-8 h-8 rounded-full flex items-center justify-center mr-3 shrink-0 border',
                        'bg-primary-100 dark:bg-primary-900/40 border-primary-200 dark:border-primary-800' => ! $isAttended,
                        'bg-white dark:bg-primary-800 border-primary-300 dark:border-primary-600' => $isAttended,
                    ]),
                    'time_label_classes' => Arr::toCssClasses([
                        'truncate font-medium',
                        'text-gray-100 dark:text-gray-200' => ! $isAttended,
                        'text-primary-900 dark:text-primary-50' => $isAttended,
                    ]),
                    'status_badge_classes' => Arr::toCssClasses([
                        'text-[10px] font-bold px-1.5 py-0.5 rounded ring-1 ring-inset',
                        'bg-success-50 dark:bg-success-500/10 text-success-600 dark:text-success-400 ring-success-600/20' => $isAttended,
                        'bg-warning-50 dark:bg-warning-500/10 text-warning-600 dark:text-warning-400 ring-warning-600/20' => ! $isAttended && $canAttend && ! $isAttended,
                        'bg-gray-50 dark:bg-gray-500/10 text-gray-600 dark:text-gray-400 ring-gray-600/20' => ! $isAttended && ! $canAttend,
                    ]),
                    'footer_classes' => Arr::toCssClasses([
                        'flex items-center justify-end gap-2 p-4 pt-0 rounded-b-xl',
                        'bg-primary-100/30 dark:bg-primary-900/10 pt-4' => $isAttended || ($canAttend && ! $isAttended),
                    ]),
                ];
            });
    }

    public function attend(int $sessionId): void
    {
        /** @var User|null $user */
        $user = Auth::user();
        $student = $user->student;
        if (! $student) {
            return;
        }

        $session = ClassSession::find($sessionId);
        if (! $session) {
            return;
        }

        // Check if already attended
        $existing = Attendance::where('student_id', $student->id)
            ->where('class_session_id', $sessionId)
            ->first();

        if ($existing) {
            SystemNotification::send('attendance_already_recorded', type: 'warning')
                ->send();

            return;
        }

        // Check session status
        if ($session->is_sent_to_lecturer) {
            SystemNotification::send('attendance_closed', type: 'danger')
                ->send();

            return;
        }

        // Check time
        $startTime = $session->start_time;
        if (now()->lessThan($startTime)) {
            SystemNotification::send('attendance_not_started', type: 'warning')
                ->send();

            return;
        }

        // Find schedule for compatibility
        $schedule = CourseSchedule::where('course_id', $session->course_id)
            ->where('day_of_week', $session->date?->dayOfWeekIso)
            ->first();

        Attendance::create([
            'student_id' => $student->id,
            'class_session_id' => $sessionId,
            'course_schedule_id' => $schedule?->id,
            'date' => $session->date?->toDateString(),
            'attended_at' => now(),
        ]);

        SystemNotification::send('attendance_success')
            ->send();
    }

    public function table(Table $table): Table
    {
        /** @var User|null $user */
        $user = Auth::user();

        return $table
            ->query(AttendanceResource::getEloquentQuery())
            ->modifyQueryUsing(fn (Builder $query) => $query->where('student_id', $user->student?->id))
            ->columns([
                TextColumn::make('date')
                    ->label('Tanggal')
                    ->date('l, d F Y')
                    ->sortable()
                    ->description(fn (Attendance $record): string => $record->attended_at?->format('H:i').' ')
                    ->color('gray'),

                TextColumn::make('courseSchedule.course.name')
                    ->label('Mata Kuliah')
                    ->searchable()
                    ->sortable()
                    ->wrap()
                    ->description(fn (Attendance $record): string => $record->courseSchedule?->course?->lecturer ?? 'Belum Ditentukan'),
            ])
            ->defaultSort('date', 'desc')
            ->filters([
                SelectFilter::make('course_id')
                    ->label('Mata Kuliah')
                    ->options(function () {
                        return Course::query()
                            ->where('semester', app(GeneralSettings::class)->current_semester)
                            ->pluck('name', 'id')
                            ->toArray();
                    })
                    ->query(function (Builder $query, array $data) {
                        return $query->when(
                            $data['value'],
                            fn (Builder $query) => $query->whereHas('courseSchedule', fn ($q) => $q->where('course_id', $data['value']))
                        );
                    })
                    ->searchable(),
            ])
            ->emptyStateIcon('heroicon-o-finger-print')
            ->emptyStateDescription('Belum ada riwayat presensi yang tercatat untuk Anda saat ini.')
            ->deferFilters(false)
            ->paginated([25, 50, 100, 'all'])
            ->defaultPaginationPageOption(25);
    }
}
