#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Script para gerenciar variáveis do Web.config do MicroUniverso
Salva e restaura as configurações: tamanhoPagina e tempoExpiracaoSessoesAplicativoSemConexoes
"""

import os
import sys
import json
import re
import xml.etree.ElementTree as ET
from datetime import datetime
from pathlib import Path
from lib.obter_configuracoes import obter_configuracoes
from lib.echo import echo


if len(sys.argv) < 2:
    echo("arquivo de configuração não informado.")
    exit(0)
    
arquivo_configuracao =  sys.argv[1]

if len(sys.argv) < 3:
    echo("nome do serviço não informado.")
    exit(0)

nomeServico = sys.argv[2]

if(nomeServico  in [ "fenixWrapper"]):
    echo("Serviço "+ nomeServico + " não utiliza Web.config. backup do arquivo pulado.")
    exit(0)

if len(sys.argv) < 4:
    echo("Escolha uma opção: salvar, restaurar, visualizar_backup, visualizar_atual.")
    exit(0)
opcao = sys.argv[3].lower()

configuracoes = obter_configuracoes(arquivo_configuracao)

diretorioBaseInstalacao = configuracoes["enderecos"]["diretorioBaseInstalacao"]
diretorioAppReleaseWeb = configuracoes["servicos"][nomeServico]["diretorioRelativoInstalacao"]
webconfig_path = os.path.join(diretorioBaseInstalacao, diretorioAppReleaseWeb, "Web.config")
backup_dir = os.path.join(diretorioBaseInstalacao, diretorioAppReleaseWeb)
backup_file = os.path.join(backup_dir, "config_backup.json")
variaveis = {
            "tamanhoPagina": {"section": "fenixConfig", "default": "20"},
            "tempoExpiracaoSessoesAplicativoSemConexoes": {"section": "microAuth", "default": "240"},
            "larguraColunaDescricao": {"section": "appSettings"},
        } 





def verificar_arquivo():
    """Verifica se o arquivo Web.config existe"""
    if not os.path.exists(webconfig_path):
        print(f" ERRO: Arquivo não encontrado: {webconfig_path}")
        return False
    print(f" Arquivo encontrado: {webconfig_path}")
    return True

def salvar_configuracoes():
    """Salva as configurações atuais em um arquivo JSON"""
    if not verificar_arquivo():
        return False
    
    try:
        # Parse do XML
        tree = ET.parse(webconfig_path)
        root = tree.getroot()
        
        # Dicionário para armazenar os valores
        config_atual = {
            "data_backup": datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
            "valores": {}
        }
        
        # Buscar cada variável nas suas respectivas seções
        for var_name, var_info in variaveis.items():
            section_name = var_info["section"]
            
            # Encontrar a seção
            section = root.find(section_name)
            if section is not None:
                # Buscar a chave específica
                for add_element in section.findall("add"):
                    if add_element.get("key") == var_name:
                        valor = add_element.get("value")
                        config_atual["valores"][var_name] = valor
                        print(f"   {var_name} = {valor}")
                        break
            else:
                print(f"   Seção '{section_name}' não encontrada")
        
        # Salvar em JSON
        os.makedirs(backup_dir, exist_ok=True)
        with open(backup_file, 'w', encoding='utf-8') as f:
            json.dump(config_atual, f, indent=2, ensure_ascii=False)
        
        print(f"\n Configurações salvas em: {backup_file}")
        print(f"  Data do backup: {config_atual['data_backup']}")
        return True
        
    except ET.ParseError as e:
        print(f" ERRO ao processar XML: {e}")
        return False
    except Exception as e:
        print(f" ERRO: {e}")
        return False

def restaurar_configuracoes():
    """Restaura as configurações salvas no Web.config"""
    if not verificar_arquivo():
        return False
    
    if not os.path.exists(backup_file):
        print(f" ERRO: Arquivo de backup não encontrado: {backup_file}")
        print("   Execute primeiro a opção 'salvar' para criar um backup.")
        return False
    
    try:
        # Ler o backup
        with open(backup_file, 'r', encoding='utf-8') as f:
            config_backup = json.load(f)
        
        print(f" Usando backup de: {config_backup['data_backup']}")
        
        # Criar backup do arquivo atual antes de modificar
        backup_timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
        webconfig_backup = f"{webconfig_path}.backup_{backup_timestamp}"
        
        import shutil
        shutil.copy2(webconfig_path, webconfig_backup)
        print(f" Backup de segurança criado: {webconfig_backup}")
        
        # Ler o arquivo como texto
        with open(webconfig_path, 'r', encoding='utf-8') as f:
            conteudo = f.read()
        
        # Parse temporário apenas para ler valores atuais
        tree = ET.parse(webconfig_path)
        root = tree.getroot()
        
        modificado = False
        
        # Restaurar cada variável usando substituição de texto
        for var_name, valor_salvo in config_backup["valores"].items():
            if var_name in variaveis:
                section_name = variaveis[var_name]["section"]
                
                # Buscar valor atual
                section = root.find(section_name)
                valor_atual = None
                
                if section is not None:
                    for add_element in section.findall("add"):
                        if add_element.get("key") == var_name:
                            valor_atual = add_element.get("value")
                            break
                
                if valor_atual is not None:
                    if valor_atual != valor_salvo:
                        # Padrões para encontrar e substituir o valor
                        # Padrão 1: key antes de value com aspas duplas
                        pattern1 = rf'(<add\s+key="{re.escape(var_name)}"[^>]*?\s+value=")([^"]*)(")'
                        # Padrão 2: value antes de key com aspas duplas
                        pattern2 = rf'(<add\s+value=")([^"]*)("[^>]*?\s+key="{re.escape(var_name)}")'
                        # Padrão 3: key antes de value com aspas simples
                        pattern3 = rf"(<add\s+key='{re.escape(var_name)}'[^>]*?\s+value=')([^']*)(')"
                        # Padrão 4: value antes de key com aspas simples
                        pattern4 = rf"(<add\s+value=')([^']*)('[^>]*?\s+key='{re.escape(var_name)}')"
                        
                        substituido = False
                        
                        if re.search(pattern1, conteudo):
                            conteudo = re.sub(pattern1, rf'\g<1>{valor_salvo}\g<3>', conteudo)
                            substituido = True
                        elif re.search(pattern2, conteudo):
                            conteudo = re.sub(pattern2, rf'\g<1>{valor_salvo}\g<3>', conteudo)
                            substituido = True
                        elif re.search(pattern3, conteudo):
                            conteudo = re.sub(pattern3, rf'\g<1>{valor_salvo}\g<3>', conteudo)
                            substituido = True
                        elif re.search(pattern4, conteudo):
                            conteudo = re.sub(pattern4, rf'\g<1>{valor_salvo}\g<3>', conteudo)
                            substituido = True
                        
                        if substituido:
                            print(f"   {var_name}: {valor_atual} -> {valor_salvo}")
                            modificado = True
                        else:
                            print(f" ! Não foi possível substituir {var_name}")
                    else:
                        print(f"  = {var_name}: {valor_atual} (sem alteração)")
        
        if modificado:
            # Salvar o arquivo modificado preservando a formatação
            with open(webconfig_path, 'w', encoding='utf-8') as f:
                f.write(conteudo)
            print(f"\n Configurações restauradas com sucesso!")
        else:
            print(f"\n Nenhuma alteração necessária - valores já estão corretos")
        
        return True
        
    except json.JSONDecodeError as e:
        print(f" ERRO ao ler backup JSON: {e}")
        return False
    except ET.ParseError as e:
        print(f" ERRO ao processar XML: {e}")
        return False
    except Exception as e:
        print(f" ERRO: {e}")
        return False

def visualizar_backup():
    """Exibe o conteúdo do arquivo de backup"""
    if not os.path.exists(backup_file):
        print(f" Arquivo de backup não encontrado: {backup_file}")
        return False
    
    try:
        with open(backup_file, 'r', encoding='utf-8') as f:
            config_backup = json.load(f)
        
       
        print(f"Data do backup: {config_backup['data_backup']}")
        print("\nVariáveis:")
        for var_name, valor in config_backup["valores"].items():
            print(f" {var_name} = {valor}")
        print("="*60)
        return True
        
    except Exception as e:
        print(f" ERRO ao visualizar backup: {e}")
        return False

def visualizar_atual():
    """Exibe as configurações atuais do Web.config"""
    if not verificar_arquivo():
        return False
    
    try:
        tree = ET.parse(webconfig_path)
        root = tree.getroot()
        
        for var_name, var_info in variaveis.items():
            section_name = var_info["section"]
            section = root.find(section_name)
            
            if section is not None:
                for add_element in section.findall("add"):
                    if add_element.get("key") == var_name:
                        valor = add_element.get("value")
                        print(f"  • {var_name} = {valor}")
                        break
        
        print("="*60)
        return True
        
    except Exception as e:
        print(f"ERRO ao ler configurações atuais: {e}")
        return False


def menu_principal():
    """Exibe o menu principal e processa as opções"""
    
    if opcao == "salvar":
        print("\nSalvando configurações...")
        salvar_configuracoes()
    
    elif opcao == "restaurar":
        restaurar_configuracoes()
      
    elif opcao == "visualizar_backup":
        visualizar_backup()

    elif opcao == "visualizar_atual":
        visualizar_atual()
    
    else:
        print("\n Opção inválida!")
        
    
if __name__ == "__main__":
    try:
        menu_principal()
        exit(0)
    except Exception as e:
        exit(0)
