<?php

namespace App\Http\Controllers;

use App\Http\Resources\DetailUserCompanyResource;
use App\Models\Company;
use App\Models\DetailUserCompany;
use App\Models\UserType;
use App\Models\DetailUserNotifications;
use App\Traits\HasResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Validator;
use Tymon\JWTAuth\Facades\JWTAuth;
use Tymon\JWTAuth\Exceptions\JWTException;

class AuthController extends Controller
{
    use HasResponse;

    public function login(Request $request)
    {
        try {
            $validator = Validator::make($request->all(), [
                'rut_company' => 'required|string|max:11', // es de compañia
                // 'rut_company' => $request->input('iduser_type') != 1 ? 'required|string|max:11' : 'nullable',
                'rut' => 'nullable|string|max:11|required_without:username',
                'username' => 'nullable|string|max:25|required_without:rut',
                'password' => 'required|string',
                'iduser_type' => 'required|integer',
            ]);
            if ($validator->fails()) return $this->errorResponse($validator->errors(), 400);

            # Validar rut de compañia y tipo de usuario
            $validatecompany = Company::rut($request['rut_company'])->active()->first();
            if(!$validatecompany) return $this->errorResponse('RUT de compañía inválido', 401);

            $validateTypeUser = UserType::activeForID($request['iduser_type'])->first();
            if(!$validateTypeUser) return $this->errorResponse('Tipo de usuario inválido', 401);

            # Obtener token
            $credentials['password'] = $request['password'];
            isset($request['rut']) ? $credentials['rut'] = $request['rut'] : $credentials['username'] = $request['username'];

            $token = JWTAuth::attempt($credentials);
            if (!$token) return $this->errorResponse('Credenciales inválidas', 401);

            $user = JWTAuth::user();
            if($user->status != 1) return $this->successResponse('Usuario inactivo', 401);

            # Validar usuario por compañia
            $userCompany = DetailUserCompany::findUser($user->id, $request['iduser_type'])->active()->first();
            if(!$userCompany) return $this->errorResponse('Credenciales inválidas', 401);
            
            # Guardar el idcompany en el token
            $token = JWTAuth::claims(['idcompany' => $validatecompany->id, 'iddetail_user' => $userCompany->id])->attempt($credentials);
            $token = JWTAuth::claims(['iddetail_user' => $userCompany->id])->attempt($credentials);

            return $this->successResponse('OK', $this->respondWithToken($token, $userCompany->load('user', 'userType', 'privilege', 'company')));
        } catch (\Throwable $th) {
            return $this->externalError('durante el login.', $th->getMessage());
            throw $th;
        }
    }

    protected function respondWithToken($token, $userCompany)
    {
        try {
            return [
                'access_token' => $token,
                'token_type' => 'bearer',
                'expires_in' => JWTAuth::factory()->getTTL() * 2000,
                'user' => DetailUserCompanyResource::make($userCompany)
            ];
        } catch (\Throwable $th) {
            throw $th;
        }
    }

    public function me()
    {
        try {
            $user = JWTAuth::user();
            $user->idcompany = JWTAuth::payload()->get('idcompany');

            $notifications = DetailUserNotifications::whereHas('notification', function ($query) use ($company) {
                $query = $query->active()->where('idcompany', $company->id);
                return $query;
            })->where('idreceiver', $user->id)->where('status_N', 1)->active()->count();
            $user->countN = $notifications;
            
            return $this->successResponse('OK', $user);
        } catch (\Throwable $th) {
            throw $th;
        }
    }

    public function logout()
    {
        try {
            $token = JWTAuth::getToken();
            JWTAuth::invalidate($token);
            return $this->successResponse('OK', 'Sesión cerrada con éxito');
        } catch (\Throwable $th) {
            throw $th;
        }
    }

    public function refresh()
    {
        try {
            $token_refresh = [
                'status' => true,
                'user' => Auth::user(),
                'token' => $this->respondWithToken(JWTAuth::refresh(), ''),
            ];
            return $this->successResponse('OK', $token_refresh);
        } catch (\Throwable $th) {
            throw $th;
        }
    }

    public function validateToken()
    {
        try {
            try {
                $user = JWTAuth::parseToken()->authenticate();
                if ($user) return $this->successResponse('OK', 'true');

                return $this->successResponse('OK', 'false');
            } catch (JWTException $e) {
                return $this->successResponse('OK', 'false');
            }
        } catch (\Throwable $th) {
        }
    }
}
