<?php

namespace App\Http\Controllers;

use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Mail;
use Tymon\JWTAuth\Facades\JWTAuth;
use Tymon\JWTAuth\Exceptions\JWTException;

class AuthController extends Controller
{
    public function __construct()
    {
        // No middleware needed as we define it in routes
    }

    public function register(Request $request)
    {
        return $this->sendSignupCode($request);
    }

    public function sendSignupCode(Request $request)
    {
        $request->validate([
            'name' => 'required|string|max:255',
            'email' => 'required|string|email|max:255|unique:users,email',
            'password' => 'required|string|min:6|confirmed',
        ]);

        $code = str_pad((string) random_int(0, 999999), 6, '0', STR_PAD_LEFT);

        DB::table('signup_verification_codes')->updateOrInsert(
            ['email' => $request->email],
            [
                'name' => $request->name,
                'password_hash' => Hash::make($request->password),
                'code' => $code,
                'expires_at' => now()->addMinutes(15),
                'updated_at' => now(),
                'created_at' => now(),
            ]
        );

        try {
            Mail::raw("Your GCM signup verification code is: {$code}. It expires in 15 minutes.\n\nPlease do not reply to this email. This is an automated notification from GCM Construction Management System.", function ($message) use ($request) {
                $message->to($request->email)->subject('GCM Signup Verification Code');
                $message->replyTo('no-reply@gcm.co.ke', 'Do Not Reply');
            });
        } catch (\Throwable $exception) {
            Log::error('Failed to send signup verification code email', [
                'email' => $request->email,
                'error' => $exception->getMessage(),
            ]);
        }

        $response = [
            'message' => 'Verification code sent to your email.',
            'email' => $request->email,
        ];

        if (app()->environment('local')) {
            $response['verification_code'] = $code;
        }

        return response()->json($response, 200);
    }

    public function verifySignupCode(Request $request)
    {
        $request->validate([
            'email' => 'required|string|email|max:255',
            'code' => 'required|digits:6',
        ]);

        $pending = DB::table('signup_verification_codes')
            ->where('email', $request->email)
            ->where('code', $request->code)
            ->first();

        if (!$pending) {
            return response()->json(['message' => 'Invalid verification code.'], 400);
        }

        if (now()->greaterThan($pending->expires_at)) {
            DB::table('signup_verification_codes')->where('email', $request->email)->delete();
            return response()->json(['message' => 'Verification code has expired.'], 400);
        }

        if (User::where('email', $request->email)->exists()) {
            DB::table('signup_verification_codes')->where('email', $request->email)->delete();
            return response()->json(['message' => 'Account already exists. Please login.'], 409);
        }

        $user = User::create([
            'name' => $pending->name,
            'email' => $pending->email,
            'password' => $pending->password_hash,
            'role' => 'user',
        ]);

        DB::table('signup_verification_codes')->where('email', $request->email)->delete();

        $token = JWTAuth::fromUser($user);

        return response()->json([
            'message' => 'User registered successfully',
            'user' => $user,
            'access_token' => $token,
            'token_type' => 'Bearer',
        ], 201);
    }

    public function forgotPassword(Request $request)
    {
        $request->validate([
            'email' => 'required|string|email'
        ]);

        $user = User::where('email', $request->email)->first();
        
        if (!$user) {
            return response()->json(['message' => 'If that email exists, a password reset link has been sent.'], 200);
        }

        $code = str_pad((string) random_int(0, 999999), 6, '0', STR_PAD_LEFT);
        
        DB::table('password_reset_tokens')->updateOrInsert(
            ['email' => $request->email],
            [
                'token' => $code,
                'created_at' => now()
            ]
        );

        try {
            Mail::raw("Your GCM password reset code is: {$code}. It expires in 15 minutes.\n\nPlease do not reply to this email. This is an automated notification from GCM Construction Management System.", function ($message) use ($request) {
                $message->to($request->email)->subject('GCM Password Reset Code');
                $message->replyTo('no-reply@gcm.co.ke', 'Do Not Reply');
            });
        } catch (\Throwable $exception) {
            Log::error('Failed to send password reset code email', [
                'email' => $request->email,
                'error' => $exception->getMessage(),
            ]);
        }

        $response = [
            'message' => 'If that email exists, a password reset code has been sent.',
            'email' => $request->email,
        ];

        if (app()->environment('local')) {
            $response['reset_code'] = $code;
        }

        return response()->json($response, 200);
    }

    public function verifyForgotPasswordCode(Request $request)
    {
        $request->validate([
            'email' => 'required|string|email',
            'code' => 'required|digits:6',
        ]);

        $resetRecord = DB::table('password_reset_tokens')
            ->where('email', $request->email)
            ->where('token', $request->code)
            ->first();

        if (!$resetRecord) {
            return response()->json(['message' => 'Invalid verification code'], 400);
        }

        if (now()->diffInMinutes($resetRecord->created_at) > 15) {
            return response()->json(['message' => 'Verification code has expired'], 400);
        }

        return response()->json(['message' => 'Verification code is valid'], 200);
    }

    public function resetPassword(Request $request)
    {
        $request->validate([
            'email' => 'required|string|email',
            'code' => 'nullable|digits:6',
            'token' => 'nullable|string',
            'password' => 'required|string|min:6|confirmed',
        ]);

        $verificationCode = $request->code ?: $request->token;
        if (!$verificationCode) {
            return response()->json(['message' => 'Verification code is required'], 422);
        }

        $resetRecord = DB::table('password_reset_tokens')
            ->where('email', $request->email)
            ->where('token', $verificationCode)
            ->first();

        if (!$resetRecord) {
            return response()->json(['message' => 'Invalid or expired reset token'], 400);
        }

        // Check if token is older than 60 minutes
        if (now()->diffInMinutes($resetRecord->created_at) > 15) {
            return response()->json(['message' => 'Reset code has expired'], 400);
        }

        $user = User::where('email', $request->email)->first();
        
        if (!$user) {
            return response()->json(['message' => 'User not found'], 404);
        }

        $user->password = Hash::make($request->password);
        $user->save();

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

        return response()->json(['message' => 'Password reset successfully'], 200);
    }

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

        $credentials = $request->only('email', 'password');

        if (!$token = JWTAuth::attempt($credentials)) {
            return response()->json(['message' => 'Invalid credentials'], 401);
        }

        $user = auth('api')->user();

        return response()->json([
            'message' => 'Login successful',
            'access_token' => $token,
            'token_type' => 'Bearer',
            'expires_in' => auth('api')->factory()->getTTL() * 60,
            'user' => $user,
        ]);
    }

    public function logout()
    {
        JWTAuth::logout();
        return response()->json(['message' => 'Logged out successfully']);
    }

    public function refresh()
    {
        try {
            $token = JWTAuth::refresh();
            return response()->json([
                'access_token' => $token,
                'token_type' => 'Bearer'
            ]);
        } catch (JWTException $e) {
            return response()->json(['message' => 'Could not refresh token'], 401);
        }
    }

    public function me()
    {
        return response()->json(auth('api')->user());
    }
}
