<?php

namespace App\Models\Pouzivatel;

use App\Models\Pracovisko\Pracovisko;
use Exception;
use Illuminate\Auth\AuthenticationException;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Hash;
use Seka\AisekV3UserAuth\Authentication as UserAuthentication;
use Seka\AisekV3UserAuth\Exceptions\HttpRequestFailedException;
use Seka\AisekV3UserAuth\Exceptions\HttpResponseIsNotSetException;
use Seka\AisekV3UserAuth\Exceptions\NotSupportedContentTypeException;
use Seka\AisekV3UserAuth\UserInterface;

/**
 * Class Authentication
 */
class Authentication
{
    /**
     * @var \Seka\AisekV3UserAuth\Authentication
     */
    protected $userAuthentication;

    protected RoleAndPermissionsAggregator $rolesAggregator;

    /**
     * Authentication constructor.
     */
    public function __construct(UserAuthentication $userAuthentication, RoleAndPermissionsAggregator $rolesAggregator)
    {
        $this->userAuthentication = $userAuthentication;
        $this->rolesAggregator = $rolesAggregator;
    }

    /**
     * @throws \Exception
     */
    public function auth(array $inputs): void
    {
        try {
            DB::beginTransaction();

            $this->userAuthentication->authenticate($inputs['login'], $inputs['password']);
            $userValObj = $this->userAuthentication->getUserDetail();

            $pek = Pracovisko::query()->firstOrNew([
                'kod' => mb_strcut($userValObj->getPek()->getName(), 0, 4),
            ]);
            $pek->setAttribute('nazov', explode(' - ', $userValObj->getPek()->getName())[1]);
            $pek->save();

            /** @var \App\Models\Pouzivatel\Pouzivatel $pouzivatel */
            $pouzivatel = Pouzivatel::query()->firstOrNew([
                'login' => $userValObj->getUserName(),
            ]);
            $pouzivatel->setAttribute('meno', $userValObj->getFirstName());
            $pouzivatel->setAttribute('priezvisko', $userValObj->getSurname());
            $pouzivatel->setAttribute('password', Hash::make($inputs['password']));
            $pouzivatel->setAttribute('telefon', $userValObj->getTelephone());
            $pouzivatel->setAttribute('email', $this->processingEmailAddress($userValObj));
            $opravnenia = $this->rolesAggregator->vratOpravneniaPreRole($userValObj->getRoles());
            $role = $this->rolesAggregator->vratRolePreRole($userValObj->getRoles());
            $pouzivatel->syncPermissions($opravnenia);
            $pouzivatel->syncRoles($role);
            $pouzivatel->pracovisko()->associate($pek);
            $pouzivatel->save();

            DB::commit();
        } catch (HttpRequestFailedException|HttpResponseIsNotSetException|NotSupportedContentTypeException $e) {
            DB::rollBack();

            if ($e->getCode() === 401) {
                throw new AuthenticationException('Nesprávne prihlasovacie údaje.');
            }

            throw new Exception('Autentifikácia používateľa voči autentifikačnému systému nebola úspešná.');
        }
    }

    public function processingEmailAddress(UserInterface $userValObj): ?string
    {
        $emailAddress = trim($userValObj->getEmailAddress());

        if (filter_var($emailAddress, FILTER_VALIDATE_EMAIL)) {
            return $emailAddress;
        }

        return null;
    }
}
