<?php

namespace App\Domain\Identity\Services;

use App\Domain\Identity\DTOs\AuthResult;
use App\Domain\Identity\Models\LoginHistory;
use App\Models\User;
use Illuminate\Support\Facades\Hash;

class AuthService
{
    private const MAX_FAILED_ATTEMPTS = 5;
    private const LOCKOUT_MINUTES = 30;

    public function attempt(string $identifier, string $password, string $ip, ?string $userAgent = null): AuthResult
    {
        $user = filter_var($identifier, FILTER_VALIDATE_EMAIL)
            ? User::where('email', $identifier)->first()
            : User::where('phone', $identifier)->first();

        if (!$user) {
            return new AuthResult(success: false, reason: 'invalid_credentials');
        }

        // Check if account is locked
        if ($user->isLockedOut()) {
            $this->recordLogin($user, $ip, $userAgent, 'locked', 'Account locked');
            $minutesRemaining = now()->diffInMinutes($user->locked_until);
            return new AuthResult(success: false, reason: 'locked', minutesRemaining: $minutesRemaining);
        }

        // Check account status
        if ($user->status !== 'active') {
            $this->recordLogin($user, $ip, $userAgent, 'blocked', "Account status: {$user->status}");
            return new AuthResult(success: false, reason: 'inactive', status: $user->status);
        }

        // Verify password
        if (!Hash::check($password, $user->password)) {
            $user->increment('failed_login_attempts');

            // Lock if threshold reached
            if ($user->failed_login_attempts >= self::MAX_FAILED_ATTEMPTS) {
                $user->update(['locked_until' => now()->addMinutes(self::LOCKOUT_MINUTES)]);
                $this->recordLogin($user, $ip, $userAgent, 'locked', 'Max attempts exceeded');
                return new AuthResult(success: false, reason: 'locked', minutesRemaining: self::LOCKOUT_MINUTES);
            }

            $this->recordLogin($user, $ip, $userAgent, 'failed', 'Invalid password');
            $attemptsRemaining = self::MAX_FAILED_ATTEMPTS - $user->failed_login_attempts;
            return new AuthResult(success: false, reason: 'invalid_credentials', attemptsRemaining: $attemptsRemaining);
        }

        // SUCCESS
        $user->update([
            'failed_login_attempts' => 0,
            'locked_until' => null,
            'last_login_at' => now(),
            'last_login_ip' => $ip,
            'login_count' => $user->login_count + 1,
        ]);

        $this->recordLogin($user, $ip, $userAgent, 'success');

        return new AuthResult(success: true, user: $user);
    }

    private function recordLogin(User $user, string $ip, ?string $userAgent, string $status, ?string $reason = null): void
    {
        LoginHistory::create([
            'user_id' => $user->id,
            'academy_id' => $user->academy_id,
            'ip_address' => $ip,
            'user_agent' => $userAgent,
            'status' => $status,
            'failed_reason' => $reason,
        ]);
    }
}
