#!/usr/bin/env python3
"""
ALFRED LINUX v7.5.3 — AUTHORIZED KING JESUS VERSION (PEREZ EDITION) SCRIPTURE STUDIO
Audio Reader & Hebrew / Aramaic / Greek Root Concordance Studio
Installs as: /usr/local/bin/alfred-bible-studio
"""

import os
import sys
import json
import shutil
import subprocess
import urllib.request
import urllib.error

# Force XWayland on Wayland sessions for rock-solid Sovereign desktop rendering
os.environ["QT_QPA_PLATFORM"] = "xcb"

from PyQt6.QtCore import Qt, QThread, pyqtSignal
from PyQt6.QtGui import QFont
from PyQt6.QtWidgets import (
    QApplication,
    QMainWindow,
    QWidget,
    QVBoxLayout,
    QHBoxLayout,
    QLabel,
    QLineEdit,
    QPushButton,
    QTextEdit,
    QComboBox,
    QFrame,
    QSplitter,
    QProgressBar,
)

EDITION_TITLE = "Authorized King Jesus Version (Perez Edition)"

FLAGSHIP_PASSAGES = {
    "Psalm 91 — The Secret Place of the Most High": (
        "Psalm 91",
        """[Authorized King Jesus Version (Perez Edition) — Psalm 91]

91:1 He that dwelleth in the secret place of the most High shall abide under the shadow of the Almighty.
91:2 I will say of the LORD, He is my refuge and my fortress: my God; in him will I trust.
91:3 Surely he shall deliver thee from the snare of the fowler, and from the noisome pestilence.
91:4 He shall cover thee with his feathers, and under his wings shalt thou trust: his truth shall be thy shield and buckler.
91:5 Thou shalt not be afraid for the terror by night; nor for the arrow that flieth by day;
91:6 Nor for the pestilence that walketh in darkness; nor for the destruction that wasteth at noonday.
91:7 A thousand shall fall at thy side, and ten thousand at thy right hand; but it shall not come nigh thee.
91:8 Only with thine eyes shalt thou behold and see the reward of the wicked.
91:9 Because thou hast made the LORD, which is my refuge, even the most High, thy habitation;
91:10 There shall no evil befall thee, neither shall any plague come nigh thy dwelling.
91:11 For he shall give his angels charge over thee, to keep thee in all thy ways.
91:12 They shall bear thee up in their hands, lest thou dash thy foot against a stone.
91:13 Thou shalt tread upon the lion and adder: the young lion and the dragon shalt thou trample under feet.
91:14 Because he hath set his love upon me, therefore will I deliver him: I will set him on high, because he hath known my name.
91:15 He shall call upon me, and I will answer him: I will be with him in trouble; I will deliver him, and honour him.
91:16 With long life will I satisfy him, and shew him my salvation.""",
    ),
    "Psalm 23 — The Lord is My Shepherd": (
        "Psalm 23",
        """[Authorized King Jesus Version (Perez Edition) — Psalm 23]

23:1 The LORD is my shepherd; I shall not want.
23:2 He maketh me to lie down in green pastures: he leadeth me beside the still waters.
23:3 He restoreth my soul: he leadeth me in the paths of righteousness for his name's sake.
23:4 Yea, though I walk through the valley of the shadow of death, I will fear no evil: for thou art with me; thy rod and thy staff they comfort me.
23:5 Thou preparest a table before me in the presence of mine enemies: thou anointest my head with oil; my cup runneth over.
23:6 Surely goodness and mercy shall follow me all the days of my life: and I will dwell in the house of the LORD for ever.""",
    ),
    "John 1:1-14 — The Word Made Flesh": (
        "John 1:1-14",
        """[Authorized King Jesus Version (Perez Edition) — John 1:1-14]

1:1 In the beginning was the Word, and the Word was with God, and the Word was God.
1:2 The same was in the beginning with God.
1:3 All things were made by him; and without him was not any thing made that was made.
1:4 In him was life; and the life was the light of men.
1:5 And the light shineth in darkness; and the darkness comprehended it not.
1:6 There was a man sent from God, whose name was John.
1:7 The same came for a witness, to bear witness of the Light, that all men through him might believe.
1:8 He was not that Light, but was sent to bear witness of that Light.
1:9 That was the true Light, which lighteth every man that cometh into the world.
1:10 He was in the world, and the world was made by him, and the world knew him not.
1:11 He came unto his own, and his own received him not.
1:12 But as many as received him, to them gave he power to become the sons of God, even to them that believe on his name:
1:13 Which were born, not of blood, nor of the will of the flesh, nor of the will of man, but of God.
1:14 And the Word was made flesh, and dwelt among us, (and we beheld his glory, the glory as of the only begotten of the Father,) full of grace and truth.""",
    ),
    "Genesis 1:1-5, 26-31 — Creation of Heaven and Earth": (
        "Genesis 1",
        """[Authorized King Jesus Version (Perez Edition) — Genesis 1]

1:1 In the beginning God created the heaven and the earth.
1:2 And the earth was without form, and void; and darkness was upon the face of the deep. And the Spirit of God moved upon the face of the waters.
1:3 And God said, Let there be light: and there was light.
1:4 And God saw the light, that it was good: and God divided the light from the darkness.
1:5 And God called the light Day, and the darkness he called Night. And the evening and the morning were the first day.
1:26 And God said, Let us make man in our image, after our likeness: and let them have dominion over the fish of the sea, and over the fowl of the air, and over the cattle, and over all the earth, and over every creeping thing that creepeth upon the earth.
1:27 So God created man in his own image, in the image of God created he him; male and female created he them.
1:28 And God blessed them, and God said unto them, Be fruitful, and multiply, and replenish the earth, and subdue it: and have dominion over the fish of the sea, and over the fowl of the air, and over every living thing that moveth upon the earth.
1:31 And God saw every thing that he had made, and, behold, it was very good. And the evening and the morning were the sixth day.""",
    ),
    "Ephesians 6:10-18 — The Whole Armor of God": (
        "Ephesians 6:10-18",
        """[Authorized King Jesus Version (Perez Edition) — Ephesians 6:10-18]

6:10 Finally, my brethren, be strong in the Lord, and in the power of his might.
6:11 Put on the whole armour of God, that ye may be able to stand against the wiles of the devil.
6:12 For we wrestle not against flesh and blood, but against principalities, against powers, against the rulers of the darkness of this world, against spiritual wickedness in high places.
6:13 Wherefore take unto you the whole armour of God, that ye may be able to withstand in the evil day, and having done all, to stand.
6:14 Stand therefore, having your loins girt about with truth, and having on the breastplate of righteousness;
6:15 And your feet shod with the preparation of the gospel of peace;
6:16 Above all, taking the shield of faith, wherewith ye shall be able to quench all the fiery darts of the wicked.
6:17 And take the helmet of salvation, and the sword of the Spirit, which is the word of God:
6:18 Praying always with all prayer and supplication in the Spirit, and watching thereunto with all perseverance and supplication for all saints.""",
    ),
    "Matthew 5:1-16 — The Beatitudes & Light of the World": (
        "Matthew 5:1-16",
        """[Authorized King Jesus Version (Perez Edition) — Matthew 5:1-16]

5:1 And seeing the multitudes, he went up into a mountain: and when he was set, his disciples came unto him:
5:2 And he opened his mouth, and taught them, saying,
5:3 Blessed are the poor in spirit: for theirs is the kingdom of heaven.
5:4 Blessed are they that mourn: for they shall be comforted.
5:5 Blessed are the meek: for they shall inherit the earth.
5:6 Blessed are they which do hunger and thirst after righteousness: for they shall be filled.
5:7 Blessed are the merciful: for they shall obtain mercy.
5:8 Blessed are the pure in heart: for they shall see God.
5:9 Blessed are the peacemakers: for they shall be called the children of God.
5:10 Blessed are they which are persecuted for righteousness' sake: for theirs is the kingdom of heaven.
5:11 Blessed are ye, when men shall revile you, and persecute you, and shall say all manner of evil against you falsely, for my sake.
5:12 Rejoice, and be exceeding glad: for great is your reward in heaven: for so persecuted they the prophets which were before you.
5:13 Ye are the salt of the earth: but if the salt have lost his savour, wherewith shall it be salted? it is thenceforth good for nothing, but to be cast out, and to be trodden under foot of men.
5:14 Ye are the light of the world. A city that is set on an hill cannot be hid.
5:15 Neither do men light a candle, and put it under a bushel, but on a candlestick; and it giveth light unto all that are in the house.
5:16 Let your light so shine before men, that they may see your good works, and glorify your Father which is in heaven.""",
    ),
    "Revelation 21:1-7 — All Things New": (
        "Revelation 21:1-7",
        """[Authorized King Jesus Version (Perez Edition) — Revelation 21:1-7]

21:1 And I saw a new heaven and a new earth: for the first heaven and the first earth were passed away; and there was no more sea.
21:2 And I John saw the holy city, new Jerusalem, coming down from God out of heaven, prepared as a bride adorned for her husband.
21:3 And I heard a great voice out of heaven saying, Behold, the tabernacle of God is with men, and he will dwell with them, and they shall be his people, and God himself shall be with them, and be their God.
21:4 And God shall wipe away all tears from their eyes; and there shall be no more death, neither sorrow, nor crying, neither shall there be any more pain: for the former things are passed away.
21:5 And he that sat upon the throne said, Behold, I make all things new. And he said unto me, Write: for these words are true and faithful.
21:6 And he said unto me, It is done. I am Alpha and Omega, the beginning and the end. I will give unto him that is athirst of the fountain of the water of life freely.
21:7 He that overcometh shall inherit all things; and I will be his God, and he shall be my son.""",
    ),
}

SOVEREIGN_BIBLE_STYLESHEET = """
QMainWindow, QWidget {
    background-color: #0A0B0E;
    color: #F4ECD8;
    font-family: 'Georgia', 'Liberation Serif', 'Segoe UI', serif;
    font-size: 14px;
}
QFrame#HeaderBanner {
    background: qlineargradient(x1:0, y1:0, x2:1, y2:0,
        stop:0 #12100B, stop:0.5 #231C0D, stop:1 #12100B);
    border: 1px solid #D4AF37;
    border-radius: 8px;
    padding: 8px;
}
QFrame#CardPanel {
    background-color: #11131A;
    border: 1px solid #332B1A;
    border-radius: 8px;
}
QLabel#TitleLabel {
    color: #FFD700;
    font-size: 20px;
    font-weight: bold;
    letter-spacing: 0.8px;
}
QLabel#SubtitleLabel {
    color: #D4AF37;
    font-size: 12px;
    font-family: 'Inter', 'Segoe UI', sans-serif;
}
QLabel#SectionHeader {
    color: #FFD700;
    font-size: 13px;
    font-weight: bold;
    font-family: 'Inter', 'Segoe UI', sans-serif;
    letter-spacing: 0.8px;
}
QLineEdit {
    background-color: #151821;
    color: #FFD700;
    border: 1px solid #D4AF37;
    border-radius: 6px;
    padding: 8px 12px;
    font-family: 'Inter', 'Segoe UI', sans-serif;
    font-size: 14px;
}
QComboBox {
    background-color: #151821;
    color: #FFD700;
    border: 1px solid #D4AF37;
    border-radius: 6px;
    padding: 7px 12px;
    font-family: 'Inter', 'Segoe UI', sans-serif;
    font-weight: bold;
    min-width: 280px;
}
QComboBox QAbstractItemView {
    background-color: #151821;
    color: #F4ECD8;
    selection-background-color: #D4AF37;
    selection-color: #0A0B0E;
    border: 1px solid #D4AF37;
}
QTextEdit {
    background-color: #0D0E12;
    color: #F6EFE0;
    border: 1px solid #3A311E;
    border-radius: 6px;
    padding: 14px;
    font-size: 16px;
    line-height: 1.5;
    selection-background-color: #D4AF37;
    selection-color: #0A0B0E;
}
QPushButton {
    background-color: #191C26;
    color: #E8D08C;
    border: 1px solid #8A7028;
    border-radius: 6px;
    padding: 8px 15px;
    font-family: 'Inter', 'Segoe UI', sans-serif;
    font-weight: bold;
}
QPushButton:hover {
    background-color: #2A2312;
    border: 1px solid #FFD700;
    color: #FFD700;
}
QPushButton:disabled {
    background-color: #121318;
    color: #55524A;
    border: 1px solid #2A2822;
}
QPushButton#GoldActionBtn {
    background: qlineargradient(x1:0, y1:0, x2:0, y2:1,
        stop:0 #E5C158, stop:1 #B8860B);
    color: #0A0B0E;
    border: 1px solid #FFD700;
    font-size: 13px;
    font-weight: bold;
    padding: 9px 16px;
}
QPushButton#GoldActionBtn:hover {
    background: qlineargradient(x1:0, y1:0, x2:0, y2:1,
        stop:0 #FFD700, stop:1 #D4AF37);
}
QPushButton#StopBtn {
    background-color: #311519;
    color: #FFA5A5;
    border: 1px solid #A83844;
}
QPushButton#StopBtn:hover {
    background-color: #4A1C22;
    border: 1px solid #FF6B6B;
    color: #FFFFFF;
}
QProgressBar {
    border: 1px solid #D4AF37;
    border-radius: 4px;
    background-color: #11131A;
    text-align: center;
    color: #FFD700;
    font-family: 'Inter', sans-serif;
    font-weight: bold;
}
QProgressBar::chunk {
    background-color: #B8860B;
}
"""


def enforce_edition_branding(text: str) -> str:
    """Ensure all displayed scripture headers and descriptions strictly credit Authorized King Jesus Version (Perez Edition)."""
    cleaned = text
    for legacy_term in ("King" + " " + "James" + " Version", "King" + " " + "James", "KJV", "AKJV"):
        cleaned = cleaned.replace(legacy_term, EDITION_TITLE)
    return cleaned


def resolve_ollama_model(preferred="alfred-haiku:latest") -> str:
    try:
        req = urllib.request.Request("http://127.0.0.1:11434/api/tags", method="GET")
        with urllib.request.urlopen(req, timeout=3) as resp:
            data = json.loads(resp.read().decode("utf-8", errors="replace"))
            models = [m.get("name", "") for m in data.get("models", [])]
            if preferred in models:
                return preferred
            for m in models:
                if "haiku" in m.lower() or "alfred" in m.lower() or "qwen" in m.lower() or "llama" in m.lower():
                    return m
            if models:
                return models[0]
    except Exception:
        pass
    return preferred


import re

AKJV_TSV_PATHS = (
    "/usr/share/alfred/bible/akjv-bible.tsv",
    "/opt/bible/akjv-bible.tsv",
    "/usr/local/share/alfred/bible/akjv-bible.tsv",
)
AKJV_PDF_PATH = "/opt/bible/akjv-perez-edition.pdf"
_AKJV_INDEX = {"loaded": False, "books": [], "chapters": {}}


def load_akjv_94_index():
    if _AKJV_INDEX["loaded"]:
        return _AKJV_INDEX
    tsv_path = next((p for p in AKJV_TSV_PATHS if os.path.isfile(p)), "")
    books = []
    chapters = {}
    if tsv_path:
        try:
            with open(tsv_path, "r", encoding="utf-8", errors="replace") as f:
                for idx, ln in enumerate(f):
                    if idx == 0 and ln.startswith("book_name"):
                        continue
                    parts = ln.rstrip("\r\n").split("\t")
                    if len(parts) < 4:
                        continue
                    bname, ch_s, vs_s, txt = parts[0], parts[1], parts[2], parts[3]
                    if bname not in chapters:
                        books.append(bname)
                        chapters[bname] = {}
                    ch_list = chapters[bname].setdefault(ch_s, [])
                    ch_list.append((vs_s, txt))
        except Exception:
            pass
    _AKJV_INDEX["loaded"] = True
    _AKJV_INDEX["books"] = books
    _AKJV_INDEX["chapters"] = chapters
    return _AKJV_INDEX


class ScriptureSearchWorker(QThread):
    result_signal = pyqtSignal(str, str)
    error_signal = pyqtSignal(str)

    def __init__(self, query: str):
        super().__init__()
        self.query = query.strip()

    def run(self):
        if not self.query:
            self.error_signal.emit("Please enter a verse reference or keyword to search.")
            return

        # 0. Direct 94-Book AKJV TSV Lookup (39,482 Verses across OT, NT, Apocrypha & Enochian Canon)
        idx = load_akjv_94_index()
        q_clean = self.query.strip()
        q_low = q_clean.lower()
        for bname in idx["books"]:
            b_low = bname.lower()
            b_short = re.sub(r"\s*\(.*?\)", "", b_low).strip()
            for cand in (b_low, b_short):
                if cand and (q_low == cand or q_low.startswith(cand + " ")):
                    rest = q_low[len(cand):].strip()
                    ch_s = "1"
                    vs_s = None
                    if rest:
                        m_cv = re.match(r"^(?:chapter\s+|ch\s+)?(\d+)(?:\s*:\s*|\s+verse\s+|\s+)(\d+)?$", rest)
                        if m_cv:
                            ch_s = m_cv.group(1)
                            vs_s = m_cv.group(2)
                        elif rest.isdigit():
                            ch_s = rest
                    ch_map = idx["chapters"].get(bname, {})
                    if ch_s in ch_map:
                        verses = ch_map[ch_s]
                        if vs_s:
                            v_hits = [f"{ch_s}:{v} {t}" for v, t in verses if v == vs_s]
                            if v_hits:
                                ref_lbl = f"{bname} {ch_s}:{vs_s}"
                                body = f"[{EDITION_TITLE} — {ref_lbl}]\n\n" + "\n\n".join(v_hits)
                                self.result_signal.emit(ref_lbl, body)
                                return
                        ref_lbl = f"{bname} {ch_s}"
                        lines = [f"{ch_s}:{v} {t}" for v, t in verses]
                        body = f"[{EDITION_TITLE} — {ref_lbl}]\n\n" + "\n".join(lines)
                        self.result_signal.emit(ref_lbl, body)
                        return

        # 1. Check built-in flagship passages for instant match
        q_lower = self.query.lower()
        for title, (ref, body) in FLAGSHIP_PASSAGES.items():
            if q_lower == ref.lower() or q_lower in title.lower():
                self.result_signal.emit(ref, enforce_edition_branding(body))
                return

        # 1B. Full-Text Keyword Search across all 39,482 AKJV Verses
        if idx["books"]:
            kw_hits = []
            for bname in idx["books"]:
                for ch_s, verses in idx["chapters"].get(bname, {}).items():
                    for vs_s, txt in verses:
                        if q_lower in txt.lower():
                            kw_hits.append(f"• {bname} {ch_s}:{vs_s} — {txt}")
                            if len(kw_hits) >= 35:
                                break
                    if len(kw_hits) >= 35:
                        break
                if len(kw_hits) >= 35:
                    break
            if kw_hits:
                ref_lbl = f"Concordance Search: '{self.query}' ({len(kw_hits)} matches shown)"
                body = f"[{EDITION_TITLE} — {ref_lbl}]\n\n" + "\n\n".join(kw_hits)
                self.result_signal.emit(ref_lbl, body)
                return

        # 2. Query /usr/local/bin/alfred-bible <query>
        bible_bin = "/usr/local/bin/alfred-bible"
        if os.path.exists(bible_bin) or shutil.which("alfred-bible"):
            cmd_path = bible_bin if os.path.exists(bible_bin) else "alfred-bible"
            try:
                res = subprocess.run(
                    [cmd_path, self.query],
                    capture_output=True,
                    text=True,
                    timeout=15,
                )
                output = (res.stdout or "").strip()
                if output and len(output) > 12:
                    branded = enforce_edition_branding(output)
                    if EDITION_TITLE not in branded:
                        branded = f"[{EDITION_TITLE} — {self.query}]\n\n{branded}"
                    self.result_signal.emit(self.query, branded)
                    return
            except Exception:
                pass

        # 3. Fallback: Query local Ollama to render the exact passage in Authorized King Jesus Version (Perez Edition)
        model_name = resolve_ollama_model("alfred-haiku:latest")
        prompt = (
            f"You are the {EDITION_TITLE} Scripture Engine.\n"
            f"Provide the full verbatim scripture verses for '{self.query}' from the {EDITION_TITLE}.\n"
            f"Include verse numbers clearly and always title the header with [{EDITION_TITLE} — {self.query}]."
        )
        payload = json.dumps(
            {
                "model": model_name,
                "prompt": prompt,
                "stream": False,
                "options": {"temperature": 0.1, "num_predict": 700},
            }
        ).encode("utf-8")

        try:
            req = urllib.request.Request(
                "http://127.0.0.1:11434/api/generate",
                data=payload,
                headers={"Content-Type": "application/json"},
                method="POST",
            )
            with urllib.request.urlopen(req, timeout=45) as resp:
                data = json.loads(resp.read().decode("utf-8", errors="replace"))
                ans = enforce_edition_branding(data.get("response", "").strip())
                if ans:
                    self.result_signal.emit(self.query, ans)
                    return
        except Exception as e:
            self.error_signal.emit(f"Could not retrieve '{self.query}': {e}")
            return

        self.error_signal.emit(f"No verses found for '{self.query}'.")


class RootConcordanceWorker(QThread):
    result_signal = pyqtSignal(str)
    error_signal = pyqtSignal(str)

    def __init__(self, reference: str, passage_text: str):
        super().__init__()
        self.reference = reference
        self.passage_text = passage_text.strip()

    def run(self):
        model_name = resolve_ollama_model("alfred-haiku:latest")
        prompt = (
            f"You are the Sovereign Biblical Philologist & Concordance Scholar for the {EDITION_TITLE}.\n"
            f"Analyze the following passage ({self.reference}) and provide a structured study guide with:\n"
            f"1. KEY HEBREW / ARAMAIC / GREEK ROOT WORDS: Original script, transliteration, Strong's-style root definition, and literal meaning.\n"
            f"2. GEMATRIA & NUMERIC / SYMBOLIC SIGNIFICANCE: Key biblical numbers, covenant structure, and prophetic patterns.\n"
            f"3. CROSS-REFERENCES ({EDITION_TITLE}): Direct Old & New Testament parallel verses that illuminate this passage.\n\n"
            f"Passage ({self.reference}):\n{self.passage_text[:2500]}"
        )
        payload = json.dumps(
            {
                "model": model_name,
                "prompt": prompt,
                "stream": False,
                "options": {"temperature": 0.25, "num_predict": 900},
            }
        ).encode("utf-8")

        try:
            req = urllib.request.Request(
                "http://127.0.0.1:11434/api/generate",
                data=payload,
                headers={"Content-Type": "application/json"},
                method="POST",
            )
            with urllib.request.urlopen(req, timeout=75) as resp:
                data = json.loads(resp.read().decode("utf-8", errors="replace"))
                analysis = enforce_edition_branding(data.get("response", "").strip())
                self.result_signal.emit(analysis)
        except Exception as e:
            self.error_signal.emit(
                f"Local Ollama root concordance query failed ({e}). Ensure ollama.service is active."
            )


class ScriptureAudioReaderWorker(QThread):
    finished_signal = pyqtSignal()
    status_signal = pyqtSignal(str)

    def __init__(self, passage_text: str):
        super().__init__()
        self.passage_text = passage_text.strip()
        self._proc = None
        self._stopped = False

    def run(self):
        if not self.passage_text:
            self.finished_signal.emit()
            return

        # Clean brackets/verse numbers slightly for natural spoken cadence
        lines = [ln.strip() for ln in self.passage_text.splitlines() if ln.strip()]
        spoken_text = " ".join(lines)

        speak_bin = "/usr/local/bin/alfred-oracle-speak"
        try:
            if os.path.exists(speak_bin):
                self._proc = subprocess.Popen(
                    [speak_bin, spoken_text],
                    stdout=subprocess.DEVNULL,
                    stderr=subprocess.DEVNULL,
                )
                self._proc.wait()
            elif shutil.which("espeak-ng"):
                self._proc = subprocess.Popen(
                    ["espeak-ng", "-s", "145", spoken_text],
                    stdout=subprocess.DEVNULL,
                    stderr=subprocess.DEVNULL,
                )
                self._proc.wait()
        except Exception:
            pass
        finally:
            self.finished_signal.emit()

    def stop(self):
        self._stopped = True
        if self._proc and self._proc.poll() is None:
            try:
                self._proc.terminate()
                self._proc.kill()
            except Exception:
                pass
        # Also stop any lingering child audio players spawned by alfred-oracle-speak
        for player in ("aplay", "pw-play", "paplay", "ffplay"):
            subprocess.run(["pkill", "-f", player], capture_output=True)


class BibleStudioWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle(f"ALFRED v7.5.3 — {EDITION_TITLE} Scripture & Concordance Studio")
        self.resize(1220, 780)
        self.setStyleSheet(SOVEREIGN_BIBLE_STYLESHEET)

        self.current_reference = "Psalm 91"
        self.search_worker = None
        self.concordance_worker = None
        self.audio_worker = None

        self._build_ui()
        self._load_flagship_index(0)

    def _build_ui(self):
        central = QWidget()
        self.setCentralWidget(central)
        root_layout = QVBoxLayout(central)
        root_layout.setContentsMargins(16, 14, 16, 14)
        root_layout.setSpacing(12)

        # Header Banner
        header = QFrame()
        header.setObjectName("HeaderBanner")
        header_layout = QHBoxLayout(header)
        header_layout.setContentsMargins(16, 10, 16, 10)

        title_col = QVBoxLayout()
        title_lbl = QLabel(f"📜 {EDITION_TITLE.upper()}")
        title_lbl.setObjectName("TitleLabel")
        subtitle_lbl = QLabel(
            "Sovereign Audio Scripture Reader • Hebrew / Aramaic / Greek Root Concordance & Gematria Studio"
        )
        subtitle_lbl.setObjectName("SubtitleLabel")
        title_col.addWidget(title_lbl)
        title_col.addWidget(subtitle_lbl)
        header_layout.addLayout(title_col)
        header_layout.addStretch()

        self.read_aloud_btn = QPushButton("🔊 Read Passage Aloud with Alfred")
        self.read_aloud_btn.setObjectName("GoldActionBtn")
        self.read_aloud_btn.clicked.connect(self.start_reading_aloud)

        self.stop_audio_btn = QPushButton("⏹ Stop Reading")
        self.stop_audio_btn.setObjectName("StopBtn")
        self.stop_audio_btn.setEnabled(False)
        self.stop_audio_btn.clicked.connect(self.stop_reading_aloud)

        header_layout.addWidget(self.read_aloud_btn)
        header_layout.addWidget(self.stop_audio_btn)
        root_layout.addWidget(header)

        # Search & Flagship Passage Bar
        nav_bar = QFrame()
        nav_bar.setObjectName("CardPanel")
        nav_layout = QHBoxLayout(nav_bar)
        nav_layout.setContentsMargins(14, 10, 14, 10)
        nav_layout.setSpacing(10)

        flagship_lbl = QLabel("94-BOOK CANON:")
        flagship_lbl.setObjectName("SectionHeader")
        self.book_combo = QComboBox()
        self.book_combo.setMinimumWidth(210)
        self.ch_combo = QComboBox()
        self.ch_combo.setMinimumWidth(75)
        _idx_data = load_akjv_94_index()
        for _b in _idx_data["books"]:
            self.book_combo.addItem(_b)
        self.book_combo.currentIndexChanged.connect(self._on_book_selected)
        self.ch_combo.currentIndexChanged.connect(self._on_chapter_selected)

        self.flagship_combo = QComboBox()
        self.flagship_combo.addItem("★ Flagship Passages...")
        for title in FLAGSHIP_PASSAGES.keys():
            self.flagship_combo.addItem(title)
        self.flagship_combo.currentIndexChanged.connect(self._load_flagship_index)

        search_lbl = QLabel("SEARCH:")
        search_lbl.setObjectName("SectionHeader")
        self.search_input = QLineEdit()
        self.search_input.setPlaceholderText("Book Ch:Vs or keyword (e.g., Bel and the Dragon 1:1, 1 Enoch 1, Isaiah 53)...")
        self.search_input.returnPressed.connect(self.search_scripture)

        self.search_btn = QPushButton("🔎 Search 94 Books")
        self.search_btn.clicked.connect(self.search_scripture)

        self.pdf_btn = QPushButton("📄 94-Book PDF")
        self.pdf_btn.clicked.connect(self.open_full_pdf)

        self.analyze_roots_btn = QPushButton("🔍 Root Concordance")
        self.analyze_roots_btn.setObjectName("GoldActionBtn")
        self.analyze_roots_btn.clicked.connect(self.run_root_concordance)

        nav_layout.addWidget(flagship_lbl)
        nav_layout.addWidget(self.book_combo)
        nav_layout.addWidget(self.ch_combo)
        nav_layout.addWidget(self.flagship_combo)
        nav_layout.addWidget(search_lbl)
        nav_layout.addWidget(self.search_input, stretch=1)
        nav_layout.addWidget(self.search_btn)
        nav_layout.addWidget(self.pdf_btn)
        nav_layout.addWidget(self.analyze_roots_btn)
        root_layout.addWidget(nav_bar)

        # Main Side-by-Side Splitter: Scripture Reader (Left) + Concordance Analysis (Right)
        splitter = QSplitter(Qt.Orientation.Horizontal)

        # Left Panel: Scripture Reader
        left_panel = QFrame()
        left_panel.setObjectName("CardPanel")
        left_layout = QVBoxLayout(left_panel)
        left_layout.setContentsMargins(14, 12, 14, 12)
        left_layout.setSpacing(8)

        left_hdr = QHBoxLayout()
        self.passage_header_lbl = QLabel(f"SCRIPTURE TEXT — {EDITION_TITLE.upper()}")
        self.passage_header_lbl.setObjectName("SectionHeader")
        copy_scripture_btn = QPushButton("📋 Copy Passage")
        copy_scripture_btn.clicked.connect(self.copy_passage)
        left_hdr.addWidget(self.passage_header_lbl)
        left_hdr.addStretch()
        left_hdr.addWidget(copy_scripture_btn)
        left_layout.addLayout(left_hdr)

        self.scripture_view = QTextEdit()
        self.scripture_view.setReadOnly(False)
        scripture_font = QFont("Georgia", 15)
        self.scripture_view.setFont(scripture_font)
        left_layout.addWidget(self.scripture_view, stretch=1)

        # Right Panel: Root Concordance & Gematria Analysis
        right_panel = QFrame()
        right_panel.setObjectName("CardPanel")
        right_layout = QVBoxLayout(right_panel)
        right_layout.setContentsMargins(14, 12, 14, 12)
        right_layout.setSpacing(8)

        right_hdr = QHBoxLayout()
        concordance_lbl = QLabel("HEBREW / ARAMAIC / GREEK ROOT CONCORDANCE & CROSS-REFERENCES")
        concordance_lbl.setObjectName("SectionHeader")
        copy_analysis_btn = QPushButton("📋 Copy Study Notes")
        copy_analysis_btn.clicked.connect(self.copy_analysis)
        right_hdr.addWidget(concordance_lbl)
        right_hdr.addStretch()
        right_hdr.addWidget(copy_analysis_btn)
        right_layout.addLayout(right_hdr)

        self.concordance_view = QTextEdit()
        self.concordance_view.setReadOnly(True)
        self.concordance_view.setPlaceholderText(
            "Click '🔍 Hebrew / Aramaic / Greek Root & Cross-Reference Analysis' to generate a deep philological, "
            "Strong's root, Gematria, and cross-reference study for the active passage via local Ollama..."
        )
        right_layout.addWidget(self.concordance_view, stretch=1)

        splitter.addWidget(left_panel)
        splitter.addWidget(right_panel)
        splitter.setSizes([640, 560])
        root_layout.addWidget(splitter, stretch=1)

        # Status Bar
        status_frame = QFrame()
        status_frame.setObjectName("CardPanel")
        status_layout = QHBoxLayout(status_frame)
        status_layout.setContentsMargins(12, 6, 12, 6)

        self.status_label = QLabel(f"Ready • {EDITION_TITLE} Loaded")
        self.status_label.setStyleSheet("color: #D4AF37; font-family: 'Inter', sans-serif; font-weight: bold;")
        self.progress_bar = QProgressBar()
        self.progress_bar.setFixedWidth(220)
        self.progress_bar.setRange(0, 100)
        self.progress_bar.setValue(100)
        self.progress_bar.setFormat("READY")

        status_layout.addWidget(self.status_label)
        status_layout.addStretch()
        status_layout.addWidget(self.progress_bar)
        root_layout.addWidget(status_frame)

    def _on_book_selected(self, idx: int):
        bname = self.book_combo.currentText()
        idx_data = load_akjv_94_index()
        ch_map = idx_data["chapters"].get(bname, {})
        self.ch_combo.blockSignals(True)
        self.ch_combo.clear()
        for ch_s in sorted(ch_map.keys(), key=lambda x: int(x) if x.isdigit() else 999):
            self.ch_combo.addItem(f"Ch {ch_s}", ch_s)
        self.ch_combo.blockSignals(False)
        if self.ch_combo.count() > 0:
            self._on_chapter_selected(0)

    def _on_chapter_selected(self, idx: int):
        bname = self.book_combo.currentText()
        ch_s = self.ch_combo.currentData() or "1"
        idx_data = load_akjv_94_index()
        verses = idx_data["chapters"].get(bname, {}).get(str(ch_s), [])
        if verses:
            ref = f"{bname} {ch_s}"
            body = f"[{EDITION_TITLE} — {ref}]\n\n" + "\n".join(f"{ch_s}:{v} {t}" for v, t in verses)
            self.current_reference = ref
            self.passage_header_lbl.setText(f"{ref.upper()} — {EDITION_TITLE.upper()} (94-BOOK CANON)")
            self.scripture_view.setPlainText(body)
            self.status_label.setText(f"📜 Loaded {ref} ({len(verses)} verses • {EDITION_TITLE})")

    def open_full_pdf(self):
        if os.path.isfile(AKJV_PDF_PATH):
            subprocess.Popen(["xdg-open", AKJV_PDF_PATH], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
            self.status_label.setText(f"📄 Opened {AKJV_PDF_PATH}")
        else:
            self.status_label.setText("⚠️ PDF file /opt/bible/akjv-perez-edition.pdf not found.")

    def _load_flagship_index(self, idx: int):
        title = self.flagship_combo.itemText(idx)
        if title in FLAGSHIP_PASSAGES:
            ref, text = FLAGSHIP_PASSAGES[title]
            self.current_reference = ref
            self.passage_header_lbl.setText(f"{ref.upper()} — {EDITION_TITLE.upper()}")
            self.scripture_view.setPlainText(enforce_edition_branding(text))
            self.status_label.setText(f"📜 Loaded {ref} ({EDITION_TITLE})")

    def search_scripture(self):
        query = self.search_input.text().strip()
        if not query:
            self.status_label.setText("⚠️ Enter a book, chapter:verse, or keyword to search.")
            return

        if self.search_worker and self.search_worker.isRunning():
            return

        self.search_btn.setEnabled(False)
        self.progress_bar.setRange(0, 0)
        self.progress_bar.setFormat("SEARCHING...")
        self.status_label.setText(f"🔎 Searching {EDITION_TITLE} for '{query}'...")

        self.search_worker = ScriptureSearchWorker(query)
        self.search_worker.result_signal.connect(self._on_search_result)
        self.search_worker.error_signal.connect(self._on_worker_error)
        self.search_worker.start()

    def _on_search_result(self, ref: str, text: str):
        self.search_btn.setEnabled(True)
        self.progress_bar.setRange(0, 100)
        self.progress_bar.setValue(100)
        self.progress_bar.setFormat("READY")

        self.current_reference = ref
        self.passage_header_lbl.setText(f"{ref.upper()} — {EDITION_TITLE.upper()}")
        self.scripture_view.setPlainText(enforce_edition_branding(text))
        self.status_label.setText(f"✅ Displayed {ref} ({EDITION_TITLE})")

    def run_root_concordance(self):
        passage = self.scripture_view.toPlainText().strip()
        if not passage:
            self.status_label.setText("⚠️ No passage loaded to analyze.")
            return

        if self.concordance_worker and self.concordance_worker.isRunning():
            return

        self.analyze_roots_btn.setEnabled(False)
        self.progress_bar.setRange(0, 0)
        self.progress_bar.setFormat("ANALYZING ROOTS...")
        self.status_label.setText(
            f"🔍 Querying local Ollama (alfred-haiku:latest) for Hebrew/Aramaic/Greek roots of {self.current_reference}..."
        )

        self.concordance_worker = RootConcordanceWorker(self.current_reference, passage)
        self.concordance_worker.result_signal.connect(self._on_concordance_result)
        self.concordance_worker.error_signal.connect(self._on_worker_error)
        self.concordance_worker.start()

    def _on_concordance_result(self, analysis_text: str):
        self.analyze_roots_btn.setEnabled(True)
        self.progress_bar.setRange(0, 100)
        self.progress_bar.setValue(100)
        self.progress_bar.setFormat("COMPLETE")

        header = f"=== {EDITION_TITLE.upper()} • ROOT CONCORDANCE: {self.current_reference.upper()} ===\n\n"
        self.concordance_view.setPlainText(header + enforce_edition_branding(analysis_text))
        self.status_label.setText(f"✅ Root Concordance & Cross-Reference Analysis complete for {self.current_reference}.")

    def _on_worker_error(self, msg: str):
        self.search_btn.setEnabled(True)
        self.analyze_roots_btn.setEnabled(True)
        self.progress_bar.setRange(0, 100)
        self.progress_bar.setValue(0)
        self.progress_bar.setFormat("ERROR")
        self.status_label.setText(f"⚠️ {msg}")

    def start_reading_aloud(self):
        passage = self.scripture_view.toPlainText().strip()
        if not passage:
            return
        self.stop_reading_aloud()

        self.read_aloud_btn.setEnabled(False)
        self.stop_audio_btn.setEnabled(True)
        self.status_label.setText(
            f"🔊 Reading {self.current_reference} ({EDITION_TITLE}) aloud via /usr/local/bin/alfred-oracle-speak..."
        )

        self.audio_worker = ScriptureAudioReaderWorker(passage)
        self.audio_worker.finished_signal.connect(self._on_reading_finished)
        self.audio_worker.start()

    def stop_reading_aloud(self):
        if self.audio_worker and self.audio_worker.isRunning():
            self.audio_worker.stop()
        self.read_aloud_btn.setEnabled(True)
        self.stop_audio_btn.setEnabled(False)
        self.status_label.setText("⏹ Scripture audio reading stopped.")

    def _on_reading_finished(self):
        self.read_aloud_btn.setEnabled(True)
        self.stop_audio_btn.setEnabled(False)
        self.status_label.setText(f"✅ Finished reading {self.current_reference} aloud.")

    def copy_passage(self):
        cb = QApplication.clipboard()
        if cb:
            cb.setText(self.scripture_view.toPlainText())
            self.status_label.setText(f"📋 Copied {self.current_reference} ({EDITION_TITLE}) to clipboard.")

    def copy_analysis(self):
        cb = QApplication.clipboard()
        if cb:
            cb.setText(self.concordance_view.toPlainText())
            self.status_label.setText("📋 Copied Hebrew/Greek Root Concordance notes to clipboard.")


def main():
    app = QApplication(sys.argv)
    app.setApplicationName(f"Alfred Scripture Studio — {EDITION_TITLE}")
    win = BibleStudioWindow()
    win.show()
    sys.exit(app.exec())


if __name__ == "__main__":
    main()
