<?php

namespace App\Http\Controllers\Api;

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

class AuthApiController extends Controller
{
    /**
     * Handle authentication login request.
     */
    public function login(Request $request)
    {
        $credentials = $request->validate([
            'email' => 'required|email',
            'password' => 'required',
        ]);

        if (Auth::attempt($credentials)) {
            $request->session()->regenerate();

            $user = Auth::user();
            if ($user) {
                $user->load('addresses');
            }

            return response()->json([
                'message' => 'Logged in successfully',
                'user' => $user,
            ]);
        }

        throw ValidationException::withMessages([
            'email' => [__('auth.failed')],
        ]);
    }

    /**
     * Handle authentication registration request.
     */
    public function register(Request $request)
    {
        $request->validate([
            'name' => 'required|string|max:255',
            'email' => 'required|string|email|max:255|unique:users',
            'phone' => 'nullable|string|max:20',
            'password' => 'required|string|min:8|confirmed',
            'address' => 'nullable|string|max:500',
        ]);

        $user = User::create([
            'name' => $request->name,
            'email' => $request->email,
            'phone' => $request->phone,
            'password' => Hash::make($request->password),
            'role' => 'customer',
        ]);

        if ($request->address) {
            $user->addresses()->create([
                'street' => $request->address,
                'zip' => '1000',
                'city' => 'Dhaka',
                'country' => 'Bangladesh',
            ]);
        }

        Auth::login($user);
        $request->session()->regenerate();

        // Log successful registration in audits if needed
        try {
            \App\Services\AuditLogger::log(
                'register_success',
                'User registered successfully: ' . $user->name . ' (' . $user->email . ')',
                null,
                null,
                $user->id
            );
        } catch (\Exception $e) {
            // Ignore audit logs failure
        }

        $user->load('addresses');

        return response()->json([
            'message' => 'Registered and logged in successfully',
            'user' => $user,
        ], 201);
    }

    /**
     * Log the user out of the application.
     */
    public function logout(Request $request)
    {
        $user = Auth::user();
        
        Auth::guard('web')->logout();
        $request->session()->invalidate();
        $request->session()->regenerateToken();

        if ($user) {
            try {
                \App\Services\AuditLogger::log(
                    'logout_success',
                    'User logged out successfully: ' . $user->name . ' (' . $user->email . ')',
                    null,
                    null,
                    $user->id
                );
            } catch (\Exception $e) {
                // Ignore audit logs failure
            }
        }

        return response()->json([
            'message' => 'Logged out successfully',
        ]);
    }

    /**
     * Send OTP to the mobile number.
     */
    public function sendOtp(Request $request)
    {
        $request->validate([
            'phone' => 'required|string|regex:/^(?:\+8801|8801|01)[3-9]\d{8}$/',
        ]);

        // Normalize phone number to standard 11 digits (e.g. 017xxxxxxxx)
        $phone = $request->phone;
        if (str_starts_with($phone, '+880')) {
            $phone = substr($phone, 3);
        } elseif (str_starts_with($phone, '880')) {
            $phone = substr($phone, 2);
        }

        // Generate actual random 6-digit OTP code
        $otp = (string) rand(100000, 999999);
        
        // Save OTP code in cache for 5 minutes
        \Illuminate\Support\Facades\Cache::put('otp_' . $phone, $otp, 300);

        $siteName = \App\Models\Setting::getValue('site_name', 'Sawdabazar');
        $otpTemplate = \App\Models\Setting::getValue('sms_template_login_otp', 'Your OTP code for {site_name} login is: {code}. Valid for 5 minutes.');
        $message = str_replace(['{site_name}', '{code}'], [$siteName, $otp], $otpTemplate);

        // Send real SMS via SmsService
        $smsResult = \App\Services\SmsService::sendSms($request->phone, $message);

        // Track audit logs for OTP request if audit log exists
        try {
            \App\Services\AuditLogger::log(
                'otp_sent',
                'OTP requested for phone: ' . $phone . '. SMS status: ' . ($smsResult['success'] ? 'success' : 'failed'),
                null,
                null
            );
        } catch (\Exception $e) {
            // Ignore audit logs failure
        }

        $responsePayload = [
            'message' => 'OTP sent successfully.',
            'phone' => $phone,
        ];

        // For local development convenience, output the OTP in the message
        if (app()->environment('local')) {
            $responsePayload['demo_otp'] = $otp;
            $responsePayload['message'] .= ' (Local Mode - OTP: ' . $otp . ')';
        }

        return response()->json($responsePayload);
    }

    /**
     * Verify OTP and login or register.
     */
    public function verifyOtp(Request $request)
    {
        $request->validate([
            'phone' => 'required|string',
            'code' => 'required|string|min:4|max:8',
        ]);

        $phone = $request->phone;
        // Normalize phone
        if (str_starts_with($phone, '+880')) {
            $phone = substr($phone, 3);
        } elseif (str_starts_with($phone, '880')) {
            $phone = substr($phone, 2);
        }

        $isLocal = app()->environment('local');

        if (!$cachedOtp && (!$isLocal || $request->code !== '123456')) {
            throw ValidationException::withMessages([
                'code' => ['OTP has expired or is invalid.'],
            ]);
        }

        if ($cachedOtp && $cachedOtp !== $request->code && (!$isLocal || $request->code !== '123456')) {
            throw ValidationException::withMessages([
                'code' => ['Invalid OTP code.'],
            ]);
        }

        // OTP verified successfully. Find or create the user.
        $user = User::where('phone', $phone)->first();

        if (!$user) {
            // Check if there is an existing user with email phone@sawdabazar.com
            // to avoid duplicates and create a new customer.
            $email = 'phone_' . $phone . '@sawdabazar.com';
            $user = User::where('email', $email)->first();

            if (!$user) {
                $user = User::create([
                    'name' => 'Customer ' . substr($phone, -4),
                    'email' => $email,
                    'phone' => $phone,
                    'password' => Hash::make(\Illuminate\Support\Str::random(16)),
                    'role' => 'customer',
                ]);
            }
        }

        Auth::login($user);
        $request->session()->regenerate();
        
        // Remove verified OTP from cache
        \Illuminate\Support\Facades\Cache::forget('otp_' . $phone);

        try {
            \App\Services\AuditLogger::log(
                'otp_login_success',
                'User logged in via OTP: ' . $user->name . ' (' . $phone . ')',
                null,
                null,
                $user->id
            );
        } catch (\Exception $e) {
            // Ignore audit logs failure
        }

        $user->load('addresses');

        return response()->json([
            'message' => 'Logged in successfully',
            'user' => $user,
        ]);
    }

    /**
     * Send password reset verification code.
     */
    public function forgotPassword(Request $request)
    {
        $request->validate([
            'email_or_phone' => 'required|string',
        ]);

        $input = $request->email_or_phone;
        
        // Find user by email or phone
        $user = User::where('email', $input)
            ->orWhere('phone', $input)
            ->first();

        if (!$user) {
            throw ValidationException::withMessages([
                'email_or_phone' => ['No account found with this email or phone number.'],
            ]);
        }

        // Generate actual random 6-digit verification code
        $code = (string) rand(100000, 999999);
        
        // Cache code linked to input for 10 minutes
        \Illuminate\Support\Facades\Cache::put('password_reset_code_' . $input, $code, 600);

        $siteName = \App\Models\Setting::getValue('site_name', 'Sawdabazar');
        if (str_contains($input, '@')) {
            $emailTemplate = \App\Models\Setting::getValue('email_template_password_reset', 'Your password reset verification code for {site_name} is: {code}. Valid for 10 minutes.');
            $message = str_replace(['{site_name}', '{code}'], [$siteName, $code], $emailTemplate);
        } else {
            $smsTemplate = \App\Models\Setting::getValue('sms_template_password_reset', 'Your password reset verification code for {site_name} is: {code}. Valid for 10 minutes.');
            $message = str_replace(['{site_name}', '{code}'], [$siteName, $code], $smsTemplate);
        }
        $sendType = 'unknown';
        $sendSuccess = false;

        // Dispatch via SMS or Email based on input
        if (str_contains($input, '@')) {
            try {
                \Illuminate\Support\Facades\Mail::raw($message, function($m) use ($user, $siteName) {
                    $m->to($user->email)->subject("Password Reset Verification Code - {$siteName}");
                });
                $sendType = 'email';
                $sendSuccess = true;
            } catch (\Exception $ex) {
                \Illuminate\Support\Facades\Log::error('Failed to send forgot password email: ' . $ex->getMessage());
                $sendType = 'email';
                $sendSuccess = false;
            }
        } else {
            $smsResult = \App\Services\SmsService::sendSms($user->phone, $message);
            $sendType = 'sms';
            $sendSuccess = $smsResult['success'];
        }

        try {
            \App\Services\AuditLogger::log(
                'password_reset_requested',
                'Password reset code requested for: ' . $input . ' via ' . $sendType . '. Dispatch status: ' . ($sendSuccess ? 'success' : 'failed'),
                null,
                null,
                $user->id
            );
        } catch (\Exception $e) {
            // Ignore audit logs failure
        }

        $responsePayload = [
            'message' => 'Verification code sent successfully.',
            'email_or_phone' => $input,
        ];

        // For local development convenience, output the code in the message
        if (app()->environment('local')) {
            $responsePayload['demo_code'] = $code;
            $responsePayload['message'] .= ' (Local Mode - Verification Code: ' . $code . ')';
        }

        return response()->json($responsePayload);
    }

    /**
     * Reset user password using verification code.
     */
    public function resetPassword(Request $request)
    {
        $request->validate([
            'email_or_phone' => 'required|string',
            'code' => 'required|string',
            'password' => 'required|string|min:8',
        ]);

        $input = $request->email_or_phone;
        $isLocal = app()->environment('local');

        if (!$cachedCode && (!$isLocal || $request->code !== '123456')) {
            throw ValidationException::withMessages([
                'code' => ['Verification code has expired or is invalid.'],
            ]);
        }

        if ($cachedCode && $cachedCode !== $request->code && (!$isLocal || $request->code !== '123456')) {
            throw ValidationException::withMessages([
                'code' => ['Invalid verification code.'],
            ]);
        }

        // Find user and update password
        $user = User::where('email', $input)
            ->orWhere('phone', $input)
            ->first();

        if (!$user) {
            throw ValidationException::withMessages([
                'email_or_phone' => ['User not found.'],
            ]);
        }

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

        // Remove verification code from cache
        \Illuminate\Support\Facades\Cache::forget('password_reset_code_' . $input);

        try {
            \App\Services\AuditLogger::log(
                'password_reset_success',
                'Password successfully reset for: ' . $input,
                null,
                null,
                $user->id
            );
        } catch (\Exception $e) {
            // Ignore audit logs failure
        }

        return response()->json([
            'message' => 'Password reset successfully. You can now log in with your new password.',
        ]);
    }

    /**
     * Get the authenticated user.
     */
    public function user(Request $request)
    {
        $user = $request->user();
        if ($user) {
            $user->load('addresses');
        }
        return response()->json([
            'user' => $user,
        ]);
    }

    /**
     * Delete the authenticated user account and all associated data.
     */
    public function deleteAccount(Request $request)
    {
        $user = Auth::user();
        if (!$user) {
            return response()->json([
                'success' => false,
                'message' => 'Unauthenticated.',
            ], 401);
        }

        try {
            // Delete wishlist items
            $user->wishlist()->delete();

            // Delete addresses
            $user->addresses()->delete();

            // Delete reviews
            \App\Models\ProductReview::where('user_id', $user->id)->delete();

            // Delete support tickets
            \App\Models\SupportTicket::where('user_id', $user->id)->delete();

            // Log activity/audit before deletion
            try {
                \App\Services\AuditLogger::log(
                    'account_deleted',
                    'User deleted their account: ' . $user->name . ' (' . $user->email . ')',
                    null,
                    null,
                    $user->id
                );
            } catch (\Exception $e) {
                // Ignore audit logs failure
            }

            // Log out user
            Auth::guard('web')->logout();
            $request->session()->invalidate();
            $request->session()->regenerateToken();

            // Finally delete user
            $user->delete();

            return response()->json([
                'success' => true,
                'message' => 'Account deleted successfully.',
            ]);
        } catch (\Exception $e) {
            return response()->json([
                'success' => false,
                'message' => 'Failed to delete account: ' . $e->getMessage(),
            ], 500);
        }
    }
}
