<?php

declare(strict_types=1);

namespace App\Repositories;

final class UserRepository extends BaseRepository
{
    public function allForTenant(int $tenantId): array
    {
        $statement = $this->db->prepare(
            'SELECT id, tenant_id, role, email, first_name, last_name, is_active, created_at, updated_at
             FROM users WHERE tenant_id = :tenant_id ORDER BY role, last_name, first_name'
        );
        $statement->execute(['tenant_id' => $tenantId]);

        return $statement->fetchAll();
    }

    public function allUsers(): array
    {
        return $this->db->query(
            'SELECT u.id, u.tenant_id, u.role, u.email, u.first_name, u.last_name, u.is_active,
                    u.created_at, u.updated_at, t.name AS tenant_name
             FROM users u
             LEFT JOIN tenants t ON t.id = u.tenant_id
             ORDER BY COALESCE(t.name, "System"), u.role, u.last_name, u.first_name'
        )->fetchAll();
    }

    public function findByEmail(string $email): ?array
    {
        $statement = $this->db->prepare(
            'SELECT u.*, t.name AS tenant_name, t.timezone AS tenant_timezone, t.is_active AS tenant_is_active
             FROM users u
             LEFT JOIN tenants t ON t.id = u.tenant_id
             WHERE u.email = :email'
        );
        $statement->execute(['email' => $email]);

        return $statement->fetch() ?: null;
    }

    public function findById(int $id): ?array
    {
        $statement = $this->db->prepare(
            'SELECT u.*, t.name AS tenant_name, t.timezone AS tenant_timezone, t.is_active AS tenant_is_active
             FROM users u
             LEFT JOIN tenants t ON t.id = u.tenant_id
             WHERE u.id = :id'
        );
        $statement->execute(['id' => $id]);

        return $statement->fetch() ?: null;
    }

    public function create(array $data): array
    {
        $timestamp = $this->now();
        $statement = $this->db->prepare(
            'INSERT INTO users
             (tenant_id, role, email, password_hash, first_name, last_name, is_active, created_at, updated_at)
             VALUES (:tenant_id, :role, :email, :password_hash, :first_name, :last_name, :is_active, :created_at, :updated_at)'
        );
        $statement->execute([
            'tenant_id' => $data['tenant_id'],
            'role' => $data['role'],
            'email' => $data['email'],
            'password_hash' => password_hash($data['password'], PASSWORD_DEFAULT),
            'first_name' => $data['first_name'],
            'last_name' => $data['last_name'],
            'is_active' => !empty($data['is_active']) ? 1 : 0,
            'created_at' => $timestamp,
            'updated_at' => $timestamp,
        ]);

        return $this->findById((int) $this->db->lastInsertId());
    }

    public function update(int $id, array $data): ?array
    {
        $current = $this->findById($id);
        if ($current === null) {
            return null;
        }

        $passwordHash = $current['password_hash'];
        if (!empty($data['password'])) {
            $passwordHash = password_hash($data['password'], PASSWORD_DEFAULT);
        }

        $statement = $this->db->prepare(
            'UPDATE users
             SET tenant_id = :tenant_id, role = :role, email = :email, password_hash = :password_hash,
                 first_name = :first_name, last_name = :last_name, is_active = :is_active, updated_at = :updated_at
             WHERE id = :id'
        );
        $statement->execute([
            'id' => $id,
            'tenant_id' => $data['tenant_id'],
            'role' => $data['role'],
            'email' => $data['email'],
            'password_hash' => $passwordHash,
            'first_name' => $data['first_name'],
            'last_name' => $data['last_name'],
            'is_active' => !empty($data['is_active']) ? 1 : 0,
            'updated_at' => $this->now(),
        ]);

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