# utils.py import pandas as pd import re import os import requests import matplotlib.font_manager as fm from pydantic import BaseModel, Field, ConfigDict from typing import List, Tuple, Optional from fpdf import FPDF from datetime import datetime # --- MODELOS PYDANTIC --- class Historico(BaseModel): entradas: List[Tuple[str, str]] = [] def adicionar(self, pergunta: str, resposta: str): if pergunta and resposta: self.entradas.append((pergunta, resposta)) # --- FUNÇÕES DE PROCESSAMENTO DE TEXTO E DADOS --- def descricao_colunas(df: pd.DataFrame) -> str: descricao = "\n".join([f"`{col}`: {str(df[col].dtype)}" for col in df.columns]) return "Colunas do DataFrame:\n" + descricao def limpar_codigo_pandas(codigo: str) -> str: codigo = re.sub(r'```(?:python)?\n?', '', codigo) codigo = re.sub(r'```', '', codigo) linhas = [linha.strip() for linha in codigo.split('\n') if linha.strip()] codigo_filtrado = [l for l in linhas if not (l.startswith('#') or 'resposta:' in l.lower())] return codigo_filtrado[-1] if codigo_filtrado else "" # --- LÓGICA DE PREPARAÇÃO DE FONTES --- FONT_PATH = "" def setup_font(): global FONT_PATH FONT_NAME_TO_FIND = "DejaVu Sans" try: FONT_PATH = fm.findfont(FONT_NAME_TO_FIND, fallback_to_default=True) if not os.path.exists(FONT_PATH): raise FileNotFoundError print(f"✅ Fonte encontrada localmente: {FONT_PATH}") except Exception: print(f"⚠️ Fonte '{FONT_NAME_TO_FIND}' não encontrada. Baixando alternativa (Roboto)...") FONT_FILE_NAME = "Roboto-Regular.ttf" FONT_URL = "https://github.com/google/fonts/raw/main/ofl/roboto/Roboto-Regular.ttf" if not os.path.exists(FONT_FILE_NAME): try: response = requests.get(FONT_URL) response.raise_for_status() with open(FONT_FILE_NAME, "wb") as f: f.write(response.content) FONT_PATH = FONT_FILE_NAME print(f"✅ Fonte alternativa baixada!") except Exception as e: print(f"❌ FALHA CRÍTICA ao baixar fonte: {e}") FONT_PATH = "" else: FONT_PATH = FONT_FILE_NAME print(f"✅ Fonte alternativa já existe.") return FONT_PATH # --- GERAÇÃO DE PDF --- def gerar_pdf_report(historico: Historico, font_path: str): if not historico or not historico.entradas: print("⚠️ Tentativa de gerar PDF com histórico vazio.") return None if not font_path or not os.path.exists(font_path): print(f"❌ Erro ao gerar PDF: Arquivo da fonte não encontrado em '{font_path}'.") return None try: timestamp = datetime.now().strftime("%Y%m%d_%H%M%S") caminho_pdf = f"relatorio_consultas_{timestamp}.pdf" pdf = FPDF() pdf.add_page() pdf.add_font('CustomFont', '', font_path, uni=True) pdf.set_font('CustomFont', '', 16) pdf.cell(0, 10, "Relatório de Consultas ao CSV", ln=True, align="C") pdf.ln(10) for i, (pergunta, resposta) in enumerate(historico.entradas, 1): pdf.set_font('CustomFont', '', 12) pdf.multi_cell(0, 8, f"Pergunta {i}: {pergunta}") pdf.ln(2) pdf.set_font('CustomFont', '', 10) pdf.multi_cell(0, 6, f"Resposta: {resposta}") pdf.ln(8) pdf.cell(0, 0, '', 'T'); pdf.ln(8) pdf.output(caminho_pdf) print(f"✅ PDF gerado: {caminho_pdf}") return caminho_pdf except Exception as e: print(f"❌ Erro crítico ao gerar PDF: {e}") return None