<?php

namespace App\Http\Controllers\Api\V1;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Password;
use App\Models\User;
use Illuminate\Validation\ValidationException;

class AuthController extends BaseController
{
    /**
     * Authenticate user and return token.
     *
     * @param Request $request
     * @return JsonResponse
     */
    public function login(Request $request)
    {
        try {
            $validated = $request->validate([
                'login' => 'required|string',
                'password' => 'required|string',
                'role' => 'required|in:student,instructor,admin',
                'remember_me' => 'nullable|boolean',
            ]);

            // Find user based on role and login type
            if ($validated['role'] === 'student') {
                $user = User::where('school_id', $validated['login'])
                    ->where('role', 'student')
                    ->first();
            } else {
                $user = User::where('email', $validated['login'])
                    ->where('role', $validated['role'])
                    ->first();
            }

            // Check credentials
            if (!$user || !Hash::check($validated['password'], $user->password)) {
                return $this->error('Invalid credentials.', null, 401);
            }

            // Revoke existing tokens for security (single device login)
            $user->tokens()->delete();

            // Create token with device information
            $deviceInfo = $this->getDeviceInfo($request);
            $tokenName = $validated['role'] . '_' . ($validated['remember_me'] ?? false ? 'remember' : 'session') . '_' . $deviceInfo;
            $token = $user->createToken($tokenName, ['*'])->plainTextToken;

            // Calculate expiration (24 hours default, or longer if remember_me)
            $expiresAt = now()->addHours($validated['remember_me'] ?? false ? 720 : 24);

            return $this->success([
                'user' => [
                    'id' => $user->id,
                    'name' => $user->name,
                    'email' => $user->email,
                    'school_id' => $user->school_id,
                    'role' => $user->role,
                    'phone' => $user->phone,
                    'address' => $user->address,
                    'profile_picture' => $user->profile_picture ? $this->getProfilePictureUrl($user) : null,
                    'email_verified_at' => $user->email_verified_at,
                    'created_at' => $user->created_at,
                ],
                'token' => $token,
                'token_type' => 'Bearer',
                'expires_at' => $expiresAt->toDateTimeString(),
            ], 'Login successful');
        } catch (ValidationException $e) {
            return $this->error('Validation failed', $e->errors(), 422);
        } catch (\Exception $e) {
            Log::error('API Login error: ' . $e->getMessage());
            return $this->error('An error occurred during login. Please try again.', null, 500);
        }
    }

    /**
     * Get authenticated user.
     *
     * @param Request $request
     * @return JsonResponse
     */
    public function user(Request $request)
    {
        try {
            $user = $request->user();

            return $this->success([
                'id' => $user->id,
                'name' => $user->name,
                'email' => $user->email,
                'school_id' => $user->school_id,
                'role' => $user->role,
                'phone' => $user->phone,
                'address' => $user->address,
                'profile_picture' => $user->profile_picture ? $this->getProfilePictureUrl($user) : null,
                'email_verified_at' => $user->email_verified_at,
                'created_at' => $user->created_at,
            ]);
        } catch (\Exception $e) {
            Log::error('API Get User error: ' . $e->getMessage());
            return $this->error('An error occurred. Please try again.', null, 500);
        }
    }

    /**
     * Logout user and revoke token.
     *
     * @param Request $request
     * @return JsonResponse
     */
    public function logout(Request $request)
    {
        try {
            // Revoke current token
            $request->user()->currentAccessToken()->delete();

            return $this->success(null, 'Successfully logged out');
        } catch (\Exception $e) {
            Log::error('API Logout error: ' . $e->getMessage());
            return $this->error('An error occurred during logout.', null, 500);
        }
    }

    /**
     * Send password reset link.
     *
     * @param Request $request
     * @return JsonResponse
     */
    public function sendPasswordResetLink(Request $request)
    {
        try {
            $validated = $request->validate([
                'email' => 'required|email|exists:users,email',
            ]);

            // Use Laravel's built-in password reset
            $status = Password::sendResetLink(
                $request->only('email')
            );

            if ($status === Password::RESET_LINK_SENT) {
                return $this->success(null, 'Password reset link sent to your email');
            }

            return $this->error('Unable to send password reset link.', null, 400);
        } catch (ValidationException $e) {
            return $this->error('Validation failed', $e->errors(), 422);
        } catch (\Exception $e) {
            Log::error('API Password Reset Link error: ' . $e->getMessage());
            return $this->error('An error occurred. Please try again.', null, 500);
        }
    }

    /**
     * Reset password.
     *
     * @param Request $request
     * @return JsonResponse
     */
    public function resetPassword(Request $request)
    {
        try {
            $validated = $request->validate([
                'token' => 'required|string',
                'email' => 'required|email',
                'password' => 'required|string|min:8|confirmed',
            ]);

            $status = Password::reset(
                $request->only('email', 'password', 'password_confirmation', 'token'),
                function ($user, $password) {
                    $user->password = Hash::make($password);
                    $user->save();
                }
            );

            if ($status === Password::PASSWORD_RESET) {
                return $this->success(null, 'Password reset successfully');
            }

            return $this->error('Unable to reset password.', null, 400);
        } catch (ValidationException $e) {
            return $this->error('Validation failed', $e->errors(), 422);
        } catch (\Exception $e) {
            Log::error('API Password Reset error: ' . $e->getMessage());
            return $this->error('An error occurred. Please try again.', null, 500);
        }
    }

    /**
     * Get device information for token naming.
     *
     * @param Request $request
     * @return string
     */
    private function getDeviceInfo(Request $request): string
    {
        $userAgent = $request->header('User-Agent', 'Unknown');
        $ip = $request->ip();
        
        // Create a unique but readable device identifier
        $deviceHash = substr(md5($userAgent . $ip), 0, 8);
        
        // Detect device type
        if (strpos($userAgent, 'Mobile') !== false) {
            return 'mobile_' . $deviceHash;
        } elseif (strpos($userAgent, 'Tablet') !== false) {
            return 'tablet_' . $deviceHash;
        } else {
            return 'desktop_' . $deviceHash;
        }
    }

    /**
     * Get profile picture URL (decrypt if encrypted).
     *
     * @param User $user
     * @return string|null
     */
    private function getProfilePictureUrl(User $user): ?string
    {
        try {
            if (!$user->profile_picture) {
                return null;
            }

            // Try to decrypt if it's encrypted
            try {
                $decrypted = \Illuminate\Support\Facades\Crypt::decryptString($user->profile_picture);
                return $decrypted;
            } catch (\Exception $e) {
                // If decryption fails, return as is (might be a URL)
                return $user->profile_picture;
            }
        } catch (\Exception $e) {
            return null;
        }
    }
}
