<?php

declare(strict_types=1);

namespace App\Models;

use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;

class LoginHistory extends Model
{
    use HasFactory;

    public const UPDATED_AT = null;

    protected $fillable = [
        'user_id',
        'ip_address',
        'user_agent',
        'device_type',
        'browser',
        'os',
        'location_country',
        'location_city',
        'success',
        'two_factor_used',
        'is_new_device',
        'device_hash',
    ];

    /** @return array<string, string> */
    protected function casts(): array
    {
        return [
            'success' => 'boolean',
            'two_factor_used' => 'boolean',
            'is_new_device' => 'boolean',
        ];
    }

    /** @return BelongsTo<User, $this> */
    public function user(): BelongsTo
    {
        return $this->belongsTo(User::class);
    }

    /**
     * Generate a device hash from user agent and first 3 octets of IP.
     */
    public static function generateDeviceHash(string $userAgent, string $ip): string
    {
        $ipPrefix = self::getIpPrefix($ip);

        return hash('sha256', $userAgent.$ipPrefix);
    }

    /**
     * Extract the first 3 octets of an IPv4 address, or first 3 groups of an IPv6 address.
     */
    private static function getIpPrefix(string $ip): string
    {
        if (str_contains($ip, '.')) {
            // IPv4: take first 3 octets
            $parts = explode('.', $ip);

            return implode('.', array_slice($parts, 0, 3));
        }

        // IPv6: take first 3 groups
        $parts = explode(':', $ip);

        return implode(':', array_slice($parts, 0, 3));
    }

    /** @param Builder<LoginHistory> $query */
    public function scopeSuccessful(Builder $query): void
    {
        $query->where('success', true);
    }

    /** @param Builder<LoginHistory> $query */
    public function scopeFailed(Builder $query): void
    {
        $query->where('success', false);
    }

    /** @param Builder<LoginHistory> $query */
    public function scopeForUser(Builder $query, int $userId): void
    {
        $query->where('user_id', $userId);
    }
}
