<?php

namespace app\service;

use support\Db;

class AdminUserRepository
{
    public function listAll(): array
    {
        $rows = Db::table('admin_users')
            ->orderByDesc('id')
            ->get()
            ->all();

        return array_map(fn (object $row): array => $this->toArray($row), $rows);
    }

    public function findByUsername(string $username): ?array
    {
        $row = Db::table('admin_users')
            ->where('username', $username)
            ->where('is_active', true)
            ->first();

        return $row ? $this->toArray($row) : null;
    }

    public function findById(int $id): ?array
    {
        $row = Db::table('admin_users')
            ->where('id', $id)
            ->where('is_active', true)
            ->first();

        return $row ? $this->toArray($row) : null;
    }

    public function findAnyById(int $id): ?array
    {
        $row = Db::table('admin_users')->where('id', $id)->first();
        return $row ? $this->toArray($row) : null;
    }

    public function findAnyByUsername(string $username): ?array
    {
        $row = Db::table('admin_users')->where('username', $username)->first();
        return $row ? $this->toArray($row) : null;
    }

    public function touchLastLogin(int $id): void
    {
        Db::table('admin_users')
            ->where('id', $id)
            ->update(['last_login_at' => Db::raw('CURRENT_TIMESTAMP')]);
    }

    public function create(string $username, string $password, ?string $displayName = null): array
    {
        $id = Db::table('admin_users')->insertGetId([
            'username' => $username,
            'display_name' => $displayName,
            'password_hash' => password_hash($password, PASSWORD_DEFAULT),
            'is_active' => true,
            'last_login_at' => null,
        ]);

        return $this->findAnyById((int) $id) ?? [];
    }

    public function updateUser(int $id, array $fields): ?array
    {
        $updates = [];

        if (array_key_exists('display_name', $fields)) {
            $displayName = $fields['display_name'];
            $updates['display_name'] = $displayName === null ? null : trim((string) $displayName);
        }

        if (array_key_exists('password', $fields) && trim((string) $fields['password']) !== '') {
            $updates['password_hash'] = password_hash((string) $fields['password'], PASSWORD_DEFAULT);
        }

        if (array_key_exists('is_active', $fields)) {
            $updates['is_active'] = (bool) $fields['is_active'];
        }

        if ($updates !== []) {
            Db::table('admin_users')->where('id', $id)->update($updates);
        }

        return $this->findAnyById($id);
    }

    private function toArray(object $row): array
    {
        return [
            'id' => (int) $row->id,
            'username' => (string) $row->username,
            'display_name' => $row->display_name,
            'password_hash' => (string) $row->password_hash,
            'is_active' => (bool) $row->is_active,
            'last_login_at' => $row->last_login_at,
            'created_time' => $row->created_time,
            'updated_time' => $row->updated_time,
        ];
    }
}
