<?php

namespace App\Http\Controllers\API\V1;

use App\Http\Controllers\Controller;
use App\Http\Requests\ChangePasswordRequest;
use App\Http\Requests\ForgotPasswordRequest;
use App\Http\Requests\LoginRequest;
use App\Http\Requests\ResetPasswordRequest;
use App\Http\Requests\UpdateUserRequest;
use App\Http\Resources\AuthResource;
use App\Http\Resources\UserResource;
use App\Models\User;
use Illuminate\Auth\Events\PasswordReset;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Password;
use Illuminate\Support\Str;

class AuthController extends Controller
{
    public function login(LoginRequest $request): Response
    {
        $user = User::findByEmailOrPhone($request->validated('username'));

        if (! $user || ! Hash::check($request->validated('password'), $user->password)) {
            return response(
                ['message' => 'Invalid credentials'],
                Response::HTTP_UNAUTHORIZED,
            );
        }

        $accessToken = $user->createToken('auth-token');

        return response(
            new AuthResource([
                'user' => $user,
                'access_token' => $accessToken->plainTextToken,
                'expires_at' => null,
            ]),
            Response::HTTP_OK,
        );
    }

    public function logout(Request $request): Response
    {
        $request->user()->currentAccessToken()->delete();

        return response(
            ['message' => 'Logged out successfully'],
            Response::HTTP_OK,
        );
    }

    public function user(Request $request): UserResource
    {
        return new UserResource($request->user());
    }

    public function forgotPassword(ForgotPasswordRequest $request): Response
    {
        $username = $request->validated('username');
        $user = User::findByEmailOrPhone($username);

        // Always return success to prevent username enumeration
        if (! $user) {
            return response(
                ['message' => 'If an account exists with this email or phone, a password reset code has been sent.'],
                Response::HTTP_OK,
            );
        }

        // For email users, use Laravel's built-in password reset
        if ($user->email) {
            $token = Password::createToken($user);
            $user->notify(new \App\Notifications\SendPasswordResetNotification($token));
        } else {
            // For phone-only users, generate a 6-digit code and store manually
            $token = str_pad((string) random_int(0, 999999), 6, '0', STR_PAD_LEFT);
            $emailColumn = 'phone:'.$user->phone;

            \DB::table('password_reset_tokens')->updateOrInsert(
                ['email' => $emailColumn],
                [
                    'token' => Hash::make($token),
                    'created_at' => now(),
                ]
            );

            // For phone-only users, log the code (TODO: replace with SMS)
            \Log::info("Password reset code for {$user->phone}: {$token} (expires in 60 minutes)");
        }

        return response(
            ['message' => 'If an account exists with this email or phone, a password reset code has been sent.'],
            Response::HTTP_OK,
        );
    }

    public function resetPassword(ResetPasswordRequest $request): Response
    {
        $username = $request->validated('username');
        $token = $request->validated('token');
        $password = $request->validated('password');

        // Find the user
        $user = User::findByEmailOrPhone($username);

        if (! $user) {
            return response(
                ['message' => 'Invalid or expired reset token.'],
                Response::HTTP_BAD_REQUEST,
            );
        }

        // For email users, use Laravel's built-in password reset
        if ($user->email) {
            $status = Password::reset(
                [
                    'email' => $user->email,
                    'token' => $token,
                    'password' => $password,
                    'password_confirmation' => $password,
                ],
                function (User $user, string $password) {
                    $user->forceFill([
                        'password' => Hash::make($password),
                    ])->setRememberToken(Str::random(60));

                    $user->save();

                    event(new PasswordReset($user));

                    // Revoke all Sanctum tokens to force re-login on all devices
                    $user->tokens()->delete();
                }
            );

            if ($status === Password::PASSWORD_RESET) {
                return response(
                    ['message' => 'Password has been reset successfully. Please login with your new password.'],
                    Response::HTTP_OK,
                );
            }

            return response(
                ['message' => 'Invalid or expired reset token.'],
                Response::HTTP_BAD_REQUEST,
            );
        }

        // For phone-only users, manually verify and reset
        $emailColumn = 'phone:'.$user->phone;
        $resetRecord = \DB::table('password_reset_tokens')
            ->where('email', $emailColumn)
            ->first();

        if (! $resetRecord || ! Hash::check($token, $resetRecord->token)) {
            return response(
                ['message' => 'Invalid or expired reset token.'],
                Response::HTTP_BAD_REQUEST,
            );
        }

        // Check if token has expired (60 minutes)
        if (now()->parse($resetRecord->created_at)->diffInMinutes(now()) > 60) {
            return response(
                ['message' => 'Invalid or expired reset token.'],
                Response::HTTP_BAD_REQUEST,
            );
        }

        // Reset the password
        $user->forceFill([
            'password' => Hash::make($password),
        ])->setRememberToken(Str::random(60));

        $user->save();

        event(new PasswordReset($user));

        // Delete the reset token
        \DB::table('password_reset_tokens')
            ->where('email', $emailColumn)
            ->delete();

        // Revoke all Sanctum tokens to force re-login on all devices
        $user->tokens()->delete();

        return response(
            ['message' => 'Password has been reset successfully. Please login with your new password.'],
            Response::HTTP_OK,
        );
    }

    public function update(UpdateUserRequest $request): UserResource
    {
        $user = $request->user();
        $validated = $request->validated();

        // Check if email is being changed
        $emailChanged = isset($validated['email']) && $validated['email'] !== $user->email;

        // Check if phone is being changed
        $phoneChanged = isset($validated['phone']) && $validated['phone'] !== $user->phone;

        // Handle both 'name' and 'first_name'/'last_name' formats
        if (isset($validated['name'])) {
            $nameParts = explode(' ', trim($validated['name']), 2);
            $firstName = $nameParts[0];
            $lastName = $nameParts[1] ?? null;
        } elseif (isset($validated['first_name'])) {
            $firstName = $validated['first_name'];
            $lastName = $validated['last_name'] ?? null;
        } else {
            // No name update requested, keep existing values
            $firstName = $user->first_name;
            $lastName = $user->last_name;
        }

        // Prepare update data
        $updateData = [
            'first_name' => $firstName,
            'last_name' => $lastName,
        ];

        if (isset($validated['email'])) {
            $updateData['email'] = $validated['email'];
        }

        if (isset($validated['phone'])) {
            $updateData['phone'] = $validated['phone'];
        }

        // If email or phone changed, require verification
        if ($emailChanged || $phoneChanged) {
            $updateData['email_verified_at'] = null;
        }

        $user->update($updateData);
        $user->refresh();

        // Send verification notification if email changed
        if ($emailChanged && $user->email) {
            $user->sendEmailVerificationNotification();
        }

        // Log verification code if phone changed (TODO: replace with SMS)
        if ($phoneChanged && $user->phone) {
            $token = str_pad((string) random_int(0, 999999), 6, '0', STR_PAD_LEFT);
            \Log::info("Phone verification code for {$user->phone}: {$token} (expires in 60 minutes)");
        }

        return new UserResource($user);
    }

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

        // Verify current password
        if (! Hash::check($request->validated('current_password'), $user->password)) {
            return response(
                ['message' => 'The current password is incorrect.'],
                Response::HTTP_UNAUTHORIZED,
            );
        }

        // Update password
        $user->forceFill([
            'password' => Hash::make($request->validated('password')),
        ])->setRememberToken(Str::random(60));

        $user->save();

        return response(
            ['message' => 'Password changed successfully.'],
            Response::HTTP_OK,
        );
    }
}
