<?php

namespace App\Http\Controllers\API\V1;

use App\Http\Controllers\Controller;
use App\Models\User;
use Carbon\Carbon;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Mail;
use Illuminate\Validation\ValidationException;

class AuthController extends Controller
{
    private function jsonSuccess($data = null, int $code = 200)
    {
        return response()->json([
            'success' => true,
            'data' => $data,
            'error' => null,
        ], $code);
    }

    private function jsonError(string $message, int $code = 422, $data = null)
    {
        return response()->json([
            'success' => false,
            'data' => $data,
            'error' => $message,
        ], $code);
    }

    private function generateOtp(): string
    {
        return (string) random_int(100000, 999999);
    }

    private function isLocalEnv(): bool
    {
        return app()->environment(['local', 'development', 'testing']);
    }

    /**
     * ✅ REGISTER + SEND OTP
     * Creates account + generates OTP + tries sending email
     * If email fails on localhost -> still allow user to continue
     */
    public function register(Request $request)
    {
        $request->validate([
            'name' => ['required', 'string', 'max:150'],
            'email' => ['required', 'email', 'max:191'],
            'password' => ['required', 'string', 'min:6'],
        ]);

        $email = strtolower(trim($request->email));

        $existing = User::where('email', $email)->first();
        if ($existing) {
            return $this->jsonError('Email already registered. Please login.', 422);
        }

        $user = User::create([
            'name' => trim($request->name),
            'email' => $email,
            'password' => Hash::make($request->password),
            'timezone' => 'UTC',
            'status' => 'active',
        ]);

        // ✅ Generate OTP
        $otp = $this->generateOtp();

        $user->email_otp = $otp;
        $user->email_otp_expires_at = now()->addMinutes(10);
        $user->email_otp_verified_at = null;
        $user->save();

        // ✅ Try sending OTP email
        $delivery = 'sent';
        $delivery_message = 'OTP sent to your email ✅';

        try {
            Mail::raw(
                "Your FollowUpPro OTP is: {$otp}. It will expire in 10 minutes.",
                function ($message) use ($email) {
                    $message->to($email)->subject("FollowUpPro - Verify your Email");
                }
            );
        } catch (\Throwable $e) {
            // ✅ On localhost / dev -> allow flow to continue
            $delivery = 'failed';
            $delivery_message = 'Account created ✅ but OTP email delivery failed. Please use Resend OTP.';
        }

        $response = [
            'user_id' => $user->id,
            'email' => $user->email,
            'otp_sent' => $delivery === 'sent',
            'delivery' => $delivery,
            'message' => $delivery_message,
            'expires_in_minutes' => 10,
        ];

        // ✅ For LOCAL ONLY: return OTP in response (helps testing)
        if ($this->isLocalEnv()) {
            $response['debug_otp'] = $otp;
        }

        // ✅ Always return success so UI goes to OTP step
        return $this->jsonSuccess($response, 201);
    }

    /**
     * ✅ RESEND OTP (Request OTP)
     * Only needs email (clean)
     */
    public function requestOtp(Request $request)
    {
        $request->validate([
            'email' => ['required', 'email', 'max:191'],
        ]);

        $email = strtolower(trim($request->email));

        $user = User::where('email', $email)->first();
        if (!$user) {
            return $this->jsonError('User not found. Please register again.', 404);
        }

        // ✅ If already verified
        if ($user->email_verified_at) {
            return $this->jsonSuccess([
                'email' => $user->email,
                'already_verified' => true,
                'message' => 'Email already verified ✅',
            ], 200);
        }

        $otp = $this->generateOtp();

        $user->email_otp = $otp;
        $user->email_otp_expires_at = now()->addMinutes(10);
        $user->email_otp_verified_at = null;
        $user->save();

        $delivery = 'sent';
        $delivery_message = 'OTP resent ✅';

        try {
            Mail::raw(
                "Your FollowUpPro OTP is: {$otp}. It will expire in 10 minutes.",
                function ($message) use ($email) {
                    $message->to($email)->subject("FollowUpPro - Email Verification OTP");
                }
            );
        } catch (\Throwable $e) {
            $delivery = 'failed';
            $delivery_message = 'OTP generated ✅ but email delivery failed. Please check mail settings.';
        }

        $response = [
            'email' => $user->email,
            'otp_sent' => $delivery === 'sent',
            'delivery' => $delivery,
            'message' => $delivery_message,
            'expires_in_minutes' => 10,
        ];

        if ($this->isLocalEnv()) {
            $response['debug_otp'] = $otp;
        }

        // ✅ Always success so UI can keep going
        return $this->jsonSuccess($response, 200);
    }

    /**
     * ✅ VERIFY OTP
     */
    public function verifyOtp(Request $request)
    {
        $request->validate([
            'email' => ['required', 'email', 'max:191'],
            'otp' => ['required', 'digits:6'],
        ]);

        $email = strtolower(trim($request->email));
        $otp = trim($request->otp);

        $user = User::where('email', $email)->first();
        if (!$user) {
            return $this->jsonError('User not found.', 404);
        }

        // ✅ Already verified
        if ($user->email_verified_at) {
            return $this->jsonSuccess([
                'email_verified' => true,
                'email' => $user->email,
                'message' => 'Email already verified ✅',
            ], 200);
        }

        if (!$user->email_otp || !$user->email_otp_expires_at) {
            return $this->jsonError('OTP not requested. Please request OTP again.', 422);
        }

        if (now()->greaterThan(Carbon::parse($user->email_otp_expires_at))) {
            return $this->jsonError('OTP expired. Please request a new OTP.', 422);
        }

        if ($user->email_otp !== $otp) {
            return $this->jsonError('Invalid OTP.', 422);
        }

        $user->email_verified_at = now();
        $user->email_otp_verified_at = now();

        // ✅ clear OTP values
        $user->email_otp = null;
        $user->email_otp_expires_at = null;

        $user->save();

        return $this->jsonSuccess([
            'email_verified' => true,
            'user_id' => $user->id,
            'email' => $user->email,
            'message' => 'Email verified successfully ✅',
        ], 200);
    }

    /**
     * ✅ LOGIN
     */
    public function login(Request $request)
    {
        $request->validate([
            'email' => ['required', 'email', 'max:191'],
            'password' => ['required', 'string'],
        ]);

        $email = strtolower(trim($request->email));

        $user = User::where('email', $email)->first();

        if (!$user || !Hash::check($request->password, $user->password)) {
            throw ValidationException::withMessages([
                'email' => ['Invalid credentials'],
            ]);
        }

        // ✅ block login if email not verified
        if (!$user->email_verified_at) {
            return $this->jsonError('Please verify your email before login.', 403);
        }

        $user->tokens()->delete();
        $token = $user->createToken('react-client')->plainTextToken;

        return $this->jsonSuccess([
            'token' => $token,
            'user' => $user->load('subscription'),
        ], 200);
    }

    /**
     * ✅ LOGOUT
     */
    public function logout(Request $request)
    {
        $request->user()->currentAccessToken()->delete();

        return $this->jsonSuccess('Logged out successfully', 200);
    }

    /**
     * ✅ ME
     */
    public function me(Request $request)
    {
        return $this->jsonSuccess(
            $request->user()->load('subscription'),
            200
        );
    }
}
