<?php

namespace App\Livewire\Personnel;

use App\DTO\UserDTO;
use App\Models\Role;
use App\Models\Shift;
use App\Models\User;
use App\Services\PersonnelExportService;
use App\Services\PersonnelImportService;
use App\Services\PersonnelService;
use App\Traits\WithToastNotifications;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
use Illuminate\Validation\Rule;
use Livewire\Component;
use Livewire\WithFileUploads;
use Livewire\WithPagination;

class PersonnelIndex extends Component
{
    use WithPagination, WithFileUploads, AuthorizesRequests, WithToastNotifications;

    public string $type = 'all'; // 'all', 'guru', 'siswa', 'alumni'
    public string $search = '';
    public ?int $selectedShiftId = null;
    public int $perPage = 10;

    // Modals state
    public bool $showFormModal = false;
    public bool $showImportModal = false;
    public bool $showDeleteModal = false;

    // Form fields for Add/Edit
    public ?int $editingUserId = null;
    public int $role_id = 4; // Default Guru
    public ?int $shift_id = null;
    public string $name = '';
    public string $nip_nis = '';
    public string $class_name = '';
    public string $email = '';
    public string $password = '';
    public $photo; // Uploaded file
    public ?string $existingPhotoUrl = null;
    public bool $is_active = true;
    public string $student_status = 'aktif';

    // Import fields
    public $importFile;
    public int $importRoleId = 4;
    public ?int $importShiftId = null;
    public bool $autoGraduateClass12 = true;

    public function pushToMachine(\App\Services\SyncService $syncService): void
    {
        $this->authorize('create', User::class);

        $res = $syncService->pushUsersToAllMachines();

        $this->notifySuccess($res['message']);
    }

    // Delete fields
    public ?int $deletingUserId = null;
    public string $deletingUserName = '';

    protected function rules(): array
    {
        $userId = $this->editingUserId;

        return [
            'role_id' => ['required', 'exists:roles,id'],
            'shift_id' => ['nullable', 'exists:shifts,id'],
            'name' => ['required', 'string', 'max:255'],
            'nip_nis' => ['nullable', 'string', 'max:50'],
            'email' => [
                'required',
                'string',
                'email',
                'max:255',
                Rule::unique('users', 'email')->ignore($userId)->whereNull('deleted_at'),
            ],
            'password' => [$userId ? 'nullable' : 'required', 'string', 'min:8'],
            'photo' => ['nullable', 'image', 'max:2048'],
            'is_active' => ['boolean'],
            'student_status' => ['required', 'string', 'in:aktif,lulus,pindah'],
        ];
    }

    protected function messages(): array
    {
        return [
            'role_id.required' => 'Peran (Role) wajib dipilih.',
            'name.required' => 'Nama lengkap wajib diisi.',
            'email.required' => 'Email wajib diisi.',
            'email.unique' => 'Email ini sudah terdaftar.',
            'password.required' => 'Password wajib diisi untuk personil baru.',
            'password.min' => 'Password minimal 8 karakter.',
            'photo.image' => 'File foto harus berupa gambar.',
            'photo.max' => 'Ukuran foto maksimal 2MB.',
        ];
    }

    public function updatingSearch(): void { $this->resetPage(); }
    public function updatingType(): void { $this->resetPage(); }
    public function updatingSelectedShiftId(): void { $this->resetPage(); }

    public function setType(string $type): void
    {
        $this->type = $type;
        $this->resetPage();
    }

    public function create(): void
    {
        $this->authorize('create', User::class);
        $this->resetForm();

        // Preset role_id if filtering by tab
        if ($this->type === 'guru') {
            $this->role_id = Role::where('name', 'guru')->first()?->id ?? 4;
            $this->shift_id = Shift::where('name', 'Shift Guru & Staf TU')->first()?->id
                ?? Shift::where('name', 'Shift Guru')->first()?->id;
        } elseif ($this->type === 'siswa' || $this->type === 'alumni') {
            $this->role_id = Role::where('name', 'siswa')->first()?->id ?? 5;
            $this->shift_id = Shift::where('name', 'Shift Siswa Reguler')->first()?->id
                ?? Shift::where('name', 'Shift Siswa')->first()?->id;
        }

        $this->showFormModal = true;
    }

    public function edit(int $id, PersonnelService $personnelService): void
    {
        $user = User::findOrFail($id);
        $this->authorize('update', $user);

        $this->editingUserId = $user->id;
        $this->role_id = $user->role_id;
        $this->shift_id = $user->shift_id;
        $this->name = $user->name;
        $this->nip_nis = $user->nip_nis ?? '';
        $this->class_name = $user->class_name ?? '';
        $this->student_status = $user->student_status ?? 'aktif';
        $this->email = $user->email;
        $this->password = '';
        $this->existingPhotoUrl = $user->photo_path ? asset('storage/' . $user->photo_path) : null;
        $this->is_active = $user->is_active;

        $this->showFormModal = true;
    }

    public function save(PersonnelService $personnelService): void
    {
        $this->validate();

        $isActive = $this->student_status === 'lulus' ? false : $this->is_active;

        $userDTO = UserDTO::fromArray([
            'role_id' => $this->role_id,
            'shift_id' => $this->shift_id,
            'name' => $this->name,
            'nip_nis' => $this->nip_nis,
            'class_name' => $this->class_name,
            'email' => $this->email,
            'password' => $this->password !== '' ? $this->password : null,
            'force_password_change' => true,
            'is_active' => $isActive,
        ]);

        if ($this->editingUserId) {
            $user = User::findOrFail($this->editingUserId);
            $this->authorize('update', $user);

            $personnelService->updatePersonnel($this->editingUserId, $userDTO, $this->photo);
            $user->refresh();
            $user->student_status = $this->student_status;
            if ($this->student_status === 'lulus') {
                $user->is_active = false;
            }
            $user->save();

            $this->notifySuccess('Data personil berhasil diperbarui.');
        } else {
            $this->authorize('create', User::class);
            $newUser = $personnelService->createPersonnel($userDTO, $this->photo);
            $newUser->student_status = $this->student_status;
            if ($this->student_status === 'lulus') {
                $newUser->is_active = false;
            }
            $newUser->save();

            $this->notifySuccess('Data personil baru berhasil ditambahkan.');
        }

        $this->closeModal();
    }

    public function openImportModal(): void
    {
        $this->authorize('create', User::class);
        $this->importFile = null;
        $this->importRoleId = Role::where('name', 'siswa')->first()?->id ?? 5;
        $this->importShiftId = Shift::where('name', 'Shift Siswa')->first()?->id;
        $this->autoGraduateClass12 = true;
        $this->showImportModal = true;
    }

    public function processImport(PersonnelImportService $importService): void
    {
        $this->validate([
            'importFile' => ['required', 'file', 'max:10240'],
            'importRoleId' => ['required', 'exists:roles,id'],
        ], [
            'importFile.required' => 'File belum selesai diunggah ke server. Mohon tunggu 2 detik hingga indikator upload selesai, lalu klik Mulai Import kembali.',
            'importFile.max' => 'Ukuran file Excel/CSV tidak boleh lebih dari 10 MB.',
        ]);

        $result = $importService->importFromFile(
            $this->importFile,
            $this->importRoleId,
            $this->importShiftId,
            $this->autoGraduateClass12
        );

        if ($result['success']) {
            $this->notifySuccess($result['message']);
            $this->showImportModal = false;
            $this->importFile = null;
        } else {
            $this->addError('importFile', $result['message']);
        }
    }

    public function exportData(PersonnelExportService $exportService)
    {
        $this->authorize('viewAny', User::class);
        return $exportService->exportCsv($this->type);
    }

    public function confirmDelete(int $id): void
    {
        $user = User::findOrFail($id);
        $this->authorize('delete', $user);

        $this->deletingUserId = $user->id;
        $this->deletingUserName = $user->name;
        $this->showDeleteModal = true;
    }

    public function deletePersonnelDirect(int $id, PersonnelService $personnelService): void
    {
        $user = User::findOrFail($id);
        $this->authorize('delete', $user);

        $personnelService->deletePersonnel($id);
        $this->notifySuccess("Data personil {$user->name} berhasil dihapus.");

        $this->showDeleteModal = false;
        $this->deletingUserId = null;
    }

    public function delete(PersonnelService $personnelService): void
    {
        if ($this->deletingUserId) {
            $user = User::findOrFail($this->deletingUserId);
            $this->authorize('delete', $user);

            $personnelService->deletePersonnel($this->deletingUserId);
            $this->notifySuccess('Data personil berhasil dihapus.');
        }

        $this->showDeleteModal = false;
        $this->deletingUserId = null;
    }

    public function closeModal(): void
    {
        $this->showFormModal = false;
        $this->showImportModal = false;
        $this->showDeleteModal = false;
        $this->resetForm();
    }

    private function resetForm(): void
    {
        $this->editingUserId = null;
        $this->role_id = Role::where('name', 'guru')->first()?->id ?? 4;
        $this->shift_id = null;
        $this->name = '';
        $this->nip_nis = '';
        $this->class_name = '';
        $this->student_status = 'aktif';
        $this->email = '';
        $this->password = '';
        $this->photo = null;
        $this->existingPhotoUrl = null;
        $this->is_active = true;
        $this->resetValidation();
    }

    public function render(PersonnelService $personnelService)
    {
        $this->authorize('viewAny', User::class);

        $personnel = $personnelService->getPaginatedPersonnel($this->type, $this->search, $this->selectedShiftId, $this->perPage);
        $roles = Role::whereIn('name', ['guru', 'siswa'])->get();
        $shifts = Shift::all();

        return view('livewire.personnel.personnel-index', [
            'personnel' => $personnel,
            'roles' => $roles,
            'shifts' => $shifts,
        ])->layout('components.layouts.app');
    }
}
