<?php

namespace App\Filament\Pages;

use App\Models\ActivityRecord;
use App\Models\AttendancePeriod;
use App\Models\AttendanceSummary;
use App\Models\User;
use Carbon\Carbon;
use Filament\Forms\Components\DatePicker;
use Filament\Forms\Components\Select;
use Filament\Forms\Concerns\InteractsWithForms;
use Filament\Forms\Contracts\HasForms;
use Filament\Forms\Form;
use Filament\Pages\Page;
use Filament\Tables\Columns\IconColumn;
use Filament\Tables\Columns\TextColumn;
use Filament\Tables\Concerns\InteractsWithTable;
use Filament\Tables\Contracts\HasTable;
use Filament\Tables\Table;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Collection;

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

    protected static ?string $navigationIcon = 'heroicon-o-clipboard-document-check';

    protected static string $view = 'filament.pages.attendance-verification';

    protected static ?string $navigationLabel = 'Verifikasi Presensi';

    protected static ?string $title = 'Verifikasi Presensi';

    protected static ?string $navigationGroup = 'Monitoring';

    protected static ?int $navigationSort = 100;

    public ?string $selectedDate = null;
    public ?int $selectedUser = null;
    public ?string $selectedPeriod = null;

    public function mount(): void
    {
        $this->selectedDate = now()->format('Y-m-d');
    }

    public function form(Form $form): Form
    {
        return $form
            ->schema([
                DatePicker::make('selectedDate')
                    ->label('Tanggal')
                    ->native(false)
                    ->displayFormat('d M Y')
                    ->live(),
                Select::make('selectedUser')
                    ->label('Pegawai')
                    ->options(
                        User::where('is_active', true)
                            ->whereDoesntHave('roles', fn ($q) => $q->where('name', 'super_admin'))
                            ->pluck('name', 'id')
                    )
                    ->searchable()
                    ->placeholder('Semua Pegawai')
                    ->live(),
                Select::make('selectedPeriod')
                    ->label('Periode')
                    ->options($this->getPeriodOptions())
                    ->placeholder('Pilih Periode')
                    ->live(),
            ])
            ->columns(3);
    }

    protected function getPeriodOptions(): array
    {
        $options = [];
        $current = now();

        for ($i = 0; $i < 12; $i++) {
            $date = $current->copy()->subMonths($i);
            $key = $date->format('Y-m');
            $options[$key] = $date->format('F Y');
        }

        return $options;
    }

    public function table(Table $table): Table
    {
        return $table
            ->query($this->getTableQuery())
            ->columns([
                TextColumn::make('log_date')
                    ->label('Tanggal')
                    ->date('d M Y')
                    ->sortable(),
                TextColumn::make('user_name')
                    ->label('Pegawai')
                    ->searchable(),
                TextColumn::make('action_label')
                    ->label('Aksi')
                    ->badge()
                    ->color(fn (string $state): string => match ($state) {
                        'Check In' => 'success',
                        'Check Out' => 'info',
                        'Dibuat' => 'success',
                        'Diperbarui' => 'warning',
                        'Dihapus' => 'danger',
                        default => 'gray',
                    }),
                TextColumn::make('log_time')
                    ->label('Waktu')
                    ->time('H:i'),
                TextColumn::make('type_label')
                    ->label('Tipe')
                    ->badge()
                    ->color(fn (?string $state): string => match ($state) {
                        'Kantor' => 'primary',
                        'WFH' => 'info',
                        'Dinas' => 'warning',
                        default => 'gray',
                    }),
                TextColumn::make('status_label')
                    ->label('Status')
                    ->badge()
                    ->color(fn (?string $state): string => match ($state) {
                        'Hadir' => 'success',
                        'Terlambat' => 'warning',
                        'Tidak Hadir' => 'danger',
                        default => 'gray',
                    }),
                TextColumn::make('source')
                    ->label('Sumber')
                    ->badge()
                    ->color(fn (string $state): string => match ($state) {
                        'Terverifikasi' => 'success',
                        'Pending' => 'warning',
                        default => 'gray',
                    }),
                TextColumn::make('recorded_at')
                    ->label('Dicatat')
                    ->dateTime('d M Y H:i')
                    ->sortable(),
            ])
            ->defaultSort('log_date', 'desc')
            ->striped()
            ->paginated([10, 25, 50, 100]);
    }

    protected function getTableQuery(): Builder
    {
        // Build combined query from both tables
        $summaryQuery = AttendanceSummary::query()
            ->select([
                'attendance_summaries.id',
                'attendance_summaries.user_id',
                'users.name as user_name',
                'attendance_summaries.log_date',
                'attendance_summaries.log_time',
                'attendance_summaries.action',
                'attendance_summaries.type',
                'attendance_summaries.status',
                'attendance_summaries.transferred_at as recorded_at',
            ])
            ->selectRaw("'summary' as source_type")
            ->join('users', 'attendance_summaries.user_id', '=', 'users.id')
            // Hide super_admin
            ->whereDoesntHave('user.roles', fn ($q) => $q->where('name', 'super_admin'));

        // Apply filters to summary query
        if ($this->selectedDate) {
            $summaryQuery->whereDate('log_date', $this->selectedDate);
        }
        if ($this->selectedUser) {
            $summaryQuery->where('attendance_summaries.user_id', $this->selectedUser);
        }
        if ($this->selectedPeriod) {
            $period = Carbon::createFromFormat('Y-m', $this->selectedPeriod);
            $summaryQuery->whereBetween('log_date', [
                $period->copy()->startOfMonth(),
                $period->copy()->endOfMonth(),
            ]);
        }

        // Get the latest transferred period to determine cutoff
        $latestPeriod = AttendancePeriod::getLatestTransferred();
        $cutoffDate = $latestPeriod
            ? $latestPeriod->period_month->copy()->endOfMonth()
            : null;

        // Build activity records query for non-transferred records
        $activityQuery = ActivityRecord::query()
            ->select([
                'activity_records.id',
                'activity_records.user_id',
                'users.name as user_name',
                'activity_records.target_date as log_date',
            ])
            ->selectRaw("TIME(activity_records.created_at) as log_time")
            ->addSelect([
                'activity_records.action',
            ])
            ->selectRaw("JSON_UNQUOTE(JSON_EXTRACT(new_values, '$.type')) as type")
            ->selectRaw("JSON_UNQUOTE(JSON_EXTRACT(new_values, '$.status')) as status")
            ->addSelect([
                'activity_records.created_at as recorded_at',
            ])
            ->selectRaw("'activity' as source_type")
            ->join('users', 'activity_records.user_id', '=', 'users.id')
            // Hide super_admin
            ->whereDoesntHave('user.roles', fn ($q) => $q->where('name', 'super_admin'))
            ->notTransferred();

        // Only get activity records after the cutoff
        if ($cutoffDate) {
            $activityQuery->where('target_date', '>', $cutoffDate);
        }

        // Apply filters to activity query
        if ($this->selectedDate) {
            $activityQuery->whereDate('target_date', $this->selectedDate);
        }
        if ($this->selectedUser) {
            $activityQuery->where('activity_records.user_id', $this->selectedUser);
        }
        if ($this->selectedPeriod) {
            $period = Carbon::createFromFormat('Y-m', $this->selectedPeriod);
            $activityQuery->whereBetween('target_date', [
                $period->copy()->startOfMonth(),
                $period->copy()->endOfMonth(),
            ]);
        }

        // Use union for combined view - return summary query as base
        // Note: For Filament table, we return the summary query and handle activity separately
        return $summaryQuery;
    }

    public function getCombinedData(): Collection
    {
        // Get verified data (from summaries)
        $summaries = AttendanceSummary::with('user')
            // Hide super_admin
            ->whereHas('user', fn ($q) => $q->whereDoesntHave('roles', fn ($r) => $r->where('name', 'super_admin')))
            ->when($this->selectedDate, fn($q) => $q->whereDate('log_date', $this->selectedDate))
            ->when($this->selectedUser, fn($q) => $q->where('user_id', $this->selectedUser))
            ->when($this->selectedPeriod, function($q) {
                $period = Carbon::createFromFormat('Y-m', $this->selectedPeriod);
                return $q->whereBetween('log_date', [
                    $period->copy()->startOfMonth(),
                    $period->copy()->endOfMonth(),
                ]);
            })
            ->get()
            ->map(function ($item) {
                return [
                    'id' => $item->id,
                    'log_date' => $item->log_date,
                    'user_name' => $item->user->name,
                    'action' => $item->action,
                    'action_label' => $item->action_label,
                    'log_time' => $item->log_time,
                    'type' => $item->type,
                    'type_label' => $this->getTypeLabel($item->type),
                    'status' => $item->status,
                    'status_label' => $this->getStatusLabel($item->status),
                    'source' => 'Terverifikasi',
                    'recorded_at' => $item->transferred_at,
                ];
            });

        // Get pending data (from activity records not transferred)
        $latestPeriod = AttendancePeriod::getLatestTransferred();
        $cutoffDate = $latestPeriod ? $latestPeriod->period_month->copy()->endOfMonth() : null;

        $activities = ActivityRecord::with('user')
            ->notTransferred()
            // Hide super_admin
            ->whereHas('user', fn ($q) => $q->whereDoesntHave('roles', fn ($r) => $r->where('name', 'super_admin')))
            ->when($cutoffDate, fn($q) => $q->where('target_date', '>', $cutoffDate))
            ->when($this->selectedDate, fn($q) => $q->whereDate('target_date', $this->selectedDate))
            ->when($this->selectedUser, fn($q) => $q->where('user_id', $this->selectedUser))
            ->when($this->selectedPeriod, function($q) {
                $period = Carbon::createFromFormat('Y-m', $this->selectedPeriod);
                return $q->whereBetween('target_date', [
                    $period->copy()->startOfMonth(),
                    $period->copy()->endOfMonth(),
                ]);
            })
            ->get()
            ->map(function ($item) {
                return [
                    'id' => 'a_' . $item->id,
                    'log_date' => $item->target_date,
                    'user_name' => $item->user->name,
                    'action' => $item->action,
                    'action_label' => $item->action_label,
                    'log_time' => $item->created_at->format('H:i:s'),
                    'type' => $item->new_values['type'] ?? null,
                    'type_label' => $this->getTypeLabel($item->new_values['type'] ?? null),
                    'status' => $item->new_values['status'] ?? null,
                    'status_label' => $this->getStatusLabel($item->new_values['status'] ?? null),
                    'source' => 'Pending',
                    'recorded_at' => $item->created_at,
                ];
            });

        return $summaries->concat($activities)->sortByDesc('log_date');
    }

    protected function getTypeLabel(?string $type): string
    {
        return match($type) {
            'office' => 'Kantor',
            'wfh' => 'WFH',
            'business_trip' => 'Dinas',
            default => '-',
        };
    }

    protected function getStatusLabel(?string $status): string
    {
        return match($status) {
            'present' => 'Hadir',
            'late' => 'Terlambat',
            'absent' => 'Tidak Hadir',
            'early_leave' => 'Pulang Awal',
            default => '-',
        };
    }

    public function getTransferStatus(): array
    {
        $latestPeriod = AttendancePeriod::getLatestTransferred();
        $pendingCount = ActivityRecord::notTransferred()->count();

        return [
            'latest_period' => $latestPeriod ? $latestPeriod->period_month->format('F Y') : 'Belum ada transfer',
            'latest_transfer_date' => $latestPeriod ? $latestPeriod->transferred_at->format('d M Y H:i') : '-',
            'pending_count' => $pendingCount,
        ];
    }
}
