<?php

namespace App\Http\Controllers\Auth;

use App\User;
use App\Aspirante;
use Validator;
use App\Http\Controllers\Controller;
use Illuminate\Foundation\Auth\ThrottlesLogins;
use Illuminate\Foundation\Auth\AuthenticatesAndRegistersUsers;
use App\Configuracion as Configuracion;
use Illuminate\Http\Request;
use App\ActivationService as ActivationService;
use App\Jobs\SendActivationEmail;
use Illuminate\Database\QueryException;

class AuthController extends Controller {
  /*
  |--------------------------------------------------------------------------
  | Registration & Login Controller
  |--------------------------------------------------------------------------
  |
  | This controller handles the registration of new users, as well as the
  | authentication of existing users. By default, this controller uses
  | a simple trait to add these behaviors. Why don't you explore it?
  |
  */

  use AuthenticatesAndRegistersUsers,
  ThrottlesLogins;

  /**
  * Where to redirect users after login / registration.
  *
  * @var string
  */
  protected $loginPath = ''; //
  protected $redirectTo = 'datos';
  protected $activationService;
  protected $redirectAfterLogout = '';

  /**
  * Create a new authentication controller instance.
  *
  * @return void
  */
  public function __construct(ActivationService $activationService) {
    $this->loginPath = env("APP_URL").'auth/login';
    $this->redirectAfterLogout = env("APP_URL").'auth/login';
    $this->middleware($this->guestMiddleware(), ['except' => 'logout']);
    $this->activationService = $activationService;
  }

  /**
   * Helper that checks whether the submission period (limit_date) has
   * already passed. The application stores the cutoff in the
   * ``Configuracion`` table under the key "limit_date".
   *
   * @return array  [bool $expired, string|null $limitDate]
   */
  protected function checkLimitDate()
  {
      $configuracion = Configuracion::where('llave', '=', 'limit_date')->first();
      $limit = $configuracion ? $configuracion->valor : null;
      $expired = false;
      if ($limit) {
          // behaviour in authenticated() uses a 5‑hour offset as well
          $expired = strtotime($limit) <= (time() - 5 * 3600);
      }
      return [$expired, $limit];
  }

  /**
  * Get a validator for an incoming registration request.
  *
  * @param  array  $data
  * @return \Illuminate\Contracts\Validation\Validator
  */
  protected function validator(array $data) {
    \Log::info('Formulario enviado ', [$data]);
    return Validator::make($data, [
      'name' => 'required|max:255',
      'email' => 'required|email|max:255|unique:users',
      'password' => 'required|min:6|confirmed',
      'terminos' => 'accepted',
      'g-recaptcha-response' => 'required',
    ]);
  }


  protected function validateLogin(Request $request) {
    $this->validate($request, [
      'email' => 'required',
      'password' => 'required|string',
      'g-recaptcha-response' => 'required|'
    ]);
  }
  protected function authenticated ( $request, $user) {
    if (!$user->activated) {
      $this->dispatch(new SendActivationEmail($user));
      auth()->logout();
      return back()->with('warning', 'Necesita confirmar su registro. Hemos enviado un código de activación a
      su correo, por favor verifíquelo.');
    } else {
      if($user->isadmin) {
        return redirect('admin/candidatos');
      } else {
        $configuracion = Configuracion::where('llave', '=', 'limit_date')->first();
        $data = [];
        if (strtotime($configuracion['valor']) > (time()- 5 * 3600)) {
          return redirect('datos');
        } else {
          $data = array(
            'limit_date' => $configuracion['valor']
          );
          auth()->logout();
          return view('auth/timeout', $data);
        }
      }
    }
  }

  public function getLogin() {
    list($expired, $limit) = $this->checkLimitDate();
    if ($expired) {
      // if the window has closed do not render the login form at all
      return view('auth/timeout', ['limit_date' => $limit]);
    }

    return view('auth/login');
  }

  public function getAdminLogin() {
    return view('admin/login_admin_console');
  }

  /**
   * Override the default GET register handler so the form is hidden once
   * the submission deadline has been reached.
   */
  public function getRegister()
  {
      list($expired, $limit) = $this->checkLimitDate();
      if ($expired) {
          return view('auth/timeout', ['limit_date' => $limit]);
      }
      return view('auth/register');
  }

  // the trait used by this controller binds the POST /auth/register route
  // to whatever method is named `register` here, so this method handles
  // the submission. We need to make sure the user cannot even POST when
  // the limit date has passed.
  public function register(Request $request) {
    list($expired, $limit) = $this->checkLimitDate();
    if ($expired) {
      return view('auth/timeout', ['limit_date' => $limit]);
    }

    $validator = $this->validator($request->all());
    
    if ($validator->fails()) {
      $this->throwValidationException(
        $request, $validator
      );
    }
    $user = $this->create($request->all());
    $this->dispatch(new SendActivationEmail($user));
    return redirect('auth/login')->with('status', 'Hemos enviado el enlace de activación a su cuenta de correo. Por favor, verifíque su correo electrónico.');
  }

  public function activateUser($token) {
    if ($user = $this->activationService->activateUser($token)) {
      auth()->login($user);
      return redirect($this->redirectPath());
    }
    return redirect('auth/login')->with('status', 'Su correo electrónico ha sido verificado correctamente.');
  }
  /**
  * Create a new user instance after a valid registration.
  *
  * @param  array  $data
  * @return User
  */
  protected function create(array $data) {
    $maxAttempts = 5;

    for ($attempt = 1; $attempt <= $maxAttempts; $attempt++) {
      try {
        return \DB::transaction(function () use ($data) {
          return User::create([
            'name' => $data['name'],
            'email' => $data['email'],
            'codigo' => $this->generateCodeNumber($data['name']),
            'password' => bcrypt($data['password']),
            'personal_data'  => true
          ]);
        });
      } catch (QueryException $e) {
        // SQLSTATE 23000 = violación de integridad (incluye UNIQUE en codigo)
        $sqlState = isset($e->errorInfo[0]) ? $e->errorInfo[0] : null;
        if ($sqlState !== '23000' || $attempt === $maxAttempts) {
          throw $e;
        }
      }
    }
  }

  public function getLogout() {
    $this->auth->logout();
    Session::flush();
    Cache::flush();
    //return env('APP_URL').'auth/login';
    return redirect()->route('auth/login');
  }
  private function generateCodeNumber($string) {
    // Prefijo seguro de hasta 7 caracteres (para mantener codigo <= 11)
    $initials = "";
    $words = preg_split("/\s+/", trim($string));
    foreach ($words as $w) {
      if (strlen($w) > 0) {
        $safeWord = $this->sanitizeCodeToken($w);
        if ($safeWord !== '') {
          $initials .= substr($safeWord, 0, 1);
        }
      }
    }
    if ($initials === '') {
      $initials = 'USR';
    }
    $initials = substr($initials, 0, 7);

    // Secuencia por prefijo sin aleatoriedad: evita saltos por diseño
    $codes = User::where('codigo', 'like', $initials . '%')
      ->lockForUpdate()
      ->pluck('codigo');

    $maxSequence = 0;
    foreach ($codes as $code) {
      if (preg_match('/^' . preg_quote($initials, '/') . '([0-9]{4})$/', $code, $matches)) {
        $seq = (int) $matches[1];
        if ($seq > $maxSequence) {
          $maxSequence = $seq;
        }
      }
    }

    $next = $maxSequence + 1;
    return $initials . str_pad((string) $next, 4, '0', STR_PAD_LEFT);
  }

  private function sanitizeCodeToken($value) {
    $value = trim((string) $value);
    $from = array('Á','À','Â','Ä','Ã','Å','á','à','â','ä','ã','å','É','È','Ê','Ë','é','è','ê','ë','Í','Ì','Î','Ï','í','ì','î','ï','Ó','Ò','Ô','Ö','Õ','ó','ò','ô','ö','õ','Ú','Ù','Û','Ü','ú','ù','û','ü','Ñ','ñ','Ç','ç');
    $to   = array('A','A','A','A','A','A','A','A','A','A','A','A','E','E','E','E','E','E','E','E','I','I','I','I','I','I','I','I','O','O','O','O','O','O','O','O','O','O','U','U','U','U','U','U','U','U','N','N','C','C');
    $value = str_replace($from, $to, $value);
    $value = strtoupper($value);
    $value = preg_replace('/[^A-Z0-9]/', '', $value);
    return $value;
  }


}
