<?php

namespace App\Services\Auth;

use App\Models\User;
use Illuminate\Support\Facades\Hash;
use Illuminate\Validation\Rules\Password;
use Illuminate\Validation\ValidationException;

class PasswordPolicyService
{
    /**
     * Get the password validation rules based on system settings.
     */
    public static function getRules(): Password
    {
        $rules = Password::min(get_setting('password_min_length', 8))
            ->max(get_setting('password_max_length', 64));

        $requireUpper = get_setting('password_require_uppercase', false);
        $requireLower = get_setting('password_require_lowercase', false);

        if ($requireUpper && $requireLower) {
            $rules->mixedCase();
        } elseif ($requireUpper) {
            $rules->rules(['regex:/[A-Z]/']);
        } elseif ($requireLower) {
            $rules->rules(['regex:/[a-z]/']);
        }

        if (get_setting('password_require_numeric', false)) {
            $rules->numbers();
        }

        if (get_setting('password_require_special', false)) {
            $rules->symbols();
        }

        return $rules;
    }

    /**
     * Check if the password has expired for a user.
     */
    public static function isPasswordExpired(User $user): bool
    {
        $expiryDays = get_setting('password_expiry_days', 0);

        if ($expiryDays <= 0) {
            return false;
        }

        $lastChanged = $user->password_changed_at ?? $user->created_at;

        return $lastChanged->addDays($expiryDays)->isPast();
    }

    /**
     * Verify that the new password is not in the user's password history.
     */
    public static function checkHistory(User $user, string $newPassword): void
    {
        $historyCount = get_setting('password_history_count', 0);

        if ($historyCount <= 0) {
            return;
        }

        $histories = $user->passwordHistories()
            ->latest()
            ->take($historyCount)
            ->get();

        foreach ($histories as $history) {
            if (Hash::check($newPassword, $history->password)) {
                throw ValidationException::withMessages([
                    'password' => __('You cannot reuse any of your last :count passwords.', ['count' => $historyCount]),
                ]);
            }
        }
    }

    /**
     * Record the current password into history and update changed_at timestamp.
     */
    public static function recordPasswordChange(User $user, string $newPasswordHash): void
    {
        $historyCount = get_setting('password_history_count', 0);

        // 1. Record to history (only if enabled)
        if ($historyCount > 0) {
            $user->passwordHistories()->create([
                'password' => $newPasswordHash,
            ]);
        }

        // 2. Update timestamp
        $user->update([
            'password_changed_at' => now(),
        ]);

        // 3. Optional: Prune old history — keep exactly $historyCount entries
        $historyCount = get_setting('password_history_count', 0);
        if ($historyCount > 0) {
            $user->passwordHistories()
                ->orderBy('created_at', 'desc')
                ->skip($historyCount)
                ->take(100)
                ->delete();
        }
    }
}
