<?php

declare(strict_types=1);

namespace ServerManager\Models;

use ServerManager\Core\Database;
use ServerManager\Core\Security;

class User
{
    private Database $db;
    private Security $security;

    public function __construct()
    {
        $this->db = Database::getInstance();
        $this->security = new Security();
    }

    public function findById(int $id): ?array
    {
        return $this->db->fetch('SELECT * FROM users WHERE id = ? AND status = \'active\'', [$id]);
    }

    public function findByUsername(string $username): ?array
    {
        return $this->db->fetch('SELECT * FROM users WHERE username = ? AND status = \'active\'', [$username]);
    }

    public function findByEmail(string $email): ?array
    {
        return $this->db->fetch('SELECT * FROM users WHERE email = ? AND status = \'active\'', [$email]);
    }

    public function authenticate(string $username, string $password): ?array
    {
        $user = $this->findByUsername($username);

        if (!$user) {
            return null;
        }

        if ($user['status'] !== 'active' || !$user['is_active']) {
            return null;
        }

        if (!$this->security->verifyPassword($password, $user['password_hash'])) {
            return null;
        }

        $this->updateLastLogin($user['id']);

        return $user;
    }

    public function create(array $data): int
    {
        $data['password_hash'] = $this->security->hashPassword($data['password']);
        unset($data['password']);

        $data['created_at'] = date('Y-m-d H:i:s');
        $data['updated_at'] = date('Y-m-d H:i:s');

        if (empty($data['api_token'])) {
            $data['api_token'] = $this->security->generateApiToken();
        }

        return $this->db->insert('users', $data);
    }

    public function update(int $id, array $data): bool
    {
        if (isset($data['password'])) {
            $data['password_hash'] = $this->security->hashPassword($data['password']);
            unset($data['password']);
        }

        $data['updated_at'] = date('Y-m-d H:i:s');

        return $this->db->update('users', $data, 'id = ?', [$id]) > 0;
    }

    public function delete(int $id): bool
    {
        return $this->db->update('users', [
            'status' => 'deleted',
            'is_active' => 0,
            'updated_at' => date('Y-m-d H:i:s'),
        ], 'id = ?', [$id]) > 0;
    }

    public function getAll(int $page = 1, int $perPage = 20): array
    {
        $offset = ($page - 1) * $perPage;

        $total = $this->db->fetch("SELECT COUNT(*) as total FROM users WHERE status = 'active'");
        $users = $this->db->fetchAll(
            'SELECT id, username, email, role, status, is_active, last_login_at, created_at 
             FROM users WHERE status = \'active\' ORDER BY created_at DESC LIMIT ? OFFSET ?',
            [$perPage, $offset]
        );

        return [
            'data' => $users,
            'total' => (int) ($total['total'] ?? 0),
            'page' => $page,
            'per_page' => $perPage,
            'total_pages' => ceil((int) ($total['total'] ?? 0) / $perPage),
        ];
    }

    public function findByApiToken(string $token): ?array
    {
        return $this->db->fetch('SELECT * FROM users WHERE api_token = ? AND status = \'active\' AND is_active = 1', [$token]);
    }

    public function updateLastLogin(int $id): void
    {
        $this->db->update('users', ['last_login_at' => date('Y-m-d H:i:s')], 'id = ?', [$id]);
    }

    public function countAll(): int
    {
        $result = $this->db->fetch("SELECT COUNT(*) as total FROM users WHERE status = 'active'");
        return (int) ($result['total'] ?? 0);
    }
}
