<?php

namespace App\Http\Controllers\Api;

use App\Http\Controllers\Controller;
use App\Http\Requests\ChangePasswordRequest;
use App\Http\Requests\LoginRequest;
use App\Http\Requests\UpdateProfileRequest;
use App\Http\Resources\UserResource;
use App\Models\User;
use App\Services\ActivityLogService;
use Illuminate\Auth\Events\PasswordReset;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Password;
use Illuminate\Support\Facades\Schema;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Str;

class AuthController extends Controller
{
    public function __construct(protected ActivityLogService $activityLogService) {}

    public function login(LoginRequest $request): JsonResponse
    {
        try {
            $credentials = $request->validated();
            $identifier = strtolower(trim($credentials['identifier']));

            $user = $this->findUserForLogin($identifier);

            if (! $user || ! Hash::check($credentials['password'], $user->password)) {
                $this->logAuthEvent(null, 'failed_login', 'تلاش ناموفق ورود', $request, $identifier);

                return response()->json([
                    'success' => false,
                    'message' => 'نام کاربری یا رمز عبور اشتباه است',
                ], 401);
            }

            if ($user->status !== null && $user->status !== 'active') {
                $this->logAuthEvent($user->id, 'blocked_login', 'تلاش ورود کاربر غیرفعال', $request, $identifier);

                return response()->json([
                    'success' => false,
                    'message' => 'امکان ورود با این اطلاعات وجود ندارد',
                ], 403);
            }

            $token = $user->createToken('api-token')->plainTextToken;

            $user->load(['roles.permissions']);
            $this->logAuthEvent($user->id, 'login', 'ورود موفق به سیستم', $request, $identifier);

            return response()->json([
                'success' => true,
                'data' => [
                    'user' => new UserResource($user),
                    'token' => $token,
                    'permissions' => $user->roles->flatMap(function ($role) {
                        return $role->permissions->pluck('name');
                    })->unique()->values(),
                ],
                'message' => 'ورود با موفقیت انجام شد',
            ]);
        } catch (\Exception $e) {
            Log::error('Login failed unexpectedly', [
                'identifier_hash' => isset($identifier) ? hash('sha256', $identifier) : null,
                'exception' => $e,
            ]);

            return response()->json([
                'success' => false,
                'message' => 'خطا در ورود به سیستم',
            ], 500);
        }
    }

    private function findUserForLogin(string $identifier): ?User
    {
        $query = User::query()
            ->whereRaw('LOWER(email) = ?', [$identifier])
            ->orWhereRaw('LOWER(name) = ?', [$identifier]);

        if (Schema::hasColumn('users', 'username')) {
            $query->orWhereRaw('LOWER(username) = ?', [$identifier]);
        }

        $user = $query->orderBy('id')->first();

        if ($user || str_contains($identifier, '@')) {
            return $user;
        }

        $emailPrefixMatches = User::query()
            ->whereRaw('LOWER(email) LIKE ?', [$identifier.'@%'])
            ->limit(2)
            ->get();

        return $emailPrefixMatches->count() === 1 ? $emailPrefixMatches->first() : null;
    }

    public function logout(Request $request): JsonResponse
    {
        try {
            $this->logAuthEvent($request->user()?->id, 'logout', 'خروج از سیستم', $request);
            $request->user()->currentAccessToken()?->delete();

            return response()->json([
                'success' => true,
                'message' => 'خروج با موفقیت انجام شد',
            ]);
        } catch (\Exception $e) {
            return response()->json([
                'success' => false,
                'message' => 'خطا در خروج از سیستم',
            ], 500);
        }
    }

    public function user(Request $request): JsonResponse
    {
        try {
            $user = $request->user()->load(['roles.permissions']);

            return response()->json([
                'success' => true,
                'data' => new UserResource($user),
                'message' => 'اطلاعات کاربر',
            ]);
        } catch (\Exception $e) {
            return response()->json([
                'success' => false,
                'message' => 'خطا در دریافت اطلاعات کاربر',
            ], 500);
        }
    }

    public function updateProfile(UpdateProfileRequest $request): JsonResponse
    {
        try {
            $user = $request->user();
            $user->update($request->validated());

            return response()->json([
                'success' => true,
                'data' => new UserResource($user->fresh()),
                'message' => 'پروفایل با موفقیت به‌روزرسانی شد',
            ]);
        } catch (\Exception $e) {
            return response()->json([
                'success' => false,
                'message' => 'خطا در به‌روزرسانی پروفایل',
            ], 500);
        }
    }

    public function updateAvatar(Request $request): JsonResponse
    {
        try {
            $request->validate([
                'avatar' => 'required|image|mimes:jpg,jpeg,png,webp|max:2048',
            ]);

            $user = $request->user();
            if ($user->avatar && $user->avatar !== 'avatars/default.png' && Storage::disk('public')->exists($user->avatar)) {
                Storage::disk('public')->delete($user->avatar);
            }

            $path = $request->file('avatar')->store('avatars', 'public');
            $user->update(['avatar' => $path]);

            return response()->json([
                'success' => true,
                'data' => new UserResource($user->fresh()),
                'message' => 'عکس پروفایل با موفقیت به‌روزرسانی شد',
            ]);
        } catch (\Exception $e) {
            return response()->json([
                'success' => false,
                'message' => 'خطا در به‌روزرسانی عکس پروفایل',
            ], 500);
        }
    }

    public function changePassword(ChangePasswordRequest $request): JsonResponse
    {
        try {
            $user = $request->user();

            if (! Hash::check($request->current_password, $user->password)) {
                return response()->json([
                    'success' => false,
                    'message' => 'رمز عبور فعلی اشتباه است',
                ], 400);
            }

            $user->update(['password' => Hash::make($request->new_password)]);
            $user->tokens()->delete();

            return response()->json([
                'success' => true,
                'message' => 'رمز عبور با موفقیت تغییر یافت',
                'reauthentication_required' => true,
            ]);
        } catch (\Exception $e) {
            return response()->json([
                'success' => false,
                'message' => 'خطا در تغییر رمز عبور',
            ], 500);
        }
    }

    public function forgotPassword(Request $request): JsonResponse
    {
        $data = $request->validate(['email' => 'required|email']);
        Password::sendResetLink(['email' => strtolower($data['email'])]);

        return response()->json([
            'success' => true,
            'message' => 'اگر حسابی با این ایمیل وجود داشته باشد، لینک بازیابی ارسال می‌شود.',
        ]);
    }

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

        $status = Password::reset(
            $data,
            function (User $user, string $password) {
                $user->forceFill([
                    'password' => Hash::make($password),
                    'remember_token' => Str::random(60),
                ])->save();
                $user->tokens()->delete();
                event(new PasswordReset($user));
            }
        );

        if ($status !== Password::PASSWORD_RESET) {
            return response()->json([
                'success' => false,
                'message' => 'توکن بازیابی نامعتبر یا منقضی شده است.',
            ], 422);
        }

        return response()->json([
            'success' => true,
            'message' => 'رمز عبور تغییر کرد. دوباره وارد شوید.',
        ]);
    }

    private function logAuthEvent(?int $userId, string $action, string $description, Request $request, ?string $identifier = null): void
    {
        try {
            $properties = [
                'ip' => $request->ip(),
                'user_agent' => substr((string) $request->userAgent(), 0, 255),
            ];

            if ($identifier) {
                $properties['identifier_hash'] = hash('sha256', strtolower($identifier));
            }

            $this->activityLogService->log($userId, $action, $description, 'auth', $userId, null, null, $properties);
        } catch (\Throwable $e) {
            Log::warning('Auth activity log failed', [
                'user_id' => $userId,
                'action' => $action,
                'exception' => $e,
            ]);
        }
    }
}
