<?php

namespace App\Http\Controllers;

use App\Models\Usuario;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Mail;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;
use Illuminate\Validation\ValidationException;

class AuthController extends Controller
{
    /**
     * Login de usuario
     * POST /api/auth/login
     */
    public function login(Request $request)
    {
        // Validar solo los campos necesarios, ignorar campos extra del frontend
        $validated = $request->validate([
            'email' => 'required|email',
            'password' => 'required|string|min:6'
        ]);

        $usuario = Usuario::where('email', $validated['email'])->first();

        // Validar usuario existe
        if (!$usuario) {
            throw ValidationException::withMessages([
                'email' => ['El correo electrónico no está registrado.'],
            ]);
        }

        // Validar password
        if (!Hash::check($validated['password'], $usuario->password)) {
            throw ValidationException::withMessages([
                'password' => ['La contraseña es incorrecta.'],
            ]);
        }

        // Validar estado activo
        if ($usuario->estado !== 'activo') {
            throw ValidationException::withMessages([
                'email' => ['Tu cuenta está ' . $usuario->estado . '. Contacta al administrador.'],
            ]);
        }

        // Generar API Token
        $token = $usuario->generateApiToken();

        return response()->json([
            'success' => true,
            'message' => 'Inicio de sesión exitoso',
            'data' => [
                'user' => [
                    'id' => $usuario->id,
                    'nombre' => $usuario->nombre,
                    'email' => $usuario->email,
                    'picture' => $usuario->picture,
                    'estado' => $usuario->estado
                ],
                'token' => $token
            ]
        ]);
    }

    /**
     * Registro de nuevo usuario
     * POST /api/auth/register
     * 
     * Lógica de contraseña:
     * - Si se proporciona password, se usa ese
     * - Si no hay password pero sí cédula, usa la cédula como password
     * - Si no hay ni password ni cédula, genera password aleatoria
     */
    public function register(Request $request)
    {
        $request->validate([
            'nombre' => 'required|string|max:100',
            'email' => 'required|email|max:150|unique:usuarios,email',
            'password' => 'nullable|string|min:6|confirmed',
            'telefono' => 'nullable|string|max:20',
            'cedula' => 'nullable|string|max:20'
        ]);

        // Determinar la contraseña a usar
        $passwordGenerada = null;
        $passwordTextoPlano = null;

        if ($request->filled('password')) {
            // Si el usuario proporciona una contraseña, usarla
            $passwordTextoPlano = $request->password;
        } elseif ($request->filled('cedula')) {
            // Si no hay password pero sí cédula, usar la cédula como password
            $passwordTextoPlano = $request->cedula;
            $passwordGenerada = $request->cedula;
        } else {
            // Si no hay ni password ni cédula, generar una aleatoria
            $passwordTextoPlano = $this->generarPasswordAleatoria();
            $passwordGenerada = $passwordTextoPlano;
        }

        $usuario = Usuario::create([
            'nombre' => $request->nombre,
            'email' => $request->email,
            'password' => Hash::make($passwordTextoPlano),
            'telefono' => $request->telefono,
            'cedula' => $request->cedula,
            'estado' => 'activo',
            'saldo_disponible' => 0,
            'saldo_pendiente' => 0,
            'saldo_total' => 0
        ]);

        // Generar token automáticamente
        $token = $usuario->generateApiToken();

        // Si se generó una contraseña, enviar notificación por email
        if ($passwordGenerada) {
            $this->enviarPasswordPorEmail($usuario, $passwordGenerada);
        }

        $responseData = [
            'user' => [
                'id' => $usuario->id,
                'nombre' => $usuario->nombre,
                'email' => $usuario->email,
                'estado' => $usuario->estado
            ],
            'token' => $token
        ];

        // Si se generó password, incluirla en la respuesta (solo para testing/admin)
        if ($passwordGenerada) {
            $responseData['password_generada'] = $passwordGenerada;
            $responseData['mensaje_password'] = 'Se ha enviado un correo con la contraseña generada';
        }

        return response()->json([
            'success' => true,
            'message' => 'Usuario registrado exitosamente',
            'data' => $responseData
        ], 201);
    }

    /**
     * Generar contraseña aleatoria segura
     */
    private function generarPasswordAleatoria(): string
    {
        // Generar password de 10 caracteres: letras mayúsculas, minúsculas y números
        $caracteres = 'ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnpqrstuvwxyz23456789';
        $password = '';
        $longitudCaracteres = strlen($caracteres);
        
        for ($i = 0; $i < 10; $i++) {
            $password .= $caracteres[random_int(0, $longitudCaracteres - 1)];
        }
        
        return $password;
    }

    /**
     * Enviar contraseña por correo electrónico
     */
    private function enviarPasswordPorEmail($usuario, $password)
    {
        // TODO: Implementar envío de email real
        // Por ahora, registrar en los logs
        \Log::info('Password generada para usuario', [
            'usuario_id' => $usuario->id,
            'nombre' => $usuario->nombre,
            'email' => $usuario->email,
            'password' => $password
        ]);

        // Crear una notificación en el sistema
        try {
            \App\Models\Notificacion::create([
                'usuario_id' => $usuario->id,
                'tipo' => 'sistema',
                'titulo' => 'Bienvenido a ScaWatts',
                'contenido' => "Tu cuenta ha sido creada exitosamente. Tu contraseña es: {$password}. Por seguridad, te recomendamos cambiarla después de tu primer inicio de sesión.",
                'leido' => false,
                'icono' => 'key'
            ]);
        } catch (\Exception $e) {
            \Log::warning('No se pudo crear notificación de bienvenida: ' . $e->getMessage());
        }
    }

    /**
     * Logout - revocar token
     * POST /api/auth/logout
     */
    public function logout(Request $request)
    {
        $usuario = $request->user();
        
        if ($usuario) {
            $usuario->revokeApiToken();
        }

        return response()->json([
            'success' => true,
            'message' => 'Sesión cerrada exitosamente'
        ]);
    }

    /**
     * Obtener usuario autenticado
     * GET /api/auth/user
     */
    public function user(Request $request)
    {
        $usuario = $request->user();

        return response()->json([
            'success' => true,
            'data' => [
                'id' => $usuario->id,
                'nombre' => $usuario->nombre,
                'email' => $usuario->email,
                'telefono' => $usuario->telefono,
                'cedula' => $usuario->cedula,
                'estado' => $usuario->estado,
                'saldo_disponible' => $usuario->saldo_disponible,
                'saldo_pendiente' => $usuario->saldo_pendiente,
                'saldo_total' => $usuario->saldo_total,
                'fecha_registro' => $usuario->fecha_registro
            ]
        ]);
    }

    /**
     * Cambiar contraseña
     * POST /api/auth/change-password
     */
    public function changePassword(Request $request)
    {
        $request->validate([
            'current_password' => 'required|string',
            'new_password' => 'required|string|min:6|confirmed'
        ]);

        $usuario = $request->user();

        // Validar contraseña actual
        if (!Hash::check($request->current_password, $usuario->password)) {
            throw ValidationException::withMessages([
                'current_password' => ['La contraseña actual es incorrecta.'],
            ]);
        }

        // Actualizar contraseña
        $usuario->password = Hash::make($request->new_password);
        $usuario->save();

        // Revocar token actual (forzar nuevo login)
        $usuario->revokeApiToken();

        return response()->json([
            'success' => true,
            'message' => 'Contraseña actualizada exitosamente. Por favor inicia sesión nuevamente.'
        ]);
    }
    
    /**
     * Google OAuth - Login/Register
     * POST /api/auth/google
     */
    public function googleAuth(Request $request)
    {
        $request->validate([
            'googleUser' => 'required|array',
            'googleUser.id' => 'required|string',
            'googleUser.email' => 'required|email',
            'googleUser.name' => 'required|string',
            'googleUser.picture' => 'nullable|string'
        ]);
        
        $googleData = $request->input('googleUser');
        
        try {
            // Buscar usuario por Google ID o email
            $usuario = Usuario::where('google_id', $googleData['id'])
                ->orWhere('email', $googleData['email'])
                ->first();

            if ($usuario) {
                // Usuario existe - actualizar datos de Google sin sobreescribir avatar personalizado
                $updateData = [
                    'google_id' => $googleData['id'],
                    'nombre' => $googleData['name'] ?? $usuario->nombre,
                ];

                $googlePicture = $googleData['picture'] ?? null;
                if ($this->debeActualizarAvatarConProveedor($usuario->picture, $googlePicture)) {
                    $updateData['picture'] = $googlePicture;
                }

                $usuario->update($updateData);

                $message = 'Inicio de sesión con Google exitoso';
            } else {
                // Usuario NO existe - crear nuevo usuario
                $usuario = Usuario::create([
                    'google_id' => $googleData['id'],
                    'nombre' => $googleData['name'],
                    'email' => $googleData['email'],
                    'picture' => $googleData['picture'] ?? null,
                    // Generamos una contraseña aleatoria para cumplir con restricciones de la BD
                    'password' => Str::random(40),
                    'estado' => 'activo',
                    'saldo_disponible' => 0,
                    'saldo_pendiente' => 0,
                    'saldo_total' => 0
                ]);

                $message = 'Registro con Google exitoso';
            }

            // Generar token
            $token = $usuario->generateApiToken();

            return response()->json([
                'success' => true,
                'message' => $message,
                'data' => [
                    'user' => [
                        'id' => $usuario->id,
                        'nombre' => $usuario->nombre,
                        'email' => $usuario->email,
                        'picture' => $usuario->picture,
                        'estado' => $usuario->estado
                    ],
                    'token' => $token
                ]
            ]);
        } catch (\Exception $e) {
            \Log::error('Error en Google Sign-In', [
                'exception' => $e->getMessage(),
                'google_id' => $googleData['id'],
                'email' => $googleData['email']
            ]);

            return response()->json([
                'success' => false,
                'message' => 'Error al autenticar con Google. Por favor intenta nuevamente.'
            ], 500);
        }
    }
    
    /**
     * Autenticación con Apple Sign In
     * POST /api/auth/apple
     * 
     * @param Request $request
     * @return \Illuminate\Http\JsonResponse
     */
    public function appleAuth(Request $request)
    {
        $request->validate([
            'appleUser' => 'required|array',
            'appleUser.user' => 'required|string', // Apple User ID (único)
            'appleUser.email' => 'nullable|email', // Email (solo primera vez)
            'appleUser.fullName' => 'nullable|array', // Nombre (solo primera vez)
            'identityToken' => 'required|string' // JWT token de Apple
        ]);
        
        $appleData = $request->input('appleUser');
        $identityToken = $request->input('identityToken');
        
        try {
            // Verificar el token de Apple (básico - en producción usar verificación completa de JWT)
            // Apple envía el email solo la primera vez, después solo el user ID
            
            // Buscar usuario por Apple ID
            $usuario = Usuario::where('apple_id', $appleData['user'])->first();
            
            if ($usuario) {
                // Usuario existe - actualizar datos si vienen
                $updateData = [
                    'apple_id' => $appleData['user']
                ];
                
                // Apple solo envía estos datos la primera vez
                if (isset($appleData['email']) && $appleData['email']) {
                    $updateData['email'] = $appleData['email'];
                }
                
                if (isset($appleData['fullName']) && is_array($appleData['fullName'])) {
                    $fullName = trim(
                        ($appleData['fullName']['givenName'] ?? '') . ' ' . 
                        ($appleData['fullName']['familyName'] ?? '')
                    );
                    if ($fullName) {
                        $updateData['nombre'] = $fullName;
                    }
                }
                
                $usuario->update($updateData);
                $message = 'Inicio de sesión con Apple exitoso';
                
            } else {
                // Usuario NO existe - verificar que tengamos email
                if (!isset($appleData['email']) || !$appleData['email']) {
                    return response()->json([
                        'success' => false,
                        'message' => 'No se recibió el email de Apple. Por favor intenta de nuevo.'
                    ], 400);
                }
                
                // Verificar si existe usuario con ese email (vinculación)
                $usuarioExistente = Usuario::where('email', $appleData['email'])->first();
                
                if ($usuarioExistente) {
                    // Vincular cuenta existente con Apple ID
                    $usuarioExistente->update([
                        'apple_id' => $appleData['user']
                    ]);
                    $usuario = $usuarioExistente;
                    $message = 'Cuenta vinculada con Apple exitosamente';
                } else {
                    // Crear nuevo usuario
                    $fullName = 'Usuario Apple';
                    if (isset($appleData['fullName']) && is_array($appleData['fullName'])) {
                        $fullName = trim(
                            ($appleData['fullName']['givenName'] ?? '') . ' ' . 
                            ($appleData['fullName']['familyName'] ?? '')
                        );
                        if (!$fullName) {
                            $fullName = 'Usuario Apple';
                        }
                    }
                    
                    $usuario = Usuario::create([
                        'apple_id' => $appleData['user'],
                        'nombre' => $fullName,
                        'email' => $appleData['email'],
                        'password' => null, // Sin contraseña para usuarios de Apple
                        'estado' => 'activo',
                        'saldo_disponible' => 0,
                        'saldo_total' => 0
                    ]);
                    
                    $message = 'Registro con Apple exitoso';
                }
            }
            
            // Generar token
            $token = $usuario->generateApiToken();
            
            return response()->json([
                'success' => true,
                'message' => $message,
                'token' => $token,
                'user' => [
                    'id' => $usuario->id,
                    'nombre' => $usuario->nombre,
                    'email' => $usuario->email,
                    'picture' => $usuario->picture,
                    'estado' => $usuario->estado
                ]
            ]);
            
        } catch (\Exception $e) {
            return response()->json([
                'success' => false,
                'message' => 'Error al autenticar con Apple: ' . $e->getMessage()
            ], 500);
        }
    }
    
    /**
     * Solicitar recuperación de contraseña (envía código por email)
     * POST /api/auth/forgot-password
     */
    public function forgotPassword(Request $request)
    {
        $request->validate([
            'email' => 'required|email'
        ]);
        
        // Verificar que el usuario existe
        $usuario = Usuario::where('email', $request->email)->first();
        
        if (!$usuario) {
            return response()->json([
                'success' => false,
                'message' => 'No existe un usuario con ese correo electrónico.'
            ], 404);
        }
        
        // Verificar que no sea usuario de Google (no tienen password)
        if ($usuario->google_id && !$usuario->password) {
            return response()->json([
                'success' => false,
                'message' => 'Esta cuenta usa Google Sign-In. Por favor inicia sesión con Google.'
            ], 400);
        }
        
        try {
            // Generar código de 6 dígitos
            $code = str_pad(random_int(0, 999999), 6, '0', STR_PAD_LEFT);
            
            // Guardar código en BD (válido por 15 minutos)
            DB::table('password_resets')->updateOrInsert(
                ['email' => $request->email],
                [
                    'code' => $code,
                    'expires_at' => now()->addMinutes(15),
                    'created_at' => now(),
                    'updated_at' => now()
                ]
            );
            
            // Enviar email con el código
            Mail::send('emails.reset-password', ['code' => $code, 'nombre' => $usuario->nombre], function ($message) use ($request) {
                $message->to($request->email)
                        ->subject('Código de recuperación de contraseña - ScaWatts');
            });
            
            return response()->json([
                'success' => true,
                'message' => 'Código de recuperación enviado a tu correo electrónico. Válido por 15 minutos.'
            ]);
            
        } catch (\Exception $e) {
            return response()->json([
                'success' => false,
                'message' => 'Error al enviar el código: ' . $e->getMessage()
            ], 500);
        }
    }
    
    /**
     * Resetear contraseña con código
     * POST /api/auth/reset-password
     */
    public function resetPassword(Request $request)
    {
        $request->validate([
            'email' => 'required|email',
            'code' => 'required|string|size:6',
            'password' => 'required|string|min:6|confirmed'
        ]);
        
        // Buscar código en BD
        $reset = DB::table('password_resets')
            ->where('email', $request->email)
            ->where('code', $request->code)
            ->first();
        
        if (!$reset) {
            return response()->json([
                'success' => false,
                'message' => 'Código incorrecto o email no válido.'
            ], 400);
        }
        
        // Verificar que no haya expirado
        if (now()->greaterThan($reset->expires_at)) {
            DB::table('password_resets')->where('email', $request->email)->delete();
            
            return response()->json([
                'success' => false,
                'message' => 'El código ha expirado. Solicita uno nuevo.'
            ], 400);
        }
        
        try {
            // Actualizar contraseña
            $usuario = Usuario::where('email', $request->email)->first();
            $usuario->password = Hash::make($request->password);
            $usuario->save();
            
            // Eliminar código usado
            DB::table('password_resets')->where('email', $request->email)->delete();
            
            return response()->json([
                'success' => true,
                'message' => 'Contraseña actualizada exitosamente. Ya puedes iniciar sesión.'
            ]);
            
        } catch (\Exception $e) {
            return response()->json([
                'success' => false,
                'message' => 'Error al actualizar contraseña: ' . $e->getMessage()
            ], 500);
        }
    }

    private function debeActualizarAvatarConProveedor(?string $actual, ?string $nuevo): bool
    {
        if (!$nuevo) {
            return false;
        }

        if (!$actual) {
            return true;
        }

        if ($this->tieneAvatarPersonalizado($actual)) {
            return false;
        }

        return true;
    }

    private function tieneAvatarPersonalizado(?string $url): bool
    {
        if (!$url) {
            return false;
        }

        return Str::contains($url, ['/storage/avatars/', '/storage/usuarios/', '/storage/perfiles/']);
    }
}
