<?php

declare(strict_types=1);

namespace App\Application\User;

use App\Application\GraphQL\ValueObjects\UserStats;
use App\Framework\Core\ValueObjects\EmailAddress;

/**
 * User Service mit framework-konformen Value Objects
 * Ersetzt primitive Arrays durch typisierte Value Objects
 */
final readonly class UserService
{
    public function __construct()
    {
        // In einem echten System würden hier Repository und andere Dependencies injiziert
    }

    /**
     * @return array<int, UserData>
     */
    public function findAll(): array
    {
        // Demo-Implementation - würde normalerweise Repository verwenden
        return [
            new UserData(
                id: 1,
                email: new EmailAddress('john@example.com'),
                name: 'John Doe',
                active: true
            ),
            new UserData(
                id: 2,
                email: new EmailAddress('jane@example.com'),
                name: 'Jane Smith',
                active: true
            ),
        ];
    }

    public function findById(int $id): ?UserData
    {
        // Demo-Implementation
        $users = $this->findAll();

        foreach ($users as $user) {
            if ($user->id === $id) {
                return $user;
            }
        }

        return null;
    }

    public function findByEmail(EmailAddress $email): ?UserData
    {
        $users = $this->findAll();

        foreach ($users as $user) {
            if ($user->email->equals($email)) {
                return $user;
            }
        }

        return null;
    }

    public function create(EmailAddress $email, string $name): UserData
    {
        // Demo-Implementation - würde normalerweise Repository verwenden
        return new UserData(
            id: $this->getNextId(),
            email: $email,
            name: $name,
            active: true
        );
    }

    public function update(int $id, ?EmailAddress $email = null, ?string $name = null): ?UserData
    {
        $existingUser = $this->findById($id);

        if ($existingUser === null) {
            return null;
        }

        // Immutable Update Pattern
        return new UserData(
            id: $existingUser->id,
            email: $email ?? $existingUser->email,
            name: $name ?? $existingUser->name,
            active: $existingUser->active
        );
    }

    public function deactivate(int $id): ?UserData
    {
        $existingUser = $this->findById($id);

        if ($existingUser === null) {
            return null;
        }

        return new UserData(
            id: $existingUser->id,
            email: $existingUser->email,
            name: $existingUser->name,
            active: false
        );
    }

    public function delete(int $id): bool
    {
        // Demo-Implementation - würde normalerweise Repository verwenden
        $user = $this->findById($id);

        return $user !== null;
    }

    /**
     * @return array<string, mixed>
     */
    public function getStats(): array
    {
        $stats = $this->getUserStats();

        return $stats->toArray();
    }

    public function getUserStats(): UserStats
    {
        $users = $this->findAll();
        $totalUsers = count($users);
        $activeUsers = count(array_filter($users, fn ($user) => $user->active));

        return new UserStats(
            totalUsers: $totalUsers,
            activeUsers: $activeUsers,
            inactiveUsers: $totalUsers - $activeUsers,
            averageAge: 0.0, // Demo data doesn't have ages
            usersCreatedToday: 0,
            usersCreatedThisWeek: 0,
            usersCreatedThisMonth: 0
        );
    }

    private function getNextId(): int
    {
        // Demo-Implementation
        return count($this->findAll()) + 1;
    }
}
