<?php

namespace App\Services;

use App\Contracts\AuditLogServiceInterface;
use App\Contracts\UserRepositoryInterface;
use App\DTO\UserDTO;
use App\Models\Role;
use App\Models\User;
use Illuminate\Contracts\Pagination\LengthAwarePaginator;
use Illuminate\Http\UploadedFile;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Storage;

class PersonnelService
{
    public function __construct(
        protected UserRepositoryInterface $userRepository,
        protected AuditLogServiceInterface $auditLogService
    ) {}

    public function getPaginatedPersonnel(string $type = 'all', string $search = '', ?int $shiftId = null, int $perPage = 10): LengthAwarePaginator
    {
        $roleId = null;
        if ($type === 'guru') {
            $roleId = Role::where('name', 'guru')->first()?->id;
        } elseif ($type === 'siswa') {
            $roleId = Role::where('name', 'siswa')->first()?->id;
        }

        return User::with(['role', 'shift'])
            ->when($type === 'all', function ($q) {
                $q->whereHas('role', fn($r) => $r->whereIn('name', ['guru', 'siswa']))
                  ->where('student_status', '!=', 'lulus');
            })
            ->when($type === 'guru', function ($q) use ($roleId) {
                $q->where('role_id', $roleId);
            })
            ->when($type === 'siswa', function ($q) use ($roleId) {
                $q->where('role_id', $roleId)->where('student_status', '!=', 'lulus');
            })
            ->when($type === 'alumni', function ($q) {
                $q->where('student_status', 'lulus');
            })
            ->when($shiftId !== null, fn($q) => $q->where('shift_id', $shiftId))
            ->when($search !== '', function ($q) use ($search) {
                $q->where(function ($sub) use ($search) {
                    $sub->where('name', 'like', "%{$search}%")
                        ->orWhere('email', 'like', "%{$search}%")
                        ->orWhere('nip_nis', 'like', "%{$search}%")
                        ->orWhere('class_name', 'like', "%{$search}%");
                });
            })
            ->latest()
            ->paginate($perPage);
    }

    public function createPersonnel(UserDTO $userDTO, ?UploadedFile $photo = null): User
    {
        $photoPath = null;
        if ($photo) {
            $photoPath = $photo->store('photos', 'public');
        }

        $dtoWithPhoto = UserDTO::fromArray([
            'role_id' => $userDTO->roleId,
            'shift_id' => $userDTO->shiftId,
            'name' => $userDTO->name,
            'nip_nis' => $userDTO->nipNis,
            'class_name' => $userDTO->className,
            'email' => $userDTO->email,
            'password' => $userDTO->password ?? 'password123',
            'force_password_change' => true,
            'is_active' => $userDTO->isActive,
            'photo_path' => $photoPath,
        ]);

        $user = $this->userRepository->create($dtoWithPhoto);
        $currentUser = Auth::user();
        $this->auditLogService->log($currentUser, 'PERSONNEL_CREATED', "Menambahkan personil baru: {$user->name} ({$user->role?->label})");

        return $user;
    }

    public function updatePersonnel(int $id, UserDTO $userDTO, ?UploadedFile $photo = null): User
    {
        $existingUser = User::findOrFail($id);
        $photoPath = $existingUser->photo_path;

        if ($photo) {
            if ($photoPath && Storage::disk('public')->exists($photoPath)) {
                Storage::disk('public')->delete($photoPath);
            }
            $photoPath = $photo->store('photos', 'public');
        }

        $dtoWithPhoto = UserDTO::fromArray([
            'role_id' => $userDTO->roleId,
            'shift_id' => $userDTO->shiftId,
            'name' => $userDTO->name,
            'nip_nis' => $userDTO->nipNis,
            'class_name' => $userDTO->className,
            'email' => $userDTO->email,
            'password' => $userDTO->password,
            'force_password_change' => $userDTO->forcePasswordChange,
            'is_active' => $userDTO->isActive,
            'photo_path' => $photoPath,
        ]);

        $user = $this->userRepository->update($id, $dtoWithPhoto);
        $currentUser = Auth::user();
        $this->auditLogService->log($currentUser, 'PERSONNEL_UPDATED', "Memperbarui data personil: {$user->name} (ID: {$id})");

        return $user;
    }

    public function deletePersonnel(int $id): bool
    {
        $user = User::findOrFail($id);
        if ($user->photo_path && Storage::disk('public')->exists($user->photo_path)) {
            Storage::disk('public')->delete($user->photo_path);
        }

        $userName = $user->name;
        $deleted = $this->userRepository->delete($id);

        if ($deleted) {
            $currentUser = Auth::user();
            $this->auditLogService->log($currentUser, 'PERSONNEL_DELETED', "Menghapus personil: {$userName} (ID: {$id})");
        }

        return $deleted;
    }
}
