<?php

namespace App\Filament\Imports;

use App\Models\Activity;
use App\Models\User;
use App\Models\Attendance;
use Filament\Actions\Imports\ImportColumn;
use Filament\Actions\Imports\Importer;
use Filament\Actions\Imports\Models\Import;
use Carbon\Carbon;

class ActivityImporter extends Importer
{
    protected static ?string $model = Activity::class;

    public static function getColumns(): array
    {
        // Format kolom persis seperti file Excel yang ditunjukkan user:
        // NO | TANGGAL | Hari | WAKTU | URAIAN | OUTPUT | KETERANGAN
        return [
            ImportColumn::make('no')
                ->label('NO')
                ->rules(['nullable']),

            ImportColumn::make('tanggal')
                ->label('TANGGAL')
                ->requiredMapping()
                ->rules(['required'])
                ->example('03-Nov-25'),

            ImportColumn::make('hari')
                ->label('Hari')
                ->rules(['nullable', 'string'])
                ->example('Monday'),

            ImportColumn::make('waktu')
                ->label('WAKTU')
                ->requiredMapping()
                ->rules(['required'])
                ->example('07:33 - 16:47'),

            ImportColumn::make('uraian')
                ->label('URAIAN')
                ->requiredMapping()
                ->rules(['required', 'string'])
                ->example('Memperbaiki dokumen hasil stress test...'),

            ImportColumn::make('output')
                ->label('OUTPUT')
                ->rules(['nullable', 'string'])
                ->example('Dokumen hasil load, stress dan spike test...'),

            ImportColumn::make('keterangan')
                ->label('KETERANGAN')
                ->rules(['nullable', 'string'])
                ->example('BPKP Pusat - HADIR'),

            // Optional columns untuk identifikasi user
            ImportColumn::make('nama')
                ->label('NAMA')
                ->rules(['nullable', 'string'])
                ->example('M. Syahril Fadli'),

            ImportColumn::make('nip')
                ->label('NIP')
                ->rules(['nullable', 'string'])
                ->example('12345'),
        ];
    }

    public function resolveRecord(): ?Activity
    {
        $data = $this->data;

        // Find user by name or NIP, or use first user if not specified
        $user = $this->findUser($data);
        if (!$user) {
            return null; // Skip if user not found
        }

        // Skip if user is super_admin
        if ($user->hasRole('super_admin')) {
            return null;
        }

        // Parse date from TANGGAL column
        $date = $this->parseDate($data['tanggal'] ?? null);
        if (!$date) {
            return null; // Skip if date invalid
        }

        // Parse WAKTU (format: "07:33 - 16:47")
        [$startTime, $endTime] = $this->parseWaktu($data['waktu'] ?? null, $date);

        // Find related attendance for the date
        $attendance = Attendance::where('user_id', $user->id)
            ->whereDate('date', $date)
            ->first();

        // Create or update activity
        return Activity::updateOrCreate(
            [
                'user_id' => $user->id,
                'date' => $date,
                'start_time' => $startTime,
            ],
            [
                'attendance_id' => $attendance?->id,
                'end_time' => $endTime,
                'activity' => $data['uraian'] ?? '',
                'output' => $data['output'] ?? null,
                'notes' => $data['keterangan'] ?? null,
            ]
        );
    }

    protected function findUser(array $data): ?User
    {
        // Try to find by NIP first
        if (!empty($data['nip'])) {
            $user = User::where('employee_id', trim($data['nip']))->first();
            if ($user) {
                return $user;
            }
        }

        // Try to find by name
        if (!empty($data['nama'])) {
            $user = User::where('name', 'like', '%' . trim($data['nama']) . '%')->first();
            if ($user) {
                return $user;
            }
        }

        // Fallback: return first active user (for single-user import scenario)
        // Exclude super_admin from fallback
        return User::whereDoesntHave('roles', fn ($q) => $q->where('name', 'super_admin'))->first();
    }

    protected function parseDate(mixed $date): ?string
    {
        if (empty($date)) {
            return null;
        }

        // Handle Excel serial date number (e.g., 45964 for a date)
        if (is_numeric($date) && $date > 1) {
            $unixTimestamp = ($date - 25569) * 86400;
            return Carbon::createFromTimestamp($unixTimestamp)->format('Y-m-d');
        }

        $date = trim((string) $date);

        // Try various date formats
        $formats = [
            'd-M-y',      // 03-Nov-25
            'd-M-Y',      // 03-Nov-2025
            'd/m/Y',      // 03/11/2025
            'd/m/y',      // 03/11/25
            'Y-m-d',      // 2025-11-03
            'd-m-Y',      // 03-11-2025
            'd-m-y',      // 03-11-25
            'd M Y',      // 03 Nov 2025
            'd M y',      // 03 Nov 25
        ];

        foreach ($formats as $format) {
            try {
                $parsed = Carbon::createFromFormat($format, $date);
                if ($parsed) {
                    return $parsed->format('Y-m-d');
                }
            } catch (\Exception $e) {
                continue;
            }
        }

        // Try Carbon's generic parse as fallback
        try {
            return Carbon::parse($date)->format('Y-m-d');
        } catch (\Exception $e) {
            return null;
        }
    }

    protected function parseWaktu(mixed $waktu, string $date): array
    {
        $startTime = null;
        $endTime = null;

        if (empty($waktu)) {
            return [$startTime, $endTime];
        }

        $waktu = trim((string) $waktu);

        // Format expected: "07:33 - 16:47" or "07:33 - 19:20"
        if (preg_match('/(\d{1,2}:\d{2})\s*-\s*(\d{1,2}:\d{2})/', $waktu, $matches)) {
            $startTime = $this->parseTime($matches[1], $date);
            $endTime = $this->parseTime($matches[2], $date);
        } else {
            // Try to parse as single time
            $startTime = $this->parseTime($waktu, $date);
        }

        return [$startTime, $endTime];
    }

    protected function parseTime(mixed $time, string $date): ?string
    {
        if (empty($time)) {
            return null;
        }

        // Handle Excel numeric time format (e.g., 0.354166667 for 08:30)
        if (is_numeric($time) && $time < 1) {
            $totalSeconds = round($time * 86400);
            $hours = floor($totalSeconds / 3600);
            $minutes = floor(($totalSeconds % 3600) / 60);
            $seconds = $totalSeconds % 60;
            return sprintf('%02d:%02d:%02d', $hours, $minutes, $seconds);
        }

        // Handle Excel datetime numeric format
        if (is_numeric($time) && $time > 1) {
            $unixTimestamp = ($time - 25569) * 86400;
            return Carbon::createFromTimestamp($unixTimestamp)->format('H:i:s');
        }

        $time = trim((string) $time);

        // Handle time format HH:MM or H:MM
        if (preg_match('/^(\d{1,2}):(\d{2})(:(\d{2}))?$/', $time, $matches)) {
            $hours = str_pad($matches[1], 2, '0', STR_PAD_LEFT);
            $minutes = $matches[2];
            $seconds = isset($matches[4]) ? $matches[4] : '00';
            return "$hours:$minutes:$seconds";
        }

        // Try Carbon parse as fallback
        try {
            return Carbon::parse($time)->format('H:i:s');
        } catch (\Exception $e) {
            return null;
        }
    }

    public static function getCompletedNotificationBody(Import $import): string
    {
        $body = 'Import aktivitas selesai. ' . number_format($import->successful_rows) . ' baris berhasil diimport.';

        if ($failedRowsCount = $import->getFailedRowsCount()) {
            $body .= ' ' . number_format($failedRowsCount) . ' baris gagal.';
        }

        return $body;
    }
}
