<?php

namespace App\Http\Controllers\Frontend\Settings;

use App\Helpers\PasswordHelper;
use App\Http\Controllers\Controller;
use App\Models\PasswordChangeOtp;
use App\Notifications\PasswordChangeOtpNotification;
use App\Notifications\PasswordChangedNotification;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Validation\Rules\Password;
use Inertia\Inertia;
use Inertia\Response;

class PasswordController extends Controller
{
    /**
     * Show the user's password settings page.
     */
    public function edit(): Response
    {
        $pinFieldEnabled = DB::table('settings')->where('key', 'pin_field_enabled')->value('value') ?? '1';
        $passwordOtpEnabled = DB::table('settings')->where('key', 'password_otp_enabled')->value('value') ?? '1';
        
        // Check if there's a pending OTP for this user
        $pendingOtp = PasswordChangeOtp::where('user_id', auth()->id())
            ->where('expires_at', '>', now())
            ->first();
        
        $user = auth()->user();
        
        // Check if user is a Google OAuth user (has google_id and hasn't set password yet)
        $isGoogleUser = !empty($user->google_id);
        
        return Inertia::render('frontend/settings/password', [
            'pinFieldEnabled' => $pinFieldEnabled === '1',
            'passwordOtpEnabled' => $passwordOtpEnabled === '1',
            'hasPendingOtp' => $pendingOtp !== null,
            'otpExpiresAt' => $pendingOtp?->expires_at?->toIso8601String(),
            'maskedEmail' => $this->maskEmail($user->email),
            'isGoogleUser' => $isGoogleUser,
        ]);
    }

    /**
     * Request OTP for password change.
     */
    public function requestOtp(Request $request)
    {
        $user = $request->user();
        $pinFieldEnabled = DB::table('settings')->where('key', 'pin_field_enabled')->value('value') ?? '1';

        $rules = [
            'current_password' => ['required', 'string'],
            'password' => ['required', Password::defaults(), 'confirmed'],
        ];

        if ($pinFieldEnabled === '1') {
            $rules['pin'] = ['required', 'digits:6'];
        }

        $validated = $request->validate($rules);

        // Verify current password
        if (!PasswordHelper::verifyPassword($user->name, $validated['current_password'], $user->passwd)) {
            return back()->withErrors(['current_password' => 'Current password is incorrect.']);
        }

        // Verify PIN matches the stored qq field (only if PIN field is enabled)
        if ($pinFieldEnabled === '1' && $user->qq !== $validated['pin']) {
            return back()->withErrors(['pin' => 'Security PIN is incorrect.']);
        }

        // Delete any existing OTP for this user
        PasswordChangeOtp::where('user_id', $user->ID)->delete();

        // Generate new OTP
        $otp = PasswordChangeOtp::generateOtp();

        // Store OTP and new password hash
        $otpRecord = PasswordChangeOtp::create([
            'user_id' => $user->ID,
            'otp' => $otp,
            'new_password_hash' => PasswordHelper::encryptPassword($user->name, $validated['password']),
            'expires_at' => now()->addMinutes(10),
        ]);

        // Send OTP via email
        try {
            $user->notify(new PasswordChangeOtpNotification($otp));
        } catch (\Exception $e) {
            // Delete the OTP if email fails
            PasswordChangeOtp::where('user_id', $user->ID)->delete();
            return back()->withErrors(['error' => 'Failed to send OTP email. Please try again.']);
        }

        // Redirect back to show OTP form
        return back()->with(['has_pending_otp' => true, 'otp_expires_at' => $otpRecord->expires_at->toIso8601String()]);
    }

    /**
     * Verify OTP and update password.
     */
    public function verifyOtp(Request $request)
    {
        $user = $request->user();

        $validated = $request->validate([
            'otp' => ['required', 'digits:6'],
        ]);

        $otpRecord = PasswordChangeOtp::where('user_id', $user->ID)->first();

        if (!$otpRecord) {
            return back()->withErrors(['otp' => 'No active password change request found.']);
        }

        if ($otpRecord->isExpired()) {
            $otpRecord->delete();
            return back()->withErrors(['otp' => 'OTP code has expired. Please request a new one.']);
        }

        if ($otpRecord->isMaxAttempts()) {
            $otpRecord->delete();
            return back()->withErrors(['otp' => 'Too many attempts. Please request a new OTP.']);
        }

        if ($otpRecord->otp !== $validated['otp']) {
            $otpRecord->incrementAttempts();
            $remaining = 5 - $otpRecord->attempts;
            return back()->withErrors(['otp' => "Invalid OTP code. Attempts remaining: {$remaining}"]);
        }

        // OTP is valid, update the password
        $user->update([
            'passwd' => $otpRecord->new_password_hash,
        ]);

        // Delete the OTP record
        $otpRecord->delete();

        // Send password changed notification
        $user->notify(new PasswordChangedNotification());

        // Redirect back to password settings page
        return back()->with('success', 'Password changed successfully!');
    }

    /**
     * Resend OTP.
     */
    public function resendOtp(Request $request)
    {
        $user = $request->user();

        $otpRecord = PasswordChangeOtp::where('user_id', $user->ID)->first();

        if (!$otpRecord) {
            return back()->withErrors(['otp' => 'No active password change request found.']);
        }

        // Generate new OTP
        $otp = PasswordChangeOtp::generateOtp();

        $otpRecord->update([
            'otp' => $otp,
            'attempts' => 0,
            'expires_at' => now()->addMinutes(10),
        ]);

        // Send OTP via email
        try {
            $user->notify(new PasswordChangeOtpNotification($otp));
        } catch (\Exception $e) {
            return back()->withErrors(['error' => 'Failed to send OTP email. Please try again.']);
        }

        // Redirect back with updated expiry time
        return back()->with(['has_pending_otp' => true, 'otp_expires_at' => $otpRecord->expires_at->toIso8601String()]);
    }

    /**
     * Cancel pending OTP request.
     */
    public function cancelOtp(Request $request)
    {
        PasswordChangeOtp::where('user_id', $request->user()->ID)->delete();

        // Redirect back without pending OTP
        return back()->with(['has_pending_otp' => false]);
    }

    /**
     * Mask email for display.
     */
    private function maskEmail(?string $email): string
    {
        if (!$email) {
            return '';
        }

        $parts = explode('@', $email);
        if (count($parts) !== 2) {
            return $email;
        }

        $name = $parts[0];
        $domain = $parts[1];

        if (strlen($name) <= 2) {
            $maskedName = $name[0] . '***';
        } else {
            $maskedName = $name[0] . str_repeat('*', strlen($name) - 2) . $name[strlen($name) - 1];
        }

        return $maskedName . '@' . $domain;
    }

    /**
     * Setup password for Google OAuth users (first time password setup).
     */
    public function setupPassword(Request $request)
    {
        $user = $request->user();
        
        // Only allow for Google OAuth users
        if (empty($user->google_id)) {
            return back()->withErrors(['error' => 'This feature is only available for Google OAuth users.']);
        }
        
        $pinFieldEnabled = DB::table('settings')->where('key', 'pin_field_enabled')->value('value') ?? '1';

        $rules = [
            'password' => ['required', Password::defaults(), 'confirmed'],
        ];

        if ($pinFieldEnabled === '1') {
            $rules['pin'] = ['required', 'digits:6'];
        }

        $validated = $request->validate($rules);

        // Verify PIN matches the stored qq field (only if PIN field is enabled)
        if ($pinFieldEnabled === '1' && $user->qq !== $validated['pin']) {
            return back()->withErrors(['pin' => 'Security PIN is incorrect.']);
        }

        $user->update([
            'passwd' => PasswordHelper::encryptPassword($user->name, $validated['password']),
        ]);

        // Send password changed notification
        $user->notify(new PasswordChangedNotification());

        return back()->with('success', 'Password set successfully! You can now login with your username and password.');
    }

    /**
     * Update the user's password (legacy method - kept for compatibility).
     */
    public function update(Request $request)
    {
        $user = $request->user();
        $pinFieldEnabled = DB::table('settings')->where('key', 'pin_field_enabled')->value('value') ?? '1';

        $rules = [
            'current_password' => ['required', 'string'],
            'password' => ['required', Password::defaults(), 'confirmed'],
        ];

        if ($pinFieldEnabled === '1') {
            $rules['pin'] = ['required', 'digits:6'];
        }

        $validated = $request->validate($rules);

        // Verify current password
        if (!PasswordHelper::verifyPassword($user->name, $validated['current_password'], $user->passwd)) {
            return back()->withErrors(['current_password' => 'The current password is incorrect.']);
        }

        // Verify PIN matches the stored qq field (only if PIN field is enabled)
        if ($pinFieldEnabled === '1' && $user->qq !== $validated['pin']) {
            return back()->withErrors(['pin' => 'The security PIN is incorrect.']);
        }

        $user->update([
            'passwd' => PasswordHelper::encryptPassword($user->name, $validated['password']),
        ]);

        // Send password changed notification
        $user->notify(new PasswordChangedNotification());

        return back()->with('success', 'Password changed successfully!');
    }
}
