<?php

namespace App\Http\Controllers\API;

use Storage;
use Carbon\Carbon;
use App\Models\User;
use App\Models\Country;
use App\Models\OtpCode;
use App\Models\Referral;
use App\Models\Governorate;
use Illuminate\Http\Request;
use App\Mail\OtpVerificationMail;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\Log;
use App\Http\Controllers\Controller;
use App\Http\Resources\UserResource;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Mail;
use App\Http\Resources\CountryResource;
use Illuminate\Support\Facades\Password;
use Laravel\Socialite\Facades\Socialite;
use Illuminate\Support\Facades\Validator;
use Illuminate\Support\Facades\RateLimiter;

class AuthController extends Controller
{
    /**
     * Constructor to set locale
     */
    public function __construct(Request $request)
    {
        $locale = $request->header('Accept-Language', 'en');
        \Illuminate\Support\Facades\App::setLocale($locale);
    }

    /**
     * Register a new user and send OTP for email verification
     *
     * @param Request $request
     * @return \Illuminate\Http\JsonResponse
     */
    public function register(Request $request)
    {
        try {
            // Validate input data
            $validated = $request->validate([
                'full_name' => 'required|string|max:255',
                'email' => 'required|string|email|max:255|unique:users,email',
                'password' => 'required|string|min:8|confirmed',
                'password_confirmation' => 'required|string',
                'referral_code' => 'nullable|string|exists:users,referral_code',
            ]);

            // Create new user
            /** @var \App\Models\User|\Laravel\Sanctum\HasApiTokens $user */
            $user = User::create([
                'full_name' => $validated['full_name'],
                'email' => $validated['email'],
                'password' => Hash::make($validated['password']),
            ]);

            // Handle referral
            if ($request->referral_code) {
                $referrer = User::where('referral_code', $request->referral_code)->first();

                if ($referrer && $referrer->id !== $user->id) {
                    // Record the referral
                    Referral::create([
                        'referrer_id' => $referrer->id,
                        'referred_id' => $user->id,
                    ]);

                    $referrer->awardPoints(10, 'referral_signup', $user->id);
                }
            }
            // Generate 6-digit OTP
            $otp = mt_rand(100000, 999999);

            // Store OTP in the database
            DB::transaction(function () use ($user, $otp) {
                OtpCode::where('user_id', $user->id)->delete(); // Remove any old OTPs
                OtpCode::create([
                    'user_id' => $user->id,
                    'code' => $otp,
                    'expires_at' => Carbon::now()->addMinutes(10),
                ]);
            });

            // Send OTP email
            try {
                Mail::to($user->email)->send(new OtpVerificationMail($otp, app()->getLocale()));
            } catch (\Exception $e) {
                Log::error('Failed to send OTP email: ' . $e->getMessage(), ['user_id' => $user->id]);
                return response()->json([
                    'status' => 'error',
                    'message' => trans('messages.failed_to_send_otp'),
                ], 500);
            }

            // Issue Sanctum token
            $token = $user->createToken('auth_token')->plainTextToken;

            return response()->json([
                'status' => 'success',
                'message' => trans('messages.registered_successfully'),
                'user' => $user,
                'token' => $token,
            ], 201);
        } catch (\Illuminate\Validation\ValidationException $e) {
            return response()->json([
                'status' => 'error',
                'message' => trans('messages.validation_failed'),
                'errors' => $e->errors(),
            ], 422);
        } catch (\Exception $e) {
            Log::error('Error registering user: ' . $e->getMessage(), ['trace' => $e->getTraceAsString()]);
            return response()->json([
                'status' => 'error',
                'message' => trans('messages.failed_to_register'),
            ], 500);
        }
    }

    // Existing login method (unchanged)
    public function login(Request $request)
    {
        $validated = $request->validate([
            'email' => 'required|string|email',
            'password' => 'required|string',
        ]);

        if (!Auth::attempt($validated)) {
            return response()->json([
                'status' => 'true',
                'message' => trans('messages.invalid_credentials'),
            ], 200);
        }

        /** @var \App\Models\User|\Laravel\Sanctum\HasApiTokens $user */
        $user = Auth::user();
        $token = $user->createToken('auth_token')->plainTextToken;

        if (!$user->hasVerifiedEmail()) {
            return response()->json([
                'status' => 'true',
                'message' => trans('messages.email_not_verified'),
                'token' => $token,

            ], 200);
        }


        return response()->json([
            'status' => 'success',
            'message' => trans('messages.logged_in_successfully'),
            'user' => $user,
            'token' => $token,
        ], 200);
    }

    // Existing forgotPassword method (updated with translations)
    public function forgotPassword(Request $request)
    {
        try {
            $validated = $request->validate([
                'email' => 'required|string|email',
            ]);

            $key = 'forgot-password:' . $request->ip();
            if (\Illuminate\Support\Facades\RateLimiter::tooManyAttempts($key, 5)) {
                return response()->json([
                    'status' => 'error',
                    'message' => trans('messages.too_many_attempts'),
                ], 429);
            }

            /** @var \App\Models\User|null $user */
            $user = User::where('email', $validated['email'])->first();

            if (!$user) {
                \Illuminate\Support\Facades\RateLimiter::increment($key, 3600);
                return response()->json([
                    'status' => 'error',
                    'message' => trans('messages.email_not_found'),
                ], 404);
            }

            // if (!$user->hasVerifiedEmail()) {
            //     \Illuminate\Support\Facades\RateLimiter::increment($key, 3600);
            //     return response()->json([
            //         'status' => 'error',
            //         'message' => trans('messages.email_not_verified'),
            //     ], 403);
            // }

            $otp = mt_rand(100000, 999999);

            DB::transaction(function () use ($user, $otp) {
                OtpCode::where('user_id', $user->id)->delete();
                OtpCode::create([
                    'user_id' => $user->id,
                    'code' => $otp,
                    'expires_at' => Carbon::now()->addMinutes(10),
                ]);
            });

            try {
                Mail::to($user->email)->send(new OtpVerificationMail($otp, app()->getLocale(), 'password_reset'));
            } catch (\Exception $e) {
                Log::error('Failed to send password reset OTP email', [
                    'user_id' => $user->id,
                    'email' => $user->email,
                    'error' => $e->getMessage(),
                    'trace' => $e->getTraceAsString(),
                ]);
                return response()->json([
                    'status' => 'error',
                    'message' => trans('messages.failed_to_send_otp'),
                    'debug' => app()->environment('local') ? $e->getMessage() : null, // Include error in local env
                ], 500);
            }

            return response()->json([
                'status' => 'success',
                'message' => trans('messages.otp_sent_for_reset'),
            ], 200);
        } catch (\Illuminate\Validation\ValidationException $e) {
            return response()->json([
                'status' => 'error',
                'message' => trans('messages.validation_failed'),
                'errors' => $e->errors(),
            ], 422);
        } catch (\Exception $e) {
            Log::error('Error requesting password reset: ' . $e->getMessage(), ['trace' => $e->getTraceAsString()]);
            return response()->json([
                'status' => 'error',
                'message' => trans('messages.failed_to_request_reset'),
            ], 500);
        }
    }

    // Existing social login methods (updated with translations)
    public function redirectToGoogle()
    {
        /** @var \Laravel\Socialite\Contracts\Provider|\Laravel\Socialite\Two\GoogleProvider $driver */
        $driver = Socialite::driver('google');
        return $driver->stateless()->redirect();
    }

    public function handleGoogleCallback()
    {
        try {
            /** @var \Laravel\Socialite\Contracts\Provider|\Laravel\Socialite\Two\GoogleProvider $driver */
            $driver = Socialite::driver('google');
            $socialUser = $driver->stateless()->user();

            /** @var \App\Models\User|\Laravel\Sanctum\HasApiTokens $user */
            $user = User::updateOrCreate(
                ['google_id' => $socialUser->getId()],
                [
                    'full_name' => $socialUser->getName(),
                    'email' => $socialUser->getEmail(),
                    'email_verified_at' => now(),
                ]
            );

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

            return response()->json([
                'status' => 'success',
                'message' => trans('messages.google_login_success'),
                'user' => $user,
                'token' => $token,
            ], 200);
        } catch (\Exception $e) {
            Log::error('Google login error: ' . $e->getMessage(), ['trace' => $e->getTraceAsString()]);
            return response()->json([
                'status' => 'error',
                'message' => trans('messages.google_login_failed'),
            ], 400);
        }
    }

    public function redirectToFacebook()
    {
        /** @var \Laravel\Socialite\Contracts\Provider|\Laravel\Socialite\Two\FacebookProvider $driver */
        $driver = Socialite::driver('facebook');
        return $driver->stateless()->redirect();
    }

    public function handleFacebookCallback()
    {
        try {
            /** @var \Laravel\Socialite\Contracts\Provider|\Laravel\Socialite\Two\FacebookProvider $driver */
            $driver = Socialite::driver('facebook');
            $socialUser = $driver->stateless()->user();

            /** @var \App\Models\User|\Laravel\Sanctum\HasApiTokens $user */
            $user = User::updateOrCreate(
                ['facebook_id' => $socialUser->getId()],
                [
                    'full_name' => $socialUser->getName(),
                    'email' => $socialUser->getEmail(),
                    'email_verified_at' => now(),
                ]
            );

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

            return response()->json([
                'status' => 'success',
                'message' => trans('messages.facebook_login_success'),
                'user' => $user,
                'token' => $token,
            ], 200);
        } catch (\Exception $e) {
            Log::error('Facebook login error: ' . $e->getMessage(), ['trace' => $e->getTraceAsString()]);
            return response()->json([
                'status' => 'error',
                'message' => trans('messages.facebook_login_failed'),
            ], 400);
        }
    }

    // Existing logout method (updated with translations)
    public function logout(Request $request)
    {
        /** @var \App\Models\User|\Laravel\Sanctum\HasApiTokens $user */
        $user = $request->user();
        $user->currentAccessToken()->delete();

        return response()->json([
            'status' => 'success',
            'message' => trans('messages.logged_out_successfully'),
        ], 200);
    }

    // Existing verifyEmail method (unchanged, included for completeness)
    public function verifyEmail(Request $request)
    {
        $request->validate([
            'otp' => 'required|digits:6',
        ]);

        try {
            /** @var \App\Models\User|\Laravel\Sanctum\HasApiTokens $user */
            $user = $request->user();

            if (!$user) {
                return response()->json([
                    'status' => 'error',
                    'message' => trans('messages.unauthorized'),
                ], 401);
            }

            if ($user->hasVerifiedEmail()) {
                return response()->json([
                    'status' => 'error',
                    'message' => trans('messages.email_already_verified'),
                ], 400);
            }

            $otp = OtpCode::where('user_id', $user->id)
                ->where('code', $request->otp)
                ->where('expires_at', '>', Carbon::now())
                ->first();

            if (!$otp) {
                return response()->json([
                    'status' => 'error',
                    'message' => trans('messages.invalid_or_expired_otp'),
                ], 400);
            }

            DB::transaction(function () use ($user, $otp) {
                $user->markEmailAsVerified();
                $otp->delete(); // Remove used OTP
            });

            return response()->json([
                'status' => 'success',
                'message' => trans('messages.email_verified'),
            ], 200);
        } catch (\Exception $e) {
            Log::error('Error verifying email: ' . $e->getMessage(), ['trace' => $e->getTraceAsString()]);
            return response()->json([
                'status' => 'error',
                'message' => trans('messages.failed_to_verify_email'),
            ], 500);
        }
    }
    public function verifyOtp(Request $request)
    {
        try {
            $validator = Validator::make($request->all(), [
                'email' => 'required|string|email|exists:users,email',
                'otp' => 'required|digits:6',
            ]);

            if ($validator->fails()) {
                return response()->json([
                    'status' => 'error',
                    'message' => trans('messages.validation_failed'),
                    'errors' => $validator->errors(),
                ], 422);
            }

            $validated = $validator->validated();

            // Log request for debugging
            Log::info('VerifyOtp attempt', [
                'email' => $validated['email'],
                'otp' => $validated['otp'],
                'locale' => app()->getLocale(),
            ]);

            // Find user
            $user = User::where('email', $validated['email'])->first();

            // Verify OTP
            $otp = OtpCode::where('user_id', $user->id)
                ->where('code', $validated['otp'])
                ->where('expires_at', '>', Carbon::now())
                ->first();

            if (!$otp) {
                return response()->json([
                    'status' => 'error',
                    'message' => trans('messages.invalid_or_expired_otp'),
                ], 400);
            }

            return response()->json([
                'status' => 'success',
                'message' => trans('messages.otp_verified'),
                'data' => new UserResource($user),
            ], 200);
        } catch (\Exception $e) {
            Log::error('Error verifying OTP', [
                'email' => $request->input('email'),
                'otp' => $request->input('otp'),
                'locale' => app()->getLocale(),
                'error' => $e->getMessage(),
                'trace' => $e->getTraceAsString(),
            ]);
            return response()->json([
                'status' => 'error',
                'message' => trans('messages.failed_to_verify_otp'),
                'debug' => app()->environment('local') ? $e->getMessage() : null,
            ], 500);
        }
    }

    /**
     * Reset password using verified OTP
     *
     * @param Request $request
     * @return \Illuminate\Http\JsonResponse
     */
    public function resetPassword(Request $request)
    {
        try {
            $validator = Validator::make($request->all(), [
                'email' => 'required|string|email|exists:users,email',
                'otp' => 'required|digits:6',
                'password' => 'required|string|min:8',
            ]);

            if ($validator->fails()) {
                return response()->json([
                    'status' => 'error',
                    'message' => trans('messages.validation_failed'),
                    'errors' => $validator->errors(),
                ], 422);
            }

            $validated = $validator->validated();

            // Log request for debugging
            Log::info('ResetPassword attempt', [
                'email' => $validated['email'],
                'otp' => $validated['otp'],
                'locale' => app()->getLocale(),
            ]);

            // Find user
            $user = User::where('email', $validated['email'])->first();

            // Verify OTP
            $otp = OtpCode::where('user_id', $user->id)
                ->where('code', $validated['otp'])
                ->where('expires_at', '>', Carbon::now())
                ->first();

            if (!$otp) {
                return response()->json([
                    'status' => 'error',
                    'message' => trans('messages.invalid_or_expired_otp'),
                ], 400);
            }

            // Update password
            DB::transaction(function () use ($user, $validated, $otp) {
                $user->password = Hash::make($validated['password']);
                $user->save();
                $otp->delete(); // Remove used OTP
            });

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

            return response()->json([
                'status' => 'success',
                'message' => trans('messages.password_reset_success'),
                'data' => new UserResource($user),
            ], 200);
        } catch (\Exception $e) {
            Log::error('Error resetting password', [
                'email' => $request->input('email'),
                'otp' => $request->input('otp'),
                'locale' => app()->getLocale(),
                'error' => $e->getMessage(),
                'trace' => $e->getTraceAsString(),
            ]);
            return response()->json([
                'status' => 'error',
                'message' => trans('messages.failed_to_reset_password'),
                'debug' => app()->environment('local') ? $e->getMessage() : null,
            ], 500);
        }
    }

    /**
     * 
     * @param \Illuminate\Http\Request $request
     * @return mixed|\Illuminate\Http\JsonResponse
     */

    public function changePassword(Request $request)
    {
        try {
            $validator = Validator::make($request->all(), [
                'current_password' => 'required|string',
                'new_password' => 'required|string|min:8|confirmed',
                'new_password_confirmation' => 'required|string',
            ]);

            if ($validator->fails()) {
                return response()->json([
                    'status' => 'error',
                    'message' => trans('messages.validation_failed'),
                    'errors' => $validator->errors(),
                ], 422);
            }

            $validated = $validator->validated();

            /** @var \App\Models\User|\Laravel\Sanctum\HasApiTokens $user */
            $user = $request->user();

            if (!Hash::check($validated['current_password'], $user->password)) {
                return response()->json([
                    'status' => 'error',
                    'message' => trans('messages.invalid_current_password'),
                ], 401);
            }

            DB::transaction(function () use ($user, $validated) {
                $user->password = Hash::make($validated['new_password']);
                $user->save();
            });

            $user->tokens()->delete();

            return response()->json([
                'status' => 'success',
                'message' => trans('messages.password_changed_success'),
                'data' => new UserResource($user),
            ], 200);
        } catch (\Exception $e) {
            Log::error('Error changing password', [
                'user_id' => $request->user()->id,
                'locale' => app()->getLocale(),
                'error' => $e->getMessage(),
                'trace' => $e->getTraceAsString(),
            ]);
            return response()->json([
                'status' => 'error',
                'message' => trans('messages.failed_to_change_password'),
                'debug' => app()->environment('local') ? $e->getMessage() : null,
            ], 500);
        }
    }


    public function getUser()
    {

        return response()->json([
            'status' => 'success',
            'message' => trans('messages.password_reset_success'),
            'data' => new UserResource(auth()->user()),
            'country-gov' => CountryResource::collection(Country::with('governorates')->get())
        ], 200);
    }

    public function updateProfile(Request $request)
    {
        try {
            $validator = Validator::make($request->all(), [
                'full_name' => 'sometimes|string|max:255',
                'phone' => 'sometimes|string|max:20|regex:/^([0-9\s\-\+\(\)]*)$/|min:10',
                'email' => 'sometimes|string|email|max:255|unique:users,email,' . $request->user()->id,
                'second_email' => 'nullable|string|email|max:255|unique:users,second_email,' . $request->user()->id,
                'zip_code' => 'nullable|string|max:20',
                'governorate_id' => 'sometimes|exists:governorates,id',
                'image' => 'sometimes|image', // Max 2MB
                'deleted' => 'sometimes|boolean',
            ]);

            if ($validator->fails()) {
                return response()->json([
                    'status' => 'error',
                    'message' => trans('messages.validation_failed'),
                    'errors' => $validator->errors(),
                ], 422);
            }

            $validated = $validator->validated();

            /** @var \App\Models\User|\Laravel\Sanctum\HasApiTokens $user */
            $user = $request->user();

            if (isset($validated['country_id'], $validated['governorate_id'])) {
                $governorate = Governorate::where('id', $validated['governorate_id'])
                    ->where('country_id', $validated['country_id'])
                    ->first();

                if (!$governorate) {
                    return response()->json([
                        'status' => 'error',
                        'message' => trans('messages.governorate_not_in_country'),
                    ], 422);
                }
            }


            if (!empty($validated['deleted']) && $validated['deleted'] === true) {
                if ($user->image && Storage::disk('public')->exists($user->image)) {
                    Storage::disk('public')->delete($user->image);
                }
                $validated['image'] = null;
            }
            if ($request->hasFile('image')) {
                try {

                    if ($user->image && Storage::disk('public')->exists($user->image)) {
                        Storage::disk('public')->delete($user->image);
                    }

                    // Store new image
                    $path = $request->file('image')->store('images/users', 'public');
                    $validated['image'] = $path;
                } catch (\Exception $e) {
                    Log::error('Error uploading image', [
                        'user_id' => $user->id,
                        'error' => $e->getMessage(),
                        'trace' => $e->getTraceAsString(),
                    ]);
                    return response()->json([
                        'status' => 'error',
                        'message' => trans('messages.image_upload_failed'),
                        'debug' => app()->environment('local') ? $e->getMessage() : null,
                    ], 500);
                }
            }


            DB::transaction(function () use ($user, $validated) {
                $user->fill($validated)->save();
            });


            $user->load('governorate.country');

            return response()->json([
                'status' => 'success',
                'message' => trans('messages.profile_updated_success'),
                'data' => new UserResource($user),
            ], 200);
        } catch (\Exception $e) {
            Log::error('Error updating profile', [
                'user_id' => $request->user()->id,
                'locale' => app()->getLocale(),
                'error' => $e->getMessage(),
                'trace' => $e->getTraceAsString(),
            ]);
            return response()->json([
                'status' => 'error',
                'message' => trans('messages.failed_to_update_profile'),
                'debug' => app()->environment('local') ? $e->getMessage() : null,
            ], 500);
        }
    }
}
