<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash;
use App\Models\Jugador;
use App\Models\Aficionado;
use App\Models\AdminUser;
use App\Models\Club;
use App\Mail\WelcomeMail;
use App\Mail\ResetPasswordMail;
use Illuminate\Support\Facades\Mail;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Http;

class AuthController extends Controller
{
    /**
     * Valida el token de Cloudflare Turnstile
     */
    private function verifyTurnstile($token)
    {
        if (in_array(config('app.env'), ['local', 'testing']) && $token === '1x00000000000000000000AA') {
            return true;
        }

        if (!$token) return false;

        $response = Http::asForm()->post('https://challenges.cloudflare.com/turnstile/v0/siteverify', [
            'secret'   => config('services.turnstile.secret_key'),
            'response' => $token,
            'remoteip' => request()->ip(),
        ]);

        return $response->successful() && $response->json('success');
    }

    public function login(Request $request)
    {
        $tipo = $request->input('tipo');
        
        if ($tipo === 'admin') {
            return $this->loginAdmin($request);
        }

        return $this->loginPlayer($request);
    }

    public function loginPlayer(Request $request)
    {
        if (!$this->verifyTurnstile($request->input('cf-turnstile-response'))) {
            return back()->with('login_error', 'Error de verificación de seguridad (Turnstile).')->with('login_tab', 'player');
        }

        $dni = $request->input('dni');
        $password = $request->input('password');

        $jugador = Jugador::where('documento', $dni)->where('activo', true)->first();
        
        if ($jugador && $jugador->password && Hash::check($password, $jugador->password)) {
            $request->session()->put('user_logged_in', true);
            $request->session()->put('user_tipo', 'jugador');
            $request->session()->put('user_id', $jugador->id_jugador);
            $request->session()->put('user_name', $jugador->nombre . ' ' . $jugador->apellido);
            $request->session()->put('user_documento', $jugador->documento);
            $request->session()->put('user_ultimo_acceso', time());
            
            return redirect()->intended('/');
        }

        $aficionado = Aficionado::where('dni', $dni)->first();
        
        if ($aficionado && $aficionado->password && Hash::check($password, $aficionado->password)) {
            $request->session()->put('user_logged_in', true);
            $request->session()->put('user_tipo', 'aficionado');
            $request->session()->put('user_id', $aficionado->id_aficionado);
            $request->session()->put('user_name', $aficionado->nombre . ' ' . $aficionado->apellido);
            $request->session()->put('user_documento', $aficionado->dni);
            $request->session()->put('user_ultimo_acceso', time());
            
            return redirect()->intended('/');
        }

        return back()->with('login_error', 'DNI o contraseña incorrectos')->with('login_tab', 'player');
    }

    public function loginAdmin(Request $request)
    {
        if (!$this->verifyTurnstile($request->input('cf-turnstile-response'))) {
            return back()->with('login_error', 'Error de verificación de seguridad (Turnstile).')->with('login_tab', 'admin');
        }

        $username = $request->input('username');
        $password = $request->input('password');

        $admin = AdminUser::whereRaw('BINARY `username` = ?', [$username])->first();

        if ($admin && Hash::check($password, $admin->password)) {
            $request->session()->put('admin_logged_in', true);
            $request->session()->put('admin_id', $admin->id);
            $request->session()->put('admin_username', $admin->username);
            $request->session()->put('admin_role', $admin->role);
            $request->session()->put('admin_id_club', $admin->id_club);

            if ($admin->id_club && $admin->club) {
                $request->session()->put('admin_club_nombre', $admin->club->nombre);
            }

            $request->session()->put('ultimo_acceso', time());
            
            return redirect()->intended('/');
        }

        return back()->with('login_error', 'Usuario o contraseña incorrectos')->with('login_tab', 'admin');
    }

    public function logout(Request $request)
    {
        $isAdmin = $request->session()->get('admin_logged_in');
        
        if ($isAdmin) {
            $request->session()->forget(['admin_logged_in', 'admin_id', 'admin_username', 'admin_role', 'ultimo_acceso']);
            $msg = 'Sesión de administrador cerrada correctamente.';
        } else {
            $request->session()->forget(['user_logged_in', 'user_tipo', 'user_id', 'user_name', 'user_documento', 'user_ultimo_acceso']);
            $msg = 'Sesión cerrada correctamente.';
        }
        
        return redirect('/?logout_msg=' . urlencode($msg));
    }

    public function showLoginForm()
    {
        return view('welcome');
    }

    public function recuperar(Request $request)
    {
        if (!$this->verifyTurnstile($request->input('cf-turnstile-response'))) {
            return back()->with('mensaje', '⚠️ Error de verificación de seguridad (Captcha).');
        }

        $dni = trim($request->input('dni'));
        $email = trim($request->input('email'));

        if (empty($dni) || empty($email)) {
            return back()->with('mensaje', 'Debes ingresar tu DNI y correo electrónico.');
        }

        $jugador = Jugador::where('documento', $dni)->where('email', $email)->first();
        $aficionado = Aficionado::where('dni', $dni)->where('email', $email)->first();

        $usuario = $jugador ?: $aficionado;

        if (!$usuario) {
            return back()->with('mensaje', 'No se encontró un usuario con ese DNI y correo.');
        }

        $token = bin2hex(random_bytes(16));
        $expires = now()->addHour();
        
        if ($jugador) {
            $jugador->update([
                'reset_token' => $token,
                'reset_expira' => $expires
            ]);
        } else {
            $aficionado->update([
                'reset_token' => $token,
                'reset_expira' => $expires
            ]);
        }
        try {
            Mail::to($usuario->email)->send(new ResetPasswordMail($usuario, $token));
        } catch (\Exception $e) {
            Log::error("Error enviando mail de recuperación: " . $e->getMessage());
        }

        return back()->with('mensaje', '📩 Te enviamos un correo con las instrucciones para recuperar tu contraseña.');
    }

    public function resetPasswordForm($token)
    {
        // Verificar que el token exista y no esté expirado
        $jugador = Jugador::where('reset_token', $token)->where('reset_expira', '>', now())->first();
        $aficionado = Aficionado::where('reset_token', $token)->where('reset_expira', '>', now())->first();

        if (!$jugador && !$aficionado) {
            return redirect()->route('recuperar')->with('mensaje', '❌ El enlace es inválido o ya expiró. Solicitá uno nuevo.');
        }

        return view('auth.reset_password', compact('token'));
    }

    public function resetPassword(Request $request)
    {
        $request->validate([
            'token'    => 'required|string',
            'password' => 'required|confirmed|min:6',
        ]);

        $token = $request->input('token');

        $jugador = Jugador::where('reset_token', $token)->where('reset_expira', '>', now())->first();
        $aficionado = Aficionado::where('reset_token', $token)->where('reset_expira', '>', now())->first();

        $usuario = $jugador ?: $aficionado;

        if (!$usuario) {
            return redirect()->route('recuperar')->with('mensaje', '❌ El enlace es inválido o ya expiró. Solicitá uno nuevo.');
        }

        $usuario->update([
            'password'     => bcrypt($request->input('password')),
            'reset_token'  => null,
            'reset_expira' => null,
        ]);

        return redirect('/')->with('login_success', '✅ Contraseña cambiada correctamente. Ya podés iniciar sesión.');
    }

    public function registroAficionado(Request $request)
    {
        if (!$this->verifyTurnstile($request->input('cf-turnstile-response'))) {
            return back()->with('registro_msg', '⚠️ Error de verificación de seguridad (Captcha).')->withInput();
        }

        $data = $request->validate([
            'nombre' => 'required|string|max:100',
            'apellido' => 'required|string|max:100',
            'dni' => 'required|string|unique:aficionados,dni',
            'email' => 'required|email|unique:aficionados,email',
            'fecha_nacimiento' => 'nullable|date',
            'telefono' => 'nullable|string|max:50',
            'localidad' => 'nullable|string|max:100',
            'password' => 'required|confirmed|min:6',
        ]);

        $data['password'] = bcrypt($data['password']);
        $data['fecha_registro'] = now();

        $aficionado = Aficionado::create($data);

        try {
            Mail::to($aficionado->email)->send(new WelcomeMail($aficionado, 'aficionado'));
        } catch (\Exception $e) {
            Log::error("Error enviando mail de bienvenida a Aficionado: " . $e->getMessage());
        }

        return redirect()->route('asociate')->with('mensaje', '✅ Te registraste correctamente. Ya podés iniciar sesión.');
    }

    public function buscarJugador(Request $request)
    {
        $request->validate([
            'nombre' => 'required|string',
            'apellido' => 'required|string',
            'dni' => 'required|string',
            'acepto' => 'required',
        ]);

        $dni = preg_replace('/[^0-9]/', '', $request->input('dni'));
        $nombre = strtoupper(trim($request->input('nombre')));
        $apellido = strtoupper(trim($request->input('apellido')));

        // Buscar jugador por DNI
        $jugador = Jugador::where('documento', $dni)->first();

        if (!$jugador) {
            // Verificar si ya está registrado como aficionado
            $aficionado = Aficionado::where('dni', $dni)->first();
            if ($aficionado) {
                return redirect()->route('asociate')->with('mensaje', '⚠️ Ya estás registrado como aficionado.');
            }
            // No existe - se debe registrar como aficionado
            return redirect()->route('asociate')->with('mensaje', '⚠️ No encontramos tu registro como jugador. Podés registrarte como aficionado.');
        }

        // --- Lógica Smart Match ---
        $nombreEnBD = $this->normalizeString($jugador->nombre ?? '');
        $apellidoEnBD = $this->normalizeString($jugador->apellido ?? '');
        $terminosBD = explode(' ', $nombreEnBD . ' ' . $apellidoEnBD);
        
        $palabrasNombreIn = explode(' ', $this->normalizeString($nombre));
        $palabrasApellidoIn = explode(' ', $this->normalizeString($apellido));

        $nombreCoincide = false;
        foreach ($palabrasNombreIn as $p) {
            if ($this->isApproxMatch($p, $terminosBD)) {
                $nombreCoincide = true;
                break;
            }
        }

        $apellidoCoincide = false;
        foreach ($palabrasApellidoIn as $p) {
            if ($this->isApproxMatch($p, $terminosBD)) {
                $apellidoCoincide = true;
                break;
            }
        }

        if (!$nombreCoincide || !$apellidoCoincide) {
            return redirect()->route('asociate')->with('mensaje', '⚠️ El DNI ingresado no coincide con el Nombre y Apellido proporcionados. Por favor, verifica tus datos.');
        }
        // --- Fin Smart Match ---

        if ($jugador->activo) {
            return redirect()->route('asociate')->with('registro_msg', 'Este jugador ya está registrado en el sistema.');
        }

        // Jugador encontrado e inactivo - mostrar formulario para completar
        $club = null;
        if ($jugador->id_club_actual) {
            $clubObj = \App\Models\Club::find($jugador->id_club_actual);
            $club = $clubObj ? $clubObj->nombre : null;
        }

        $jugador_encontrado = [
            'documento' => $jugador->documento,
            'nombre' => $jugador->nombre,
            'apellido' => $jugador->apellido,
            'fecha_nacimiento' => $jugador->fecha_nacimiento,
            'club' => $club,
            'categoria' => $jugador->categoria,
        ];

        return view('auth.asociate', compact('jugador_encontrado'))->with('tab', 'jugador');
    }

    public function completarRegistroJugador(Request $request)
    {
        if (!$this->verifyTurnstile($request->input('cf-turnstile-response'))) {
            return back()->with('registro_msg', '⚠️ Error de verificación de seguridad (Captcha).')->withInput();
        }

        $request->validate([
            'dni' => 'required|string',
            'email' => 'required|email',
            'telefono' => 'nullable|string',
            'password' => 'required|confirmed|min:6',
        ]);

        $dni = preg_replace('/[^0-9]/', '', $request->input('dni'));

        $jugador = Jugador::where('documento', $dni)->first();

        if (!$jugador) {
            return redirect()->route('asociate')->with('registro_msg', 'Jugador no encontrado.');
        }

        if ($jugador->activo) {
            return redirect()->route('asociate')->with('registro_msg', 'Este jugador ya está registrado.');
        }

        $jugador->update([
            'email'    => $request->input('email'),
            'telefono' => $request->input('telefono'),
            'password' => bcrypt($request->input('password')),
            'activo'   => 1,
            'fecha_registro' => now(),
        ]);

        try {
            Mail::to($jugador->email)->send(new WelcomeMail($jugador, 'jugador'));
        } catch (\Exception $e) {
            Log::error("Error enviando mail de bienvenida a Jugador: " . $e->getMessage());
        }

        return redirect()->route('asociate')->with('mensaje', '✅ Registro completado exitosamente. Ya podés iniciar sesión.');
    }

    /**
     * Normaliza un string para comparaciones (mayúsculas, sin acentos, sin espacios extras)
     */
    private function normalizeString($str)
    {
        $unwanted_array = ['Š'=>'S', 'š'=>'s', 'Ž'=>'Z', 'ž'=>'z', 'À'=>'A', 'Á'=>'A', 'Â'=>'A', 'Ã'=>'A', 'Ä'=>'A', 'Å'=>'A', 'Æ'=>'A', 'Ç'=>'C', 'È'=>'E', 'É'=>'E',
                            'Ê'=>'E', 'Ë'=>'E', 'Ì'=>'I', 'Í'=>'I', 'Î'=>'I', 'Ï'=>'I', 'Ñ'=>'N', 'Ò'=>'O', 'Ó'=>'O', 'Ô'=>'O', 'Õ'=>'O', 'Ö'=>'O', 'Ø'=>'O', 'Ù'=>'U',
                            'Ú'=>'U', 'Û'=>'U', 'Ü'=>'U', 'Ý'=>'Y', 'Þ'=>'B', 'ß'=>'Ss', 'à'=>'a', 'á'=>'a', 'â'=>'a', 'ã'=>'a', 'ä'=>'a', 'å'=>'a', 'æ'=>'a', 'ç'=>'c',
                            'è'=>'e', 'é'=>'e', 'ê'=>'e', 'ë'=>'e', 'ì'=>'i', 'í'=>'i', 'î'=>'i', 'ï'=>'i', 'ð'=>'o', 'ñ'=>'n', 'ò'=>'o', 'ó'=>'o', 'ô'=>'o', 'õ'=>'o',
                            'ö'=>'o', 'ø'=>'o', 'ù'=>'u', 'ú'=>'u', 'û'=>'u', 'ý'=>'y', 'þ'=>'b', 'ÿ'=>'y'];
        
        $str = strtr($str, $unwanted_array);
        return strtoupper(trim(preg_replace('/\s+/', ' ', $str)));
    }

    /**
     * Comprueba si una palabra coincide aproximadamente con alguna de la lista
     */
    private function isApproxMatch($word, $list)
    {
        if (strlen($word) < 3) return false;

        foreach ($list as $item) {
            if (strlen($item) < 3) continue;

            // Coincidencia exacta o contenida
            if ($word === $item || strpos($item, $word) !== false || strpos($word, $item) !== false) {
                return true;
            }

            // Levenshtein para errores de tipeo (máximo 1 de distancia)
            if (levenshtein($word, $item) <= 1) {
                return true;
            }
        }
        return false;
    }
}
