from flask import request, jsonify, send_from_directory, render_template, request, redirect, url_for
from api.utils import util
from api.utils.bots import modulos as md, sefaz_arquivos as sf

from . import rota_
import models
import re
import time
import models
import threading
import queue
import os
from datetime import date

mes_vigente=util.FormatarData.formatar_data()
bot_ativo=False

#THREADS
class Workers:
    """
    Efetua a requisição do banco atraves de paralelismo
    """
    def __init__(self, cnpj, regime, cd, ie=None, im=None, modo='cnpj', valor=None, fila=None, coluna=None, id=None):
        self.cnpj, self.regime, self.ie, self.im, self.cd, self.modo, self.fila, self.coluna, self.id=(cnpj, regime, ie, im, cd, modo, fila, coluna, id)
        self.valor=valor if valor!=None else self.cnpj

    def create(self):
        time.sleep(10)
        models.SQLConn().parametro_create(lista=[self.cnpj, self.cd, self.regime, self.ie, self.im])

    def read(self):
        time.sleep(10)
        dados=models.SQLConn().parametro_readline(param=["cnpj",self.cnpj])
        self.fila.put(dados)
        return

    def update(self):
        print(f"coluna -> {self.coluna}")
        models.SQLConn().parametro_update(id=self.id, coluna=self.coluna, valor=self.valor)

    def delete(self):
        time.sleep(10)
        empresa=models.SQLConn().parametro_delete(param=[self.modo, self.valor])
        


@rota_.route("/principal", methods=["GET"])
def principal():
    if request.method=="GET":
        return render_template('base.html')

@rota_.route("/zip", methods=["POST"])
def main():
    """
        Retorna o arquivo zipado do mes informado
    """
    modelo=[]
    diretorio=os.path.join(os.path.expanduser("~"),"api/estrutura_api/api/utils/temp/arquivos_zipado")
    arquivos=arquivo=None
    try:
        if request.method=="POST":
            escopo=str(request.form.get('escopo'))
            print(f"Escopo atual -> {escopo}")
            match escopo:
                case "GLOBAL":
                    print(f"REQUESTE GLOBAL RETORNO -> {util.FormatarData.formatar_data()}")

                    modelo.append("nfe") if str(request.form.get('nfe'))=="on" else None
                    modelo.append("nfse") if str(request.form.get('nfse'))=="on" else None
                    modelo.append("guias") if str(request.form.get('guias'))=="on" else None
                    modelo.append("livros") if str(request.form.get('livro'))=="on" else None
                    modelo.append("notasT") if str(request.form.get('notas_t'))=="on" else None
                    modelo.append("relatorios") if str(request.form.get('relatorio'))=="on" else None

                    for a in range(len(modelo)):
                        if modelo[a]==None:
                            modelo.pop(a)
                    if len(modelo)>=1:
                        print(f"REQUESTE MODULO -> {modelo}")
                        zip_=util.ZiparArquivos
                        zip_=threading.Thread(target=zip_.zipar, args=(util.FormatarData.formatar_data(), modelo, "global", ))
                        zip_.start()
                        zip_.join()
                         
                case "LOCAL":
                    cnpj=re.sub(r"\D","",str(request.form.get("cnpj")))
                    try:
                        md.VerificarNT(cnpj, util.FormatarData.formatar_data())
                        time.sleep(1.5)
                        md.GerarRelatorio.gerar_arquivo(os.path.join(os.path.expanduser("~"),f".arquivos_api/{cnpj}/{mes_vigente}/2025/relatorios"))
                    except:
                        pass

                    modelo.append("nfe") if str(request.form.get('nfe'))=="on" else None
                    modelo.append("nfse") if str(request.form.get('nfse'))=="on" else None
                    modelo.append("guias") if str(request.form.get('guias'))=="on" else None
                    modelo.append("livros") if str(request.form.get('livro'))=="on" else None
                    modelo.append("notasT") if str(request.form.get('notas_t'))=="on" else None
                    modelo.append("relatorios") if str(request.form.get('relatorio'))=="on" else None
                    for a in range(len(modelo)):
                        if modelo[a]==None:
                            modelo.pop(a)
                    if len(modelo)>=1:
                        print(f"REQUESTE MODULO -> {modelo}")
                        zip_=util.ZiparArquivos
                        zip_=threading.Thread(target=zip_.zipar, args=(util.FormatarData.formatar_data(), modelo, "local", cnpj))
                        zip_.start()
                        zip_.join()
                    else:
                        return render_template('message.html', msg="NENHUM ARQUIVO INFORMADO")

                case "SINGULAR":
                    cnpj, pasta, chave=(request.form.get("cnpj"), [request.form.get("nfe"),request.form.get("nfse")], request.form.get("chave"))
                    f="nfe" if str(pasta[0])=="on" else "nfse"
                    f="nfse" if str(pasta[1])=="on" else "nfe"
                    if f=='nfe':
                        arquivos=os.path.join(os.path.expanduser("~"), f".arquivos_api/{cnpj}/{util.FormatarData.formatar_data()}/{date.today().year}/{f}/xml")
                    else:
                        arquivos=os.path.join(os.path.expanduser("~"), f".arquivos_api/{cnpj}/{util.FormatarData.formatar_data()}/{date.today().year}/{f}")
                    print(chave)
                    for file in os.listdir(arquivos):
                        print(f"{str(file)[-10:-4]} - {chave}")
                        if f=="nfe" and str(file)==f"xml_{chave}.xml":
                            arquivo=file
                        elif f=="nfse" and str(file)[-10:-4]==f"{chave}":
                            print(chave)
                            arquivo=file
    
    except Exception as e:
        return jsonify({"Erro":"404"})
    finally:
        if len(os.listdir(diretorio))>0 and arquivos==None:
            return send_from_directory(diretorio, os.listdir(diretorio)[0], as_attachment=True)
        elif arquivos!=None:
            print(arquivos, arquivo)
            return send_from_directory(arquivos, arquivo, as_attachment=True)
        else:
            return render_template("message.html", msg="Erro nenhum arquivo selecionado")

@rota_.route("/empresas")
def main_():
    try:
        empresas=[i for i in models.SQLConn().parametro_read()]
    except:
        return jsonify({"Erro ao retornar empresas":404})
    finally:
        return render_template("empresas.html", empresas=empresas)
         
@rota_.route("/empresa")
def main_0():
    try:
        id=request.args.get("id")
        
        empresa=models.SQLConn().parametro_readline(param=["id",id])
    except:
        return jsonify({"Erro ao retornar empresa":404})
    finally:
        if empresa:
            return render_template("empresa.html", empresa=empresa)
        else:
            return jsonify("Empresa nao consta no banco")
    
@rota_.route("/deletar")
def main_1():
    try:
        modo=request.args.get("mode")
        valor=request.args.get("id")
        print(f"ID: {valor} MODE: {modo}")
        empresa=models.SQLConn().parametro_readline(param=[f"{modo}", f"{valor}"])
        nome_emp=empresa['razao']
        time.sleep(5)
        empresa=Workers(empresa["cnpj"], empresa["modalidade"], empresa["codigo"], empresa["ie"], empresa["im"], modo, valor)
        time.sleep(1)
        tarefa=threading.Thread(target=empresa.delete)
        tarefa.start()
        tarefa.join()
    except:
        return jsonify({"Erro ao excluir empresa":404})
    finally:
        return render_template("message.html", msg=f"Empresa {nome_emp} excluida!")
    
@rota_.route("/adicionar", methods=["POST","GET"])
def main_2():
    
        if request.method=="GET":
            return render_template("criar_empresa.html")
        elif request.method=="POST":
            dados=None
            try:
                try:
                    ie=request.form.get("ie") if request.form.get("ie") else None
                    im=request.form.get("im") if request.form.get("im") else None
                except:
                    ie,im=(None,None)
                    pass
                
                print(f"""
                    CNPJ -> {request.form.get("cnpj")}
                    Código -> {request.form.get("codigo")}
                    IE -> {request.form.get("ie")}
                    IM -> {request.form.get("im")}
                    Modalidade -> {request.form.get("modalidade")}
    
                """)

                if request.form.get("modalidade")!=None and request.form.get("cnpj")!=None and request.form.get("codigo")!=None:
                    #rt -> regime tributario
                    cnpj=re.sub(r"\D","",str(request.form.get("cnpj")))
                    modalidade=request.form.get("modalidade")
                    codigo=request.form.get("codigo")
                    worker=Workers(cnpj, modalidade, codigo, ie, im)
                    tarefa=threading.Thread(target=worker.create)
                    tarefa.start()
                    tarefa.join()
                    time.sleep(2.5)

                else:
                    return jsonify(f"Os dados a seguir sao obrigatorio -> CNPJ ")
            except:
                return jsonify({"Erro":"empresa não cadastrada"})
            finally:
                dados=models.SQLConn().parametro_readline(param=["cnpj",f"{cnpj}"])
                print(f"Empresa -> {dados["razao"]}")
                time.sleep(0.5)
                return redirect(f'empresa?id={dados['id']}')
    
@rota_.route("/editar", methods=["POST"])
def main_3():
    if request.method=="POST":
        try:
            id=request.form.get("id")
            valores=[request.form.get("codigo"),request.form.get("razao"),request.form.get("nome_fantasia"),request.form.get("cnae"),
                            request.form.get("cep"), request.form.get("cidade"), request.form.get("uf"),request.form.get("bairro"),
                            request.form.get("logradouro"),request.form.get("complemento"),request.form.get("telefone"),request.form.get("email"),
                            request.form.get("modalidade"), request.form.get("ie"), request.form.get("im"),request.form.get("porte"), request.form.get("codigo_municipio")],
            colunas=["codigo", "razao", "nome_fantasia", "cnae", "cep", "cidade", "uf", "bairro", "logradouro", 
                    "complemento", "telefone", "email", "modalidade", "ie",
                    "im","porte","codigo_municipio"]
            empresa=models.SQLConn().parametro_readline(param=[f"id", f"{id}"])
            for i in range(len(colunas)):
                if str(valores[0][i]) != str(empresa[f"{colunas[i]}"]):
                    print(f"FORM -> {valores[0][i]} DB -> {empresa[f"{colunas[i]}"]}")
                    empresa_=Workers(cnpj=empresa["cnpj"], regime=empresa["modalidade"], cd=empresa["codigo"], ie=empresa["ie"], im=empresa["im"], valor=valores[0][i], coluna=colunas[i], id=id)
                    tarefa=threading.Thread(target=empresa_.update)
                    tarefa.start()
                    tarefa.join()                
                    time.sleep(2.5)
                else:
                    continue

                
        except:
            return jsonify({"Erro":f"ao tentar editar coluna"})
        finally:
            if empresa:
                return redirect(f"empresa?id={empresa['id']}")
            else:
                return render_template('message.html', msg="Erro ao editar empresa")

@rota_.route("/bots", methods=["GET","POST"])
def main_4():
    global bot_ativo
    if request.method=="GET":
        return render_template("bot_manager.html")
    
    elif request.method=="POST":
        try:
            bot=request.form.get("bot")
            match str(bot).lower():
                case 'start':
                    threading.Thread(target=util.parar_processo, args=("py.exe",)).start()
                    threading.Thread(target=util.parar_processo, args=("chrome.exe",)).start()
                    threading.Thread(target=util.parar_processo, args=("python.exe",)).start()
                    time.sleep(5)
                    threading.Thread(target=sf.RequesteInit.iniciar).start()
                    return jsonify({"Sucesso na execucao":200})
               
                case 'stop':
                    print("REQUESTE")
                    threading.Thread(target=util.parar_processo, args=("py.exe",)).start()
                    threading.Thread(target=util.ApiExec().finalizar).start()
                    cache_bot=threading.Thread(target=util.parar_processo, args=("python.exe",))
                    cache_bot.start()
                    cache_bot.join()

                    return jsonify({"Parando servidores":200})
        except Exception as e:
            return jsonify("Erro ao inicializar bot")
        finally:
            pass
        return

@rota_.route("/server")
def main_5():
    try:
        server=request.args.get("server")
        msg="None"
        match str(server):
            case "stop":
                threading.Thread(target=util.ApiExec().finalizar).start()
                msg="Finalizando"
            case "reset":
                threading.Thread(target=util.ApiExec().resetar).start()
                msg="Reiniciando"
    except Exception as e:
        jsonify({f"Error {e}":401})
    finally:
        return jsonify({f"{msg} servidor":200})

