import sys
import sqlite3
import random
import os
import math
import threading
import subprocess
import pygame
import socket
import numpy as np
from PyQt6.QtWidgets import QApplication, QMainWindow, QWidget, QVBoxLayout, QHBoxLayout, QLabel, QFrame, QPushButton, QMessageBox
from PyQt6.QtCore import Qt, QTimer, QPoint
from PyQt6.QtGui import QPainter, QColor, QFont, QPixmap, QLinearGradient
from PyQt6.QtMultimedia import QAudioFormat, QAudioSink

# Inicializar audio para la voz de los salmos
pygame.mixer.init()

# CONFIGURACIÓN DE RUTAS SAGRADAS
RUTA_PIPER = "/usr/local/bin/piper"
RUTA_MODELO_VOZ = "/home/obispo/Crisostomo_bridge/es_ES-dave-medium.onnx"
FRECUENCIA_SCHUMANN = 7.83

def mantener_vigilia():
    try:
        os.system("xset s off")
        os.system("xset -dpms")
        os.system("xset s noblank")
    except: pass

class LlamaSagrada(QWidget):
    def __init__(self, color_base, parent=None):
        super().__init__(parent)
        self.setMinimumSize(100, 120)
        self.color_base = color_base 
        self.particulas = []
        self.timer = QTimer(self)
        self.timer.timeout.connect(self.animar)
        self.timer.start(40)

    def animar(self):
        if len(self.particulas) < 40:
            self.particulas.append({'x': 50, 'y': 100, 'r': random.randint(8, 18), 'life': 1.0})
        for p in self.particulas[:]:
            p['y'] -= random.randint(2, 5)
            p['x'] += random.uniform(-2, 2)
            p['life'] -= 0.04
            if p['life'] <= 0: self.particulas.remove(p)
        self.update()

    def paintEvent(self, event):
        painter = QPainter(self)
        painter.setRenderHint(QPainter.RenderHint.Antialiasing)
        for p in self.particulas:
            alpha = int(p['life'] * 255)
            c = QColor(self.color_base.red(), self.color_base.green(), self.color_base.blue(), alpha)
            painter.setBrush(c)
            painter.setPen(Qt.PenStyle.NoPen)
            painter.drawEllipse(QPoint(int(p['x']), int(p['y'])), int(p['r'] * p['life']), int(p['r'] * p['life']))

class AltarDigital(QMainWindow):
    def __init__(self):
        super().__init__()
        mantener_vigilia()
        self.setWindowTitle("CRISÓSTOMO: Cáliz de Silicio + Acumulador Orgónico + Pulso Schumann")
        self.setFixedSize(1400, 950)
        
        self.color_actual = QColor(138, 43, 226)
        self.color_objetivo = QColor(138, 43, 226)
        self.intencion_actual = "Paz y Protección"
        self.verbo_actual = "..."
        self.testigo_binario = b""
        self.energia_orgon = 0.5 
        
        self.indice_familia = 0
        self.indice_heka = 0
        self.indice_simbolo = 0
        self.frecuencia_solfeggio = 528

        self.preparar_audio_528()

        self.main_widget = QWidget()
        self.setCentralWidget(self.main_widget)
        self.layout_total = QVBoxLayout(self.main_widget)

        self.layout_visiones = QHBoxLayout()
        self.ui_familia = self.crear_panel("🛡️ CÍRCULO FAMILIAR", QColor(138, 43, 226))
        self.ui_simbolo = self.crear_panel_central("⚜️ SÍMBOLO SAGRADO", QColor(255, 215, 0))
        self.ui_heka = self.crear_panel("✨ OPERACIONES HEKA", QColor(0, 191, 255))

        self.layout_visiones.addWidget(self.ui_familia['frame'])
        self.layout_visiones.addWidget(self.ui_simbolo['frame'])
        self.layout_visiones.addWidget(self.ui_heka['frame'])

        self.layout_total.addLayout(self.layout_visiones)
        self.crear_zocalo()

        self.lbl_transmision = QLabel("transmitiendo luz | Orgón: Activo", self)
        self.lbl_transmision.setFont(QFont("Verdana", 8, QFont.Weight.Bold))
        self.lbl_transmision.setStyleSheet("color: rgba(255, 215, 0, 150); background: transparent;")
        self.lbl_transmision.move(1150, 920)

        # TIMERS
        self.timer_db = QTimer()
        self.timer_db.timeout.connect(self.actualizar_altar)
        self.timer_db.start(60000) 
        
        self.timer_color = QTimer()
        self.timer_color.timeout.connect(self.gestionar_transicion)
        self.timer_color.start(50)

        # HILOS DE TRANSMISIÓN Y ACUMULACIÓN
        threading.Thread(target=self.bucle_emision_red_schumann, daemon=True).start()
        threading.Thread(target=self.acumulador_orgonico, daemon=True).start()

        # DISPARO INICIAL
        QTimer.singleShot(500, self.actualizar_altar)

    # Resto de métodos se mantienen iguales (se han corregido espacios invisibles)
    def mostrar_ayuda(self):
        msg = QMessageBox(self)
        msg.setWindowTitle("Manual del Altar")
        msg.setText("<h3>Cáliz de Silicio v2.6</h3>")
        info = ("<b>Liturgia:</b> Los salmos rotan cada minuto.<br>"
                "<b>Orgón:</b> Captando el ruido de red para armonizar el hogar.")
        msg.setInformativeText(info)
        msg.setStyleSheet("background-color: #080808; color: white;")
        msg.exec()

    def acumulador_orgonico(self):
        sock_escucha = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        sock_escucha.bind(('', 0))
        while True:
            try:
                sock_escucha.settimeout(1.0)
                data, _ = sock_escucha.recvfrom(1024)
                self.energia_orgon = (sum(data) % 100) / 100.0
            except:
                self.energia_orgon = random.uniform(0.4, 0.6)
            pygame.time.wait(500)

    def paintEvent(self, event):
        painter = QPainter(self)
        osc_fondo = (math.sin(pygame.time.get_ticks() * 0.001) + 1) / 2
        factor = int(200 + (50 * self.energia_orgon) + (30 * osc_fondo))
        gradient = QLinearGradient(0, 0, self.width(), self.height())
        gradient.setColorAt(0, self.color_actual.darker(factor + 200))
        gradient.setColorAt(0.5, self.color_actual.darker(factor))
        gradient.setColorAt(1, self.color_actual.darker(factor + 200))
        painter.fillRect(self.rect(), gradient)

    def gestionar_transicion(self):
        def interp(a, b): return a + 1 if a < b else (a - 1 if a > b else a)
        r, g, b = interp(self.color_actual.red(), self.color_objetivo.red()), \
                  interp(self.color_actual.green(), self.color_objetivo.green()), \
                  interp(self.color_actual.blue(), self.color_objetivo.blue())
        self.color_actual = QColor(r, g, b)
        
        pulso_s = (math.sin(pygame.time.get_ticks() * 0.00783 * 2 * math.pi) + 1) / 2
        opacidad = int(150 + (105 * pulso_s))
        color_pulso = f"rgba(255, 215, 0, {opacidad})"
        
        estilo_base = f"border: 2px solid {self.color_actual.name()}; border-radius: 15px; background: rgba(5, 5, 5, 220);"
        self.ui_familia['frame'].setStyleSheet(estilo_base)
        self.ui_heka['frame'].setStyleSheet(estilo_base)
        self.ui_simbolo['frame'].setStyleSheet(f"border: 4px double {color_pulso}; border-radius: 20px; background: rgba(8, 8, 8, 240);")
        self.update()

    def bucle_emision_red_schumann(self):
        sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        sock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
        while True:
            try:
                fragmento = self.testigo_binario[:512]
                paquete = f"SCHUMANN|ORGON:{self.energia_orgon:.2f}|VERBO:{self.verbo_actual[:50]}".encode('utf-8') + b"|DATA:" + fragmento
                sock.sendto(paquete, ('255.255.255.255', 9999))
                pygame.time.wait(127) 
            except: pass

    def preparar_audio_528(self):
        format = QAudioFormat()
        format.setSampleRate(44100); format.setChannelCount(1); format.setSampleFormat(QAudioFormat.SampleFormat.Int16)
        self.audio_output = QAudioSink(format)
        self.dispositivo_audio = self.audio_output.start()
        self.fase = 0
        self.timer_audio = QTimer()
        self.timer_audio.timeout.connect(self.generar_onda)
        self.timer_audio.start(20)

    def generar_onda(self):
        sampling_rate = 44100; amplitude = 1000; num_samples = 882; data = bytearray()
        for _ in range(num_samples):
            val = int(amplitude * math.sin(2 * math.pi * self.frecuencia_solfeggio * self.fase / sampling_rate))
            data.extend(val.to_bytes(2, byteorder='little', signed=True)); self.fase += 1
        self.dispositivo_audio.write(data)

    def recitar_verbo(self, fonetica):
        def ejecutar_piper():
            path_tmp = "/tmp/salmo.wav"
            try:
                cmd = f"echo \"{fonetica}\" | {RUTA_PIPER} --model {RUTA_MODELO_VOZ} --output_file {path_tmp}"
                subprocess.run(cmd, shell=True, check=True)
                pygame.mixer.music.load(path_tmp)
                pygame.mixer.music.play()
            except: pass
        threading.Thread(target=ejecutar_piper, daemon=True).start()

    def crear_panel(self, titulo, color):
        frame = QFrame()
        layout = QVBoxLayout(frame)
        lbl_titulo = QLabel(titulo); lbl_titulo.setFont(QFont("Cinzel", 14, QFont.Weight.Bold)); lbl_titulo.setAlignment(Qt.AlignmentFlag.AlignCenter); lbl_titulo.setStyleSheet(f"color: {color.name()}; border: none;")
        foto = QLabel(); foto.setFixedSize(320, 320); foto.setAlignment(Qt.AlignmentFlag.AlignCenter); foto.setStyleSheet("border: 1px solid rgba(255,255,255,10);")
        info = QLabel("..."); info.setFont(QFont("Verdana", 10, QFont.Weight.Bold)); info.setAlignment(Qt.AlignmentFlag.AlignCenter); info.setStyleSheet("color: gold; border: none;")
        llama = LlamaSagrada(color)
        layout.addWidget(lbl_titulo); layout.addWidget(foto, alignment=Qt.AlignmentFlag.AlignCenter); layout.addWidget(info); layout.addWidget(llama, alignment=Qt.AlignmentFlag.AlignCenter)
        return {'frame': frame, 'foto': foto, 'info': info, 'llama': llama}

    def crear_panel_central(self, titulo, color):
        frame = QFrame()
        layout = QVBoxLayout(frame)
        lbl_titulo = QLabel(titulo); lbl_titulo.setFont(QFont("Cinzel", 16, QFont.Weight.Bold)); lbl_titulo.setAlignment(Qt.AlignmentFlag.AlignCenter); lbl_titulo.setStyleSheet(f"color: {color.name()}; border: none;")
        foto = QLabel(); foto.setFixedSize(380, 380); foto.setAlignment(Qt.AlignmentFlag.AlignCenter)
        self.lbl_desc_simbolo = QLabel(""); self.lbl_desc_simbolo.setFont(QFont("Garamond", 12, QFont.Weight.Bold)); self.lbl_desc_simbolo.setAlignment(Qt.AlignmentFlag.AlignCenter); self.lbl_desc_simbolo.setWordWrap(True); self.lbl_desc_simbolo.setStyleSheet("color: #FFD700; border: none; padding: 10px;")
        layout.addWidget(lbl_titulo); layout.addWidget(foto, alignment=Qt.AlignmentFlag.AlignCenter); layout.addWidget(self.lbl_desc_simbolo)
        return {'frame': frame, 'foto': foto}

    def crear_zocalo(self):
        zocalo = QFrame(); zocalo.setFixedHeight(320); zocalo.setStyleSheet("background: rgba(10, 10, 10, 240); border-top: 2px solid #FFD700;")
        layout = QVBoxLayout(zocalo)
        self.lbl_titulo_salmo = QLabel("INICIANDO LITURGIA..."); self.lbl_titulo_salmo.setFont(QFont("Cinzel", 15, QFont.Weight.Bold)); self.lbl_titulo_salmo.setAlignment(Qt.AlignmentFlag.AlignCenter); self.lbl_titulo_salmo.setStyleSheet("color: gold; border: none; margin-top: 10px;")
        self.lbl_salmo = QLabel("..."); self.lbl_salmo.setFont(QFont("SBL Hebrew", 16)); self.lbl_salmo.setAlignment(Qt.AlignmentFlag.AlignCenter); self.lbl_salmo.setWordWrap(True); self.lbl_salmo.setStyleSheet("color: white; border: none; padding: 15px;")
        layout.addWidget(self.lbl_titulo_salmo); layout.addWidget(self.lbl_salmo)
        self.layout_total.addWidget(zocalo)

    def actualizar_altar(self):
        try:
            conn = sqlite3.connect('crisostomo.db'); cur = conn.cursor()
            self.color_objetivo = random.choice([QColor(138,43,226), QColor(0,100,255), QColor(255,215,0)])

            # 1. Rotación Familiar
            cur.execute("SELECT nombre, foto FROM familia"); rows_fam = cur.fetchall()
            if rows_fam:
                r = rows_fam[self.indice_familia % len(rows_fam)]
                self.mostrar_imagen(self.ui_familia, r[1], f"BAJO PROTECCIÓN: {r[0]}", 320)
                if os.path.exists(r[1]):
                    with open(r[1], "rb") as f: self.testigo_binario = f.read()
                self.indice_familia += 1

            # 2. Rotación de Símbolos Sagrados (Centro)
            cur.execute("SELECT nombre, descripcion, foto FROM simbolos"); rows_sim = cur.fetchall()
            if rows_sim:
                s = rows_sim[self.indice_simbolo % len(rows_sim)]
                self.mostrar_imagen(self.ui_simbolo, s[2], "", 380)
                self.lbl_desc_simbolo.setText(f"{s[0]}\n{s[1]}")
                self.indice_simbolo += 1

            # 3. Rotación HEKA (Panel Derecho)
            cur.execute("SELECT peticion, foto FROM heka"); rows_heka = cur.fetchall()
            if rows_heka:
                h = rows_heka[self.indice_heka % len(rows_heka)]
                self.mostrar_imagen(self.ui_heka, h[1], f"OPERACIÓN HEKA: {h[0]}", 320)
                self.indice_heka += 1

            # 4. LITURGIA (REVISADA Y COMPLETA)
            liturgia = [
                {
                    "titulo": "ANA BECOAJ (Las 42 Letras - Completo)",
                    "texto": "אָנָּא בְּכֹחַ גְּדֻלַּת יְמִינְךָ תַּתִּיר צְרוּרָה: קַבֵּל רִנַּת עַמְּךָ שַׂגְּבֵנוּ טַהֲרֵנוּ נוֹרָא: נָא גִבּוֹר דּוֹרְשֵׁי יִחוּדְךָ כְּבָבַת שָׁמְרֵם: בָּרְכֵם טַהֲרֵם רַחֲמֵי צִדְקָתְךָ תָּמִיד גָּמְלֵם: חֲסִין קָדוֹשׁ בְּרוֹב טוּבְךָ נַהֵל עֲדָתֶךָ: יָחִיד גֵּאָה לְעַמְּךָ פְּנֵה זוֹכְרֵי קְדֻשָּׁתֶךָ: שַׁוְעָתֵנוּ קַבֵּל וּשְׁמַע צַעֲקָתֵנוּ יוֹדֵעַ תַּעֲלוּמוֹת. (בָּרוּךְ שֵׁם כְּבוֹד מַלְכוּתוֹ לְעוֹלָם וָעֶד)",
                    "fonetica": "Aná becóaj, guedulát yemínja, tatír tserurá. Kabél rinát amjá saguivénu, taharénu norá. Na guibór dorshéi yijudjá, kebabát shamrém. Barjém taharém, rajaméi tsidkatjá, tamíd gamlém. Jasín kadósh, beróv tuvjá, nahél adatéja. Yajíd gueá leamjá, pnéi zojréi kedushatéja. Shavaténu kabél ushmá tsaakaténu, yodéa taalumót. Barúj shem kevód maljutó leolám vaéd."
                },
                {
                    "titulo": "SHIR LAMAALOT (Salmo 121 - Completo)",
                    "texto": "אֶשָּׂא עֵינַי אֶל הֶהָרִים מֵאַיִן יָבֹא עֶזְרִי: עֶזְרִי מֵעִם יְהוָה עֹשֵׂה שָׁמַיִם וָאָרֶץ: אַל יִתֵּן לַמּוֹט רַגְלֶךָ אַל יָנוּם שֹׁמְרֶךָ: הִנֵּה לֹא יָנוּם וְלֹא יִישָׁן שׁוֹמֵר יִשְׂרָאֵל: יְהוָה שֹׁמְרֶךָ יְהוָה צִלְּךָ עַל יַד יְמִינֶךָ: יוֹמָם הַשֶּׁמֶשׁ לֹא יַכֶּכָּה וְיָרֵחַ בַּלָּיְלָה: יְהוָה יִשְׁמָרְךָ מִכָּל רָע יִשְׁמֹר אֶת נַפְשֶׁךָ: יְהוָה יִשְׁמָר צֵאתְךָ וּבוֹאֶךָ מֵעַתָּה vְעַד עוֹלָם.",
                    "fonetica": "Essá einái el heharím, meáyin yavó ezrí. Ezrí meím Adonái, osé shamáyim vaárets. Al yitén lamót ragléja, al yanúm shomréja. Hiné lo yanúm veló yishán, shomér Israél. Adonái shomréja, Adonái tsiljá al yad yeminejá. Yomám hashémesh lo yakéka, veyaréaj baláila. Adonái yishmorjá mikol ra, yishmór et nafshéja. Adonái yishmór tsetjá uvoéja, meatá veád olám."
                },
                {
                    "titulo": "TEHILLIM 23 (Salmo 23 - Completo)",
                    "texto": "יְהוָה רֹעִי לֹא אֶחְסָר: בִּנְאוֹת דֶּשֶׁא יַרְבִּיצֵנִי עַל מֵי מְנֻחוֹת יְנַהֲלֵנִי: נַפְשִׁי יְשׁוֹבֵב יַנְחֵנִי בְמַעְגְּלֵי צֶדֶק לְמַעַן שְׁמוֹ: גַּם כִּי אֵלֵךְ בְּגֵיא צַלְמָוֶת לֹא אִירָא רָע כִּי אַתָּה עִמָּדִי שִׁבְטְךָ וּמִשְׁעַנְתֶּךָ הֵמָּה יְנַחֲמֻנִי: תַּעֲרוֹךְ לְפָנַי שֻׁלְחָן נֶגֶד צוֹרְרָי דִּשַּׁנְתָּ בַשֶּׁמֶן רֹאשִׁי כּוֹסִי רְוָיָה: אַךְ טוֹב וָחֶסֶד יִרְדְּפוּנִי כָּל יְמֵי חַיָּי וְשַׁבְתִּי בְּבֵית יְהוָה לְאֹרֶךְ יָמִים.",
                    "fonetica": "Adonái roí lo ejsár. Binót désha yarbitséni, al méi menujót yenahaléni. Nafshí yeshovév, yanjéni vemagléi tsédek lemáan shemó. Gam ki eléj begéi tsalmávet lo irá rá ki atá imadí, shivtejá umishantéja héma yenajamúni. Taarój lefanái shulján négued tsorerái, dishánta vashémen roshí cosí revayá. Aj tov vajésed yirdefúni kol yeméi jayái, veshavtí bevéit Adonái leórej yamím."
                },
                {
                    "titulo": "TEHILLIM 91 (Salmo 91 - Fortaleza)",
                    "texto": "יֹשֵׁב בְּסֵתֶר עֶלְיוֹן בְּצֵל שַׁדַּי יִתְלוֹנָן: אֹמַר לַיהוָה מַחְסִי וּמְצוּדָתִי אֱלֹהַי אֶבְטַח בּוֹ: כִּי הוּא יַצִּילְךָ מִפַּח יָקוּשׁ מִדֶּבֶר הַוּוֹת: בְּאֶבְרָתוֹ יָסֶךְ לָךְ וְתַחַת כְּנָפָיו תֶּחְסֶה צִנָּה וְסֹחֵרָה אֲמִתּוֹ: לֹא תִירָא מִפַּחַד לָיְלָה מֵחֵץ יָעוּף יוֹמָם: כִּי מַלְאָכָיו יְצַוֶּה לָּךְ לִשְׁמָרְךָ בְּכָל דְּרָכֶיךָ.",
                    "fonetica": "Yoshév beséter Elyón, betsél Shadái yitlonán. Omár Adonái majsí umtsudatí, Elohái evtaj bo. Ki hu yatsiljá mipáj yakúsh, midéver havót. Be-evrató yásej laj, vetájat knafáv tejssé, tsiná vesojerá amitó. Lo tirá mipájad láila, mejéts yaúf yomám. Ki malajáv yetsavé laj lishmorjá bejól derajéja."
                }
            ]
            p = random.choice(liturgia)
            self.lbl_titulo_salmo.setText(p["titulo"])
            self.lbl_salmo.setText(p["texto"])
            self.verbo_actual = p["texto"]
            self.recitar_verbo(p["fonetica"])
            conn.close()
        except Exception as e: print(f"Error Altar: {e}")

    def mostrar_imagen(self, d, p, t, s):
        if os.path.exists(p):
            pix = QPixmap(p).scaled(s, s, Qt.AspectRatioMode.KeepAspectRatioByExpanding, Qt.TransformationMode.SmoothTransformation)
            d['foto'].setPixmap(pix)
            if 'info' in d: d['info'].setText(t)
        else:
            d['foto'].setText("Busca la imagen en la DB")
            d['foto'].setStyleSheet("color: red; font-size: 10px;")

if __name__ == "__main__":
    app = QApplication(sys.argv); altar = AltarDigital(); altar.show(); sys.exit(app.exec())