<?php

namespace App\Models\Pouzivatel;

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

/**
 * Class Authentication
 * @package App\Models\Pouzivatel
 */
class Authentication
{
    /**
     * @var \Seka\AisekV3UserAuth\Authentication
     */
    protected $userAuthentication;

    protected RoleAndPermissionsAggregator $rolesAggregator;

    /**
     * Authentication constructor.
     *
     * @param \Seka\AisekV3UserAuth\Authentication                $userAuthentication
     * @param \App\Models\Pouzivatel\RoleAndPermissionsAggregator $rolesAggregator
     */
    public function __construct(UserAuthentication $userAuthentication, RoleAndPermissionsAggregator $rolesAggregator)
    {
        $this->userAuthentication = $userAuthentication;
        $this->rolesAggregator = $rolesAggregator;
    }

    /**
     * @param array $inputs
     *
     * @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']));
            $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 (401 === $e->getCode()) {
                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á.');
        }
    }
}
