<?php

namespace App\Filament\Pages\Auth;

use App\Models\Enum\RoleEnum;
use App\Models\Enum\UserTypeEnum;
use App\Models\User;
use DanHarrin\LivewireRateLimiting\Exceptions\TooManyRequestsException;
use Filament\Facades\Filament;
use Filament\Forms\Components\TextInput;
use Filament\Http\Responses\Auth\Contracts\LoginResponse;
use Filament\Models\Contracts\FilamentUser;
use Filament\Pages\Auth\Login as BaseLogin;
use Filament\Forms\Form;
use Illuminate\Support\Facades\Http;

class Login extends BaseLogin
{
    public function form(Form $form): Form
    {
        return $form
            ->schema([
                TextInput::make('barcode')
                    ->label('Barcode or Identification Number')
                    ->required()
                    ->placeholder('Input barcode or identification number')
                    ->maxLength(255),

                TextInput::make('pin')
                    ->label('PIN')
                    ->password()
                    ->required()
                    ->placeholder('Input PIN')
                    ->maxLength(255),
            ]);
    }

    public function authenticate(): ?LoginResponse
    {
        try {
            $this->rateLimit(5);
        } catch (TooManyRequestsException $exception) {
            $this->getRateLimitedNotification($exception)?->send();

            return null;
        }

        $data = $this->form->getState();

        $response = $this->validateUserWithAPI($data['barcode'], $data['pin']);

        if ($response['codi_resposta'] != 0) {
            $this->throwFailureValidationException();
        }

        $userLocked = $this->isUserBlocked($response);

        $user = User::where("library_identifier", $data["barcode"])
            ->orWhere("identifier", $data["barcode"])
            ->first()
        ;

        if (!$user) {
            $user = $this->createUserFromAPIResponse($response["usuari_xb"], $userLocked);
        }

        if ($userLocked) {
            $user->update(['locked' => true]);

            $this->throwFailureValidationException();
        }

        $data["email"] = $user->email;
        $data["password"] = $response["usuari_xb"]["codi"];

        if (! Filament::auth()->attempt($this->getCredentialsFromFormData($data), $data['remember'] ?? false)) {
            $this->throwFailureValidationException();
        }

        $user = Filament::auth()->user();

        if (
            ($user instanceof FilamentUser) &&
            (! $user->canAccessPanel(Filament::getCurrentPanel()))
        ) {
            Filament::auth()->logout();

            $this->throwFailureValidationException();
        }

        session()->regenerate();

        return app(LoginResponse::class);
    }

    private function validateUserWithAPI($codi, $pin)
    {
        $apiUrl = env("SAJ_DIBA_BIBL_USER_VALIDATION_URL");
        $response = Http::get($apiUrl, [
            'ws_usuari' => env('SAJ_DIBA_BIBL_USER_WS_USER'),
            'ws_clau'   => env('SAJ_DIBA_BIBL_USER_WS_ACCESS'),
            'codi'      => $codi,
            'pin'       => $pin,
            'tipus_resposta' => 'json',
            'bloq'      => true,
            'circdata'  => 't'
        ]);

        if ($response->failed()) {
            return [
                'codi_resposta' => 1,
                'text_resposta' => 'Error al comunicarse con el servicio.',
            ];
        }

        return $response->json();
    }

    private function createUserFromAPIResponse($apiData, $isBlocked)
    {
        return User::create([
            'name'         => $apiData['nom'],
            'email'        => $apiData['email'] ?? null,
            'library_identifier'      => $apiData['codi'],
            'birth_date'   => $apiData['data_naixament'] ?? null,
            'address'      => $apiData['adreça'] ?? null,
            'identifier'          => $apiData['dni'] ?? null,
            'locked' => $isBlocked,
            'sierra_record_number' => $apiData['record_number'] ?? null,
            'sex' => $apiData['sexe'] ?? null,
            'user_type' => $apiData['tipus_usuari'] ?? null,
            'location' => $apiData['municipi'] ?? null,
            'town' => $apiData['barri'] ?? null,
            'country_born' => $apiData['pais_nacionalitat'] ?? null,
            'principal_library' => $apiData['biblioteca_home'] ?? null,
            'lock_date_until' => $apiData['data_límit_bloqueig'] ?? null,
            'notice_number' => $apiData['numero_avisos'] ?? null,
            'warnings' => $apiData['alertes'] ?? null,
            'record_number' => $apiData['record_number'] ?? null,
            'password' => bcrypt($apiData['codi']),
            'role_id' => RoleEnum::ID[RoleEnum::SIDE_USER],
            'user_type_id' => UserTypeEnum::ID[UserTypeEnum::GENERAL]
        ]);
    }

    private function isUserBlocked($apiResponse)
    {
        // Lógica basada en los códigos de bloqueo (160, 161, etc.)
        $responseCode = $apiResponse['codi_motiu'] ?? null;

        return in_array($responseCode, [160, 161]);
    }

}
