<?php

declare(strict_types=1);

namespace App\Domain\User;

use App\Framework\Database\Attributes\Column;
use App\Framework\Database\Attributes\Entity;

#[Entity(tableName: 'users')]
final readonly class User
{
    public function __construct(
        #[Column(name: 'id', primary: true)]
        public string $id,
        #[Column(name: 'name')]
        public string $name,
        #[Column(name: 'email')]
        public ?string $email = null,
        #[Column(name: 'failed_attempts')]
        public int $failed_attempts = 0,
        #[Column(name: 'last_login')]
        public ?\DateTimeImmutable $last_login = null,
        #[Column(name: 'password_hash')]
        public ?string $password_hash = null,
        #[Column(name: 'last_failed_attempt')]
        public ?\DateTimeImmutable $last_failed_attempt = null,
        #[Column(name: 'locked_until')]
        public ?\DateTimeImmutable $locked_until = null
    ) {
    }

    public function withFailedAttemptsReset(): self
    {
        return new self(
            id: $this->id,
            name: $this->name,
            email: $this->email,
            failed_attempts: 0,
            last_login: new \DateTimeImmutable(),
            password_hash: $this->password_hash,
            last_failed_attempt: $this->last_failed_attempt,
            locked_until: null // Clear lockout on successful login
        );
    }

    public function withIncrementedFailedAttempts(): self
    {
        return new self(
            id: $this->id,
            name: $this->name,
            email: $this->email,
            failed_attempts: $this->failed_attempts + 1,
            last_login: $this->last_login,
            password_hash: $this->password_hash,
            last_failed_attempt: new \DateTimeImmutable(),
            locked_until: $this->locked_until
        );
    }

    public function withLockout(\DateTimeImmutable $lockedUntil): self
    {
        return new self(
            id: $this->id,
            name: $this->name,
            email: $this->email,
            failed_attempts: $this->failed_attempts,
            last_login: $this->last_login,
            password_hash: $this->password_hash,
            last_failed_attempt: $this->last_failed_attempt,
            locked_until: $lockedUntil
        );
    }

    public function withUpdatedLastLogin(\DateTimeImmutable $lastLogin): self
    {
        return new self(
            id: $this->id,
            name: $this->name,
            email: $this->email,
            failed_attempts: $this->failed_attempts,
            last_login: $lastLogin,
            password_hash: $this->password_hash,
            last_failed_attempt: $this->last_failed_attempt,
            locked_until: $this->locked_until
        );
    }
}
