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

use DateTimeImmutable;
use WorkbloomERP\Services\DBService;
use WorkbloomERP\Module\v0\Empresa\Models\EmpresaModel;

class EmpresaRepo {
    protected string $empresaTable = 'empresa';

    public function __construct(
        protected DBService $db
    ) {}

    public function insert(EmpresaModel $empresaModel): ?EmpresaModel {
        $query =
        "INSERT INTO {$this->empresaTable} (
            uuid,
            is_active,
            nome_empresarial,
            nome_fantasia,
            tipo,
            matriz_id,
            document_cnpj,
            document_ie,
            document_im,
            regime_tributario,
            end_cep,
            end_ibge,
            end_logradouro,
            end_numero,
            end_complemento,
            end_bairro,
            end_cidade,
            end_uf,
            created_at
        ) VALUES (
            :uuid,
            :is_active,
            :nome_empresarial,
            :nome_fantasia,
            :tipo,
            :matriz_id,
            :document_cnpj,
            :document_ie,
            :document_im,
            :regime_tributario,
            :end_cep,
            :end_ibge,
            :end_logradouro,
            :end_numero,
            :end_complemento,
            :end_bairro,
            :end_cidade,
            :end_uf,
            :created_at
        )";

        $empresaModel->setCreatedAt(new DateTimeImmutable());

        $this->db->execute(
            sql: $query,
            params: [
                ':uuid' => $empresaModel->getUuid(),
                ':is_active' => $empresaModel->getIsActive(),
                ':nome_empresarial' => $empresaModel->getNomeEmpresarial(),
                ':nome_fantasia' => $empresaModel->getNomeFantasia(),
                ':tipo' => $empresaModel->getTipo(),
                ':matriz_id' => $empresaModel->getMatrizId(),
                ':document_cnpj' => $empresaModel->getDocumentCnpj(),
                ':document_ie' => $empresaModel->getDocumentIe(),
                ':document_im' => $empresaModel->getDocumentIm(),
                ':regime_tributario' => $empresaModel->getRegimeTributario(),
                ':end_cep' => $empresaModel->getEndCep(),
                ':end_ibge' => $empresaModel->getEndIbge(),
                ':end_logradouro' => $empresaModel->getEndLogradouro(),
                ':end_numero' => $empresaModel->getEndNumero(),
                ':end_complemento' => $empresaModel->getEndComplemento(),
                ':end_bairro' => $empresaModel->getEndBairro(),
                ':end_cidade' => $empresaModel->getEndCidade(),
                ':end_uf' => $empresaModel->getEndUf(),
                ':created_at' => $empresaModel->getCreatedAt()->format('Y-m-d H:i:s'),
            ]
        );

        $empresaModel->setId($this->db->lastInsertId());
        return $empresaModel;
    }

    public function update(EmpresaModel $empresaModel): bool {
        $query =
        "UPDATE {$this->empresaTable} SET
            is_active = :is_active,
            nome_empresarial = :nome_empresarial,
            nome_fantasia = :nome_fantasia,
            tipo = :tipo,
            matriz_id = :matriz_id,
            document_cnpj = :document_cnpj,
            document_ie = :document_ie,
            document_im = :document_im,
            regime_tributario = :regime_tributario,
            end_cep = :end_cep,
            end_ibge = :end_ibge,
            end_logradouro = :end_logradouro,
            end_numero = :end_numero,
            end_complemento = :end_complemento,
            end_bairro = :end_bairro,
            end_cidade = :end_cidade,
            end_uf = :end_uf,
            updated_at = :updated_at
        WHERE id = :id OR uuid = :uuid";

        $empresaModel->setUpdatedAt(new DateTimeImmutable());

        return $this->db->execute(
            sql: $query,
            params: [
                ':id' => $empresaModel->getId(),
                ':uuid' => $empresaModel->getUuid(),
                ':is_active' => $empresaModel->getIsActive(),
                ':nome_empresarial' => $empresaModel->getNomeEmpresarial(),
                ':nome_fantasia' => $empresaModel->getNomeFantasia(),
                ':tipo' => $empresaModel->getTipo(),
                ':matriz_id' => $empresaModel->getMatrizId(),
                ':document_cnpj' => $empresaModel->getDocumentCnpj(),
                ':document_ie' => $empresaModel->getDocumentIe(),
                ':document_im' => $empresaModel->getDocumentIm(),
                ':regime_tributario' => $empresaModel->getRegimeTributario(),
                ':end_cep' => $empresaModel->getEndCep(),
                ':end_ibge' => $empresaModel->getEndIbge(),
                ':end_logradouro' => $empresaModel->getEndLogradouro(),
                ':end_numero' => $empresaModel->getEndNumero(),
                ':end_complemento' => $empresaModel->getEndComplemento(),
                ':end_bairro' => $empresaModel->getEndBairro(),
                ':end_cidade' => $empresaModel->getEndCidade(),
                ':end_uf' => $empresaModel->getEndUf(),
                ':updated_at' => $empresaModel->getUpdatedAt()->format('Y-m-d H:i:s'),
            ]
        );
    }

    public function delete(EmpresaModel $empresaModel): bool {
        $query =
        "UPDATE {$this->empresaTable} SET
            deleted_at = :deleted_at
        WHERE id = :id OR uuid = :uuid";

        $empresaModel->setDeletedAt(new DateTimeImmutable());

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

    public function findByIdentifier(string $identifier, mixed $value): ?EmpresaModel {
        $query =
        "SELECT
            id,
            uuid,
            is_active,
            nome_empresarial,
            nome_fantasia,
            tipo,
            matriz_id,
            document_cnpj,
            document_ie,
            document_im,
            regime_tributario,
            end_cep,
            end_ibge,
            end_logradouro,
            end_numero,
            end_complemento,
            end_bairro,
            end_cidade,
            end_uf,
            created_at,
            updated_at,
            deleted_at
        FROM {$this->empresaTable}
        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 findAllByMatrizId(int $matriz_id): array {
        $query =
        "SELECT
            id,
            uuid,
            is_active,
            nome_empresarial,
            nome_fantasia,
            tipo,
            matriz_id,
            document_cnpj,
            document_ie,
            document_im,
            regime_tributario,
            end_cep,
            end_ibge,
            end_logradouro,
            end_numero,
            end_complemento,
            end_bairro,
            end_cidade,
            end_uf,
            created_at,
            updated_at,
            deleted_at
        FROM {$this->empresaTable}
        WHERE (
            id = :matriz_id OR 
            matriz_id = :matriz_id
        )
        AND deleted_at IS NULL";

        $results = $this->db->fetchAll(
            sql: $query,
            params: [
                ':matriz_id' => $matriz_id
            ]
        );

        return array_map(fn($data) => $this->mapToModel($data), $results);
    }

    private function mapToModel(array $data): EmpresaModel {
        return new EmpresaModel(
            id: $data['id'],
            uuid: $data['uuid'],
            is_active: $data['is_active'],
            nome_empresarial: $data['nome_empresarial'],
            nome_fantasia: $data['nome_fantasia'],
            tipo: $data['tipo'],
            matriz_id: $data['matriz_id'],
            document_cnpj: $data['document_cnpj'],
            document_ie: $data['document_ie'],
            document_im: $data['document_im'],
            regime_tributario: $data['regime_tributario'],
            end_cep: $data['end_cep'],
            end_ibge: $data['end_ibge'],
            end_logradouro: $data['end_logradouro'],
            end_numero: $data['end_numero'],
            end_complemento: $data['end_complemento'],
            end_bairro: $data['end_bairro'],
            end_cidade: $data['end_cidade'],
            end_uf: $data['end_uf'],
            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,
        );
    }
}