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

use DateTimeImmutable;
use WorkbloomERP\Services\DBService;
use WorkbloomERP\Module\v0\Contato\Models\ContatoModel;

class ContatoRepo {
    protected string $contatoTable = 'contato';
    public function __construct(
        private DBService $db
    ) {}

    public function insert(ContatoModel $contatoModel): ContatoModel {
        $query =
        "INSERT INTO {$this->contatoTable} (
            uuid,
            empresa_id,
            is_active,
            tipo,
            nome_empresarial,
            nome_fantasia,
            personalidade,
            document_cpf,
            document_cnpj,
            regime_tributario,
            contribuinte_icms,
            orgao_publico,
            document_ie,
            document_im,
            document_is,
            end_pais,
            end_cep,
            end_ibge,
            end_logradouro,
            end_numero,
            end_complemento,
            end_bairro,
            end_cidade,
            end_uf,
            info_email,
            info_email_nfe,
            info_observacao,
            info_telefone,
            info_uso_consumo_ibs_cbs,
            created_at
        ) VALUES (
            :uuid,
            :empresa_id,
            :is_active,
            :tipo,
            :nome_empresarial,
            :nome_fantasia,
            :personalidade,
            :document_cpf,
            :document_cnpj,
            :regime_tributario,
            :contribuinte_icms,
            :orgao_publico,
            :document_ie,
            :document_im,
            :document_is,
            :end_pais,
            :end_cep,
            :end_ibge,
            :end_logradouro,
            :end_numero,
            :end_complemento,
            :end_bairro,
            :end_cidade,
            :end_uf,
            :info_email,
            :info_email_nfe,
            :info_observacao,
            :info_telefone,
            :info_uso_consumo_ibs_cbs,
            :created_at
        )";

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

        $this->db->execute(
            sql: $query,
            params: [
                ':uuid' => $contatoModel->getUuid(),
                ':empresa_id' => $contatoModel->getEmpresaId(),
                ':is_active' => $contatoModel->getIsActive(),
                ':tipo' => $contatoModel->getTipo(),
                ':nome_empresarial' => $contatoModel->getNomeEmpresarial(),
                ':nome_fantasia' => $contatoModel->getNomeFantasia(),
                ':personalidade' => $contatoModel->getPersonalidade(),
                ':document_cpf' => $contatoModel->getDocumentCpf(),
                ':document_cnpj' => $contatoModel->getDocumentCnpj(),
                ':regime_tributario' => $contatoModel->getRegimeTributario(),
                ':contribuinte_icms' => $contatoModel->getContribuinteIcms(),
                ':orgao_publico' => $contatoModel->getOrgaoPublico(),
                ':document_ie' => $contatoModel->getDocumentIe(),
                ':document_im' => $contatoModel->getDocumentIm(),
                ':document_is' => $contatoModel->getDocumentIs(),
                ':end_pais' => $contatoModel->getEndPais(),
                ':end_cep' => $contatoModel->getEndCep(),
                ':end_ibge' => $contatoModel->getEndIbge(),
                ':end_logradouro' => $contatoModel->getEndLogradouro(),
                ':end_numero' => $contatoModel->getEndNumero(),
                ':end_complemento' => $contatoModel->getEndComplemento(),
                ':end_bairro' => $contatoModel->getEndBairro(),
                ':end_cidade' => $contatoModel->getEndCidade(),
                ':end_uf' => $contatoModel->getEndUf(),
                ':info_email' => $contatoModel->getInfoEmail(),
                ':info_email_nfe' => $contatoModel->getInfoEmailNfe(),
                ':info_observacao' => $contatoModel->getInfoObservacao(),
                ':info_telefone' => $contatoModel->getInfoTelefone(),
                ':info_uso_consumo_ibs_cbs' => $contatoModel->getInfoUsoConsumoIbsCbs(),
                ':created_at' => $contatoModel->getCreatedAt()->format('Y-m-d H:i:s'),
            ]
        );

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

    public function update(ContatoModel $contatoModel): bool {
        $query =
        "UPDATE {$this->contatoTable} SET
            is_active = :is_active,
            tipo = :tipo,
            nome_empresarial = :nome_empresarial,
            nome_fantasia = :nome_fantasia,
            personalidade = :personalidade,
            document_cpf = :document_cpf,
            document_cnpj = :document_cnpj,
            regime_tributario = :regime_tributario,
            contribuinte_icms = :contribuinte_icms,
            orgao_publico = :orgao_publico,
            document_ie = :document_ie,
            document_im = :document_im,
            document_is = :document_is,
            end_pais = :end_pais,
            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,
            info_email = :info_email,
            info_email_nfe = :info_email_nfe,
            info_observacao = :info_observacao,
            info_telefone = :info_telefone,
            info_uso_consumo_ibs_cbs = :info_uso_consumo_ibs_cbs,
            updated_at = :updated_at
        WHERE id = :id OR uuid = :uuid";

        return $this->db->execute(
            sql: $query,
            params: [
                ':id' => $contatoModel->getId(),
                ':uuid' => $contatoModel->getUuid(),
                ':empresa_id' => $contatoModel->getEmpresaId(),
                ':is_active' => $contatoModel->getIsActive(),
                ':tipo' => $contatoModel->getTipo(),
                ':nome_empresarial' => $contatoModel->getNomeEmpresarial(),
                ':nome_fantasia' => $contatoModel->getNomeFantasia(),
                ':personalidade' => $contatoModel->getPersonalidade(),
                ':document_cpf' => $contatoModel->getDocumentCpf(),
                ':document_cnpj' => $contatoModel->getDocumentCnpj(),
                ':regime_tributario' => $contatoModel->getRegimeTributario(),
                ':contribuinte_icms' => $contatoModel->getContribuinteIcms(),
                ':orgao_publico' => $contatoModel->getOrgaoPublico(),
                ':document_ie' => $contatoModel->getDocumentIe(),
                ':document_im' => $contatoModel->getDocumentIm(),
                ':document_is' => $contatoModel->getDocumentIs(),
                ':end_pais' => $contatoModel->getEndPais(),
                ':end_cep' => $contatoModel->getEndCep(),
                ':end_ibge' => $contatoModel->getEndIbge(),
                ':end_logradouro' => $contatoModel->getEndLogradouro(),
                ':end_numero' => $contatoModel->getEndNumero(),
                ':end_complemento' => $contatoModel->getEndComplemento(),
                ':end_bairro' => $contatoModel->getEndBairro(),
                ':end_cidade' => $contatoModel->getEndCidade(),
                ':end_uf' => $contatoModel->getEndUf(),
                ':info_email' => $contatoModel->getInfoEmail(),
                ':info_email_nfe' => $contatoModel->getInfoEmailNfe(),
                ':info_observacao' => $contatoModel->getInfoObservacao(),
                ':info_telefone' => $contatoModel->getInfoTelefone(),
                ':info_uso_consumo_ibs_cbs' => $contatoModel->getInfoUsoConsumoIbsCbs(),
                ':updated_at' => $contatoModel->getUpdatedAt()->format('Y-m-d H:i:s'),
            ]
        );
    }

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

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

    public function findByIdentifier(int $empresa_id, string $identifier, mixed $value) {
        $query =
        "SELECT
            id,
            uuid,
            empresa_id,
            is_active,
            nome_empresarial,
            nome_fantasia,
            personalidade,
            document_cpf,
            document_cnpj,
            regime_tributario,
            contribuinte_icms,
            orgao_publico,
            document_ie,
            document_im,
            document_is,
            end_cep,
            end_ibge,
            end_logradouro,
            end_numero,
            end_complemento,
            end_bairro,
            end_cidade,
            end_uf,
            info_email,
            info_email_nfe,
            info_observacao,
            info_telefone,
            info_uso_consumo_ibs_cbs,
            created_at,
            updated_at,
            deleted_at
        FROM {$this->contatoTable}
        WHERE empresa_id = :empresa_id
        AND {$identifier} = :value
        AND deleted_at IS NULL
        LIMIT 1";

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

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

    public function findOneByConditions(int $empresa_id, array $conditions): ?ContatoModel {
        if (empty($conditions)) {
            throw new \InvalidArgumentException('O array de condições não pode estar vazio.');
        }

        // Começa com as condições fixas
        $whereClauses = [
            'empresa_id = :empresa_id',
            'deleted_at IS NULL'
        ];

        $params = [
            ':empresa_id' => $empresa_id
        ];

        // Adiciona as condições dinâmicas
        foreach ($conditions as $condition) {
            if (!isset($condition['field'], $condition['value'])) {
                throw new \InvalidArgumentException(
                    "Cada condição deve conter 'field' e 'value'."
                );
            }

            $field = $condition['field'];
            $operator = $condition['operator'] ?? '=';
            $value = $condition['value'];

            $whereClauses[] = "{$field} {$operator} :{$field}";
            $params[":{$field}"] = $value;
        }

        $whereSql = implode(' AND ', $whereClauses);

        $query = 
        "SELECT
            id,
            uuid,
            empresa_id,
            is_active,
            tipo,
            nome_empresarial,
            nome_fantasia,
            personalidade,
            document_cpf,
            document_cnpj,
            regime_tributario,
            contribuinte_icms,
            orgao_publico,
            document_ie,
            document_im,
            document_is,
            end_pais,
            end_cep,
            end_ibge,
            end_logradouro,
            end_numero,
            end_complemento,
            end_bairro,
            end_cidade,
            end_uf,
            info_email,
            info_email_nfe,
            info_observacao,
            info_telefone,
            info_uso_consumo_ibs_cbs,
            created_at,
            updated_at,
            deleted_at
        FROM {$this->contatoTable}
        WHERE {$whereSql}
        LIMIT 1";

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

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

    private function mapToModel(array $data): ContatoModel {
        return new ContatoModel(
            id: $data['id'],
            uuid: $data['uuid'],
            empresa_id: $data['empresa_id'],
            is_active: $data['is_active'],
            tipo: $data['tipo'],
            nome_empresarial: $data['nome_empresarial'],
            nome_fantasia: $data['nome_fantasia'],
            personalidade: $data['personalidade'],
            document_cpf: $data['document_cpf'],
            document_cnpj: $data['document_cnpj'],
            regime_tributario: $data['regime_tributario'],
            contribuinte_icms: $data['contribuinte_icms'],
            orgao_publico: $data['orgao_publico'],
            document_ie: $data['document_ie'],
            document_im: $data['document_im'],
            document_is: $data['document_is'],
            end_pais: $data['end_pais'],
            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'],
            info_email: $data['info_email'],
            info_email_nfe: $data['info_email_nfe'],
            info_observacao: $data['info_observacao'],
            info_telefone: $data['info_telefone'],
            info_uso_consumo_ibs_cbs: $data['info_uso_consumo_ibs_cbs'],
            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,
        );
    }
}