<?php

namespace Modules\User\Services;

use Illuminate\Contracts\Pagination\LengthAwarePaginator;
use Illuminate\Http\UploadedFile;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Storage;
use Modules\Auth\Entities\User;
use Modules\Role\Entities\Role;
use Modules\User\Repositories\Contracts\UserRepositoryInterface;

class UserService
{
    public function __construct(
        protected UserRepositoryInterface $repository
    ) {}

    public function getPaginatedList(
        int $perPage,
        string $search,
        string $status,
        string $sortBy,
        string $sortOrder
    ): LengthAwarePaginator {
        return $this->repository->getAllWithRelationsPaginated(
            $perPage,
            $search,
            $status,
            $sortBy,
            $sortOrder
        );
    }

    public function getDeletedPaginatedList(
        int $perPage,
        string $search,
        string $status,
        string $sortBy,
        string $sortOrder
    ): LengthAwarePaginator {
        return $this->repository->getDeletedWithRelationsPaginated(
            $perPage,
            $search,
            $status,
            $sortBy,
            $sortOrder
        );
    }

    public function restoreUser(string $id): ?User
    {
        if (! $this->repository->restore($id)) {
            return null;
        }

        return $this->repository->findById($id);
    }

    public function getUserWithRelations(string $id): ?User
    {
        $user = $this->repository->findById($id);

        if ($user) {
            $user->load([
                'roles.permissions',
                'addresses',
                'employments',
                'bankDetails.bank',
                'heirs',
            ]);
        }

        return $user;
    }

    /**
     * @return array{user: User}|array{error: string}
     */
    public function assignRoles(string $id, array $roleIds): array
    {
        $user = $this->repository->findById($id);

        if (! $user) {
            return ['error' => 'User not found.'];
        }

        $roles = Role::whereIn('id', $roleIds)
            ->where('guard_name', 'api')
            ->get();

        if ($roles->isEmpty()) {
            return ['error' => 'No valid roles found.'];
        }

        $user->syncRoles($roles);
        $user->load(['roles.permissions']);

        return ['user' => $user];
    }

    public function updateProfile(User $user, array $validated, ?UploadedFile $image = null): User
    {
        if ($image) {
            if ($user->image_url && Storage::disk('public')->exists($user->image_url)) {
                Storage::disk('public')->delete($user->image_url);
            }

            $validated['image_url'] = $image->store('user-images', 'public');
        }

        unset($validated['image']);

        $data = $this->prepareProfileUpdateData($validated);
        $user->update($data);
        $user->load(['roles.permissions']);

        return $user;
    }

    /**
     * @return array{}|array{error: string}
     */
    public function updatePassword(User $user, string $currentPassword, string $newPassword): array
    {
        if (! Hash::check($currentPassword, $user->password)) {
            return ['error' => 'Current password is incorrect.'];
        }

        $user->update([
            'password' => Hash::make($newPassword),
        ]);

        return [];
    }

    protected function prepareProfileUpdateData(array $validated): array
    {
        unset($validated['uuid']);

        if (! array_key_exists('email', $validated)) {
            unset($validated['email']);
        }

        return $validated;
    }
}
