"""Diagnostic engine — maps guitar symptoms to logical causes using propositional logic."""

import re
from typing import Dict, List

from sympy import Symbol
from sympy.logic.boolalg import Implies, Or, And

from mentorr.logic_core import LogicCore


class DiagnosticEngine:
    def __init__(self):
        self.rules = []
        self.symbols: Dict[str, Symbol] = {}
        self.core = LogicCore()

    def define_symbol(self, name: str) -> Symbol:
        if name not in self.symbols:
            self.symbols[name] = Symbol(name)
        return self.symbols[name]

    def add_rule(self, condition: str, implication: str):
        """Parses simple string rules into SymPy logic.

        Example: "Buzz_Open" -> "Nut_Low | Neck_Backbow"
        """
        tokens = set(re.findall(r'[A-Za-z_0-9]+', condition + " " + implication))
        for t in tokens:
            self.define_symbol(t)

        cond_sym = self._parse_expr(condition)
        impl_sym = self._parse_expr(implication)

        rule = Implies(cond_sym, impl_sym)
        self.rules.append(rule)

    def load_rules_from_markdown(self, file_path: str):
        """Scrapes logic rules from a Markdown file.

        Looks for lines like: **Logic:** A -> (B | C)
        """
        if not re.search(r'\.md$', file_path):
            return

        with open(file_path, 'r', encoding='utf-8') as f:
            for line in f:
                match = re.search(r'\*\*Logic:\*\*\s*(.+)', line)
                if match:
                    logic_str = match.group(1).strip()
                    logic_str = logic_str.replace('\u2192', '->')
                    logic_str = logic_str.replace('\u2228', '|')
                    logic_str = logic_str.replace('\u2227', '&')

                    if '->' in logic_str:
                        cond, conseq = logic_str.split('->', 1)
                        self.add_rule(cond.strip(), conseq.strip())

    def _parse_expr(self, expr_str: str):
        expr_str = expr_str.replace('(', '').replace(')', '')

        or_parts = expr_str.split('|')
        or_syms = []
        for part in or_parts:
            part = part.strip()
            if '&' in part:
                and_parts = part.split('&')
                and_syms = [self.symbols[p.strip()] for p in and_parts if p.strip() in self.symbols]
                if and_syms:
                    or_syms.append(And(*and_syms))
            elif part in self.symbols:
                or_syms.append(self.symbols[part])

        if not or_syms:
            return Symbol('Unknown')

        if len(or_syms) == 1:
            return or_syms[0]
        return Or(*or_syms)

    def diagnose(self, symptoms: List[str]) -> List[str]:
        """Given a list of TRUE symptoms, use LogicCore to find valid deductions."""
        conclusions = []

        symptom_syms = []
        for s in symptoms:
            if s in self.symbols:
                symptom_syms.append(self.symbols[s])
            else:
                return [f"Unknown symptom: {s}"]

        for rule in self.rules:
            cond = rule.args[0]
            conseq = rule.args[1]

            valid, _ = self.core.check_validity(symptom_syms, cond)

            if valid:
                conclusions.append(str(conseq))

        return conclusions
