<?php
namespace WorkbloomERP\Module\v0\Usuario\Repos;

use DateTimeImmutable;
use WorkbloomERP\Services\DBService;
use WorkbloomERP\Module\v0\Usuario\Models\UsuarioModel;

class UsuarioRepo {
    protected string $usuarioTable = 'usuario';

    public function __construct(
        private DBService $db
    ) {}

    public function insert(UsuarioModel $usuarioModel): ?UsuarioModel {
        $query = 
        "INSERT INTO {$this->usuarioTable} (
            uuid,
            is_active,
            is_root,
            nome_completo,
            nome_usuario,
            email,
            senha_hash,
            created_at
        ) VALUES (
            :uuid,
            :is_active,
            :is_root,
            :nome_completo,
            :nome_usuario,
            :email,
            :senha_hash,
            :created_at
        )";

        $usuarioModel->setCreatedAt(created_at: new DateTimeImmutable());

        $this->db->execute(
            sql: $query,
            params: [
                'uuid' => $usuarioModel->getUuid(),
                'is_active' => $usuarioModel->getIsActive(),
                'is_root' => $usuarioModel->getIsRoot(),
                'nome_completo' => $usuarioModel->getNomeCompleto(),
                'nome_usuario' => $usuarioModel->getNomeUsuario(),
                'email' => $usuarioModel->getEmail(),
                'senha_hash' => $usuarioModel->getSenhaHash(),
                'created_at' => $usuarioModel->getCreatedAt()->format(format: 'Y-m-d H:i:s')
            ]
        );

        $usuarioModel->setId(id: $this->db->lastInsertId());
        return $usuarioModel;
    }

    public function update(UsuarioModel $usuarioModel): ?UsuarioModel {
        $query = 
        "UPDATE {$this->usuarioTable} SET
            is_active = :is_active,
            is_root = :is_root,
            nome_completo = :nome_completo,
            nome_usuario = :nome_usuario,
            email = :email,
            senha_hash = :senha_hash,
            updated_at = :updated_at
        WHERE id = :id OR uuid = :uuid";

        $usuarioModel->setUpdatedAt(updated_at: new DateTimeImmutable());
        $this->db->execute(
            sql: $query,
            params: [
                ':id' => $usuarioModel->getId(),
                ':uuid' => $usuarioModel->getUuid(),
                ':is_active' => $usuarioModel->getIsActive(),
                ':is_root' => $usuarioModel->getIsRoot(),
                ':nome_completo' => $usuarioModel->getNomeCompleto(),
                ':nome_usuario' => $usuarioModel->getNomeUsuario(),
                ':email' => $usuarioModel->getEmail(),
                ':senha_hash' => $usuarioModel->getSenhaHash(),
                ':updated_at' => $usuarioModel->getUpdatedAt()->format(format: 'Y-m-d H:i:s')
            ]
        );

        return $usuarioModel;
    }

    public function delete(UsuarioModel $usuarioModel): ?UsuarioModel {
        $query =
        "UPDATE {$this->usuarioTable} SET
            is_active = 0,
            deleted_at = :deleted_at
        WHERE id = :id OR uuid = :uuid";

        $usuarioModel->setDeletedAt(deleted_at: new DateTimeImmutable());
        
        $this->db->execute(
            sql: $query,
            params: [
                ':id' => $usuarioModel->getId(),
                ':uuid' => $usuarioModel->getUuid(),
                ':deleted_at' => $usuarioModel->getDeletedAt()->format(format: 'Y-m-d H:i:s')
            ]
        );

        return $usuarioModel;
    }

    public function findByIdentifier(string $identifier, mixed $value): ?UsuarioModel {
        $query =
        "SELECT
            id,
            uuid,
            is_active,
            is_root,
            nome_completo,
            nome_usuario,
            email,
            senha_hash,
            created_at,
            updated_at,
            deleted_at
        FROM {$this->usuarioTable}
        WHERE {$identifier} = :value
        AND deleted_at IS NULL
        LIMIT 1";

        $result = $this->db->fetchOne(
            sql: $query,
            params: [
                ':value' => $value
            ]
        );

        return $result ? $this->mapToModel($result) : null;
    }

    public function findByLogin(string $login): ?UsuarioModel {
        $query =
        "SELECT
            id,
            uuid,
            is_active,
            is_root,
            nome_completo,
            nome_usuario,
            email,
            senha_hash,
            created_at,
            updated_at,
            deleted_at
        FROM {$this->usuarioTable}
        WHERE (nome_usuario = :login OR email = :login)
        AND deleted_at IS NULL
        LIMIT 1";

        $result = $this->db->fetchOne(
            sql: $query,
            params: [
                ':login' => $login
            ]
        );

        return $result ? $this->mapToModel($result) : null;
    }

    private function mapToModel(array $data): UsuarioModel {
        return new UsuarioModel(
            id: $data['id'],
            uuid: $data['uuid'],
            is_active: $data['is_active'],
            is_root: $data['is_root'],
            nome_completo: $data['nome_completo'],
            nome_usuario: $data['nome_usuario'],
            email: $data['email'],
            senha_hash: $data['senha_hash'],
            created_at: $data['created_at'] ? new DateTimeImmutable($data['created_at']) : null,
            updated_at: $data['updated_at'] ? new DateTimeImmutable($data['updated_at']) : null,
            deleted_at: $data['deleted_at'] ? new DateTimeImmutable($data['deleted_at']) : null,
        );
    }
}