import sys
import json
import os
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.QtGui import *
import math

class FormulaDatabase:
    """数学公式数据库管理类"""
    def __init__(self, data_file="formulas.json"):
        self.data_file = data_file
        self.formulas = self._load_formulas()
    
    def _load_formulas(self):
        """加载公式数据"""
        default_data = {
            "代数": {
                "一元二次方程求根公式": {
                    "公式": "x = [-b ± √(b² - 4ac)] / 2a",
                    "说明": "解 ax² + bx + c = 0 的公式，其中a≠0",
                    "示例": "对于 2x² + 5x - 3 = 0，a=2, b=5, c=-3，\n解为 x=0.5 或 x=-3"
                },
                "平方差公式": {
                    "公式": "a² - b² = (a+b)(a-b)",
                    "说明": "平方差因式分解公式",
                    "示例": "x² - 9 = (x+3)(x-3)"
                },
                "完全平方公式": {
                    "公式": "(a ± b)² = a² ± 2ab + b²",
                    "说明": "完全平方展开公式",
                    "示例": "(x+2)² = x² + 4x + 4"
                }
            },
            "几何": {
                "勾股定理": {
                    "公式": "c² = a² + b²",
                    "说明": "直角三角形斜边平方等于两直角边平方和",
                    "示例": "a=3, b=4, 则 c=√(3²+4²)=5"
                },
                "圆面积公式": {
                    "公式": "S = πr²",
                    "说明": "圆的面积公式，r为半径",
                    "示例": "r=2, 则 S=4π≈12.57"
                },
                "球体积公式": {
                    "公式": "V = (4/3)πr³",
                    "说明": "球的体积公式",
                    "示例": "r=3, 则 V=36π≈113.1"
                }
            },
            "微积分": {
                "幂函数导数": {
                    "公式": "(xⁿ)' = nxⁿ⁻¹",
                    "说明": "幂函数的导数公式",
                    "示例": "(x³)' = 3x²"
                },
                "指数函数导数": {
                    "公式": "(eˣ)' = eˣ",
                    "说明": "自然指数函数的导数",
                    "示例": "(e²ˣ)' = 2e²ˣ"
                },
                "幂函数积分": {
                    "公式": "∫xⁿ dx = xⁿ⁺¹/(n+1) + C (n≠-1)",
                    "说明": "幂函数的不定积分公式",
                    "示例": "∫x² dx = x³/3 + C"
                }
            },
            "三角函数": {
                "正弦定理": {
                    "公式": "a/sinA = b/sinB = c/sinC = 2R",
                    "说明": "三角形边与对角正弦值之比等于外接圆直径",
                    "示例": "已知a=5, A=30°, B=60°, 则b=a*sinB/sinA≈8.66"
                },
                "余弦定理": {
                    "公式": "c² = a² + b² - 2ab·cosC",
                    "说明": "三角形边长与夹角的关系",
                    "示例": "已知a=3, b=4, C=60°, 则c=√(9+16-24 * 0.5)=√13≈3.606"
                }
            },
            "概率统计": {
                "期望公式": {
                    "公式": "E(X) = Σ[x * P(x)]",
                    "说明": "离散随机变量的数学期望",
                    "示例": "掷骰子期望值 = (1+2+3+4+5+6)/6=3.5"
                },
                "方差公式": {
                    "公式": "Var(X) = E[(X-μ)²] = E(X²) - [E(X)]²",
                    "说明": "随机变量的方差公式",
                    "示例": ""
                }
            }
        }
        
        if os.path.exists(self.data_file):
            try:
                with open(self.data_file, 'r', encoding='utf-8') as f:
                    return json.load(f)
            except:
                return default_data
        else:
            self._save_formulas(default_data)
            return default_data
    
    def _save_formulas(self, data):
        """保存公式数据"""
        with open(self.data_file, 'w', encoding='utf-8') as f:
            json.dump(data, f, ensure_ascii=False, indent=2)
    
    def get_categories(self):
        """获取所有类别"""
        return list(self.formulas.keys())
    
    def get_formulas_by_category(self, category):
        """获取指定类别的所有公式"""
        return self.formulas.get(category, {})
    
    def search_formulas(self, keyword):
        """搜索公式"""
        results = []
        keyword = keyword.lower()
        
        for category, formulas in self.formulas.items():
            for name, info in formulas.items():
                search_text = f"{category} {name} {info.get('公式', '')} {info.get('说明', '')} {info.get('示例', '')}".lower()
                if keyword in search_text:
                    results.append({
                        'category': category,
                        'name': name,
                        'formula': info.get('公式', ''),
                        'description': info.get('说明', ''),
                        'example': info.get('示例', '')
                    })
        return results
    
    def add_formula(self, category, name, formula, description="", example=""):
        """添加公式"""
        if category not in self.formulas:
            self.formulas[category] = {}
        
        if name in self.formulas[category]:
            return False
        
        self.formulas[category][name] = {
            "公式": formula,
            "说明": description,
            "示例": example
        }
        
        self._save_formulas(self.formulas)
        return True
    
    def delete_formula(self, category, name):
        """删除公式"""
        if category in self.formulas and name in self.formulas[category]:
            del self.formulas[category][name]
            if not self.formulas[category]:
                del self.formulas[category]
            self._save_formulas(self.formulas)
            return True
        return False


class CalculatorWidget(QWidget):
    """公式计算器部件"""
    def __init__(self):
        super().__init__()
        self.init_ui()
    
    def init_ui(self):
        layout = QVBoxLayout()
        
        # 标题
        title = QLabel("🧮 公式计算器")
        title.setStyleSheet("font-size: 18px; font-weight: bold; color: #2c3e50;")
        layout.addWidget(title)
        
        # 公式选择
        form_layout = QFormLayout()
        
        self.category_combo = QComboBox()
        self.category_combo.addItems(["几何", "代数", "微积分", "三角函数", "概率统计"])
        
        self.formula_combo = QComboBox()
        self.formula_combo.addItems(["勾股定理", "圆面积公式", "球体积公式"])
        
        form_layout.addRow("公式类别:", self.category_combo)
        form_layout.addRow("选择公式:", self.formula_combo)
        
        layout.addLayout(form_layout)
        
        # 输入参数
        self.param_widget = QWidget()
        param_layout = QVBoxLayout(self.param_widget)
        
        self.param_a = QLineEdit()
        self.param_b = QLineEdit()
        self.param_c = QLineEdit()
        
        param_layout.addWidget(QLabel("参数 a:"))
        param_layout.addWidget(self.param_a)
        param_layout.addWidget(QLabel("参数 b:"))
        param_layout.addWidget(self.param_b)
        param_layout.addWidget(QLabel("参数 c:"))
        param_layout.addWidget(self.param_c)
        
        layout.addWidget(self.param_widget)
        
        # 计算按钮
        calc_btn = QPushButton("计算")
        calc_btn.clicked.connect(self.calculate)
        calc_btn.setStyleSheet("""
            QPushButton {
                background-color: #3498db;
                color: white;
                border: none;
                padding: 8px;
                border-radius: 4px;
                font-weight: bold;
            }
            QPushButton:hover {
                background-color: #2980b9;
            }
        """)
        layout.addWidget(calc_btn)
        
        # 结果显示
        self.result_label = QLabel("结果将在这里显示")
        self.result_label.setStyleSheet("""
            background-color: #f8f9fa;
            border: 1px solid #dee2e6;
            border-radius: 4px;
            padding: 10px;
            font-family: 'Courier New', monospace;
        """)
        self.result_label.setWordWrap(True)
        layout.addWidget(self.result_label)
        
        self.setLayout(layout)
    
    def calculate(self):
        """执行计算"""
        try:
            formula = self.formula_combo.currentText()
            
            if formula == "勾股定理":
                a = float(self.param_a.text()) if self.param_a.text() else 0
                b = float(self.param_b.text()) if self.param_b.text() else 0
                c = math.sqrt(a*a + b*b)
                self.result_label.setText(f"c = √({a}² + {b}²) = {c:.4f}")
            
            elif formula == "圆面积公式":
                r = float(self.param_a.text()) if self.param_a.text() else 0
                area = math.pi * r * r
                self.result_label.setText(f"S = π × {r}² = {area:.4f} ≈ {area}")
            
            elif formula == "球体积公式":
                r = float(self.param_a.text()) if self.param_a.text() else 0
                volume = (4/3) * math.pi * r**3
                self.result_label.setText(f"V = (4/3)π × {r}³ = {volume:.4f}")
            
            else:
                self.result_label.setText("该公式计算功能开发中...")
                
        except Exception as e:
            self.result_label.setText(f"计算错误: {str(e)}")


class FormulaBrowser(QWidget):
    """公式浏览器"""
    def __init__(self, db):
        super().__init__()
        self.db = db
        self.init_ui()
    
    def init_ui(self):
        main_layout = QHBoxLayout()
        
        # 左侧类别列表
        left_widget = QWidget()
        left_layout = QVBoxLayout(left_widget)
        
        # 类别列表
        self.category_list = QListWidget()
        self.category_list.itemClicked.connect(self.on_category_selected)
        left_layout.addWidget(QLabel("📁 公式类别"))
        left_layout.addWidget(self.category_list)
        
        # 搜索框
        search_layout = QHBoxLayout()
        self.search_input = QLineEdit()
        self.search_input.setPlaceholderText("搜索公式...")
        self.search_input.textChanged.connect(self.on_search)
        search_btn = QPushButton("🔍")
        search_btn.clicked.connect(self.on_search)
        search_layout.addWidget(self.search_input)
        search_layout.addWidget(search_btn)
        left_layout.addLayout(search_layout)
        
        # 中间公式列表
        middle_widget = QWidget()
        middle_layout = QVBoxLayout(middle_widget)
        
        self.formula_list = QListWidget()
        self.formula_list.itemClicked.connect(self.on_formula_selected)
        middle_layout.addWidget(QLabel("📝 公式列表"))
        middle_layout.addWidget(self.formula_list)
        
        # 右侧详情显示
        right_widget = QWidget()
        right_layout = QVBoxLayout(right_widget)
        
        self.detail_text = QTextEdit()
        self.detail_text.setReadOnly(True)
        self.detail_text.setStyleSheet("""
            QTextEdit {
                background-color: #f8f9fa;
                border: 1px solid #dee2e6;
                border-radius: 4px;
                padding: 10px;
                font-family: 'Microsoft YaHei';
            }
        """)
        right_layout.addWidget(QLabel("📄 公式详情"))
        right_layout.addWidget(self.detail_text)
        
        # 添加到主布局
        main_layout.addWidget(left_widget, 1)
        main_layout.addWidget(middle_widget, 2)
        main_layout.addWidget(right_widget, 3)
        
        self.setLayout(main_layout)
        
        # 加载类别
        self.load_categories()
    
    def load_categories(self):
        """加载所有类别"""
        self.category_list.clear()
        categories = self.db.get_categories()
        for category in categories:
            formulas = self.db.get_formulas_by_category(category)
            count = len(formulas)
            item = QListWidgetItem(f"{category} ({count}个)")
            item.setData(Qt.UserRole, category)
            self.category_list.addItem(item)
    
    def on_category_selected(self, item):
        """类别选择事件"""
        category = item.data(Qt.UserRole)
        self.load_formulas(category)
    
    def load_formulas(self, category):
        """加载指定类别的公式"""
        self.formula_list.clear()
        self.detail_text.clear()
        
        formulas = self.db.get_formulas_by_category(category)
        for name in formulas.keys():
            item = QListWidgetItem(name)
            item.setData(Qt.UserRole, (category, name))
            self.formula_list.addItem(item)
    
    def on_formula_selected(self, item):
        """公式选择事件"""
        category, name = item.data(Qt.UserRole)
        formula_info = self.db.get_formulas_by_category(category)[name]
        
        # 显示详细信息
        text = f"""<h2 style='color:#2c3e50;'>{name}</h2>
        <h3 style='color:#7f8c8d;'>📁 类别: {category}</h3>
        <hr>
        <h3 style='color:#2980b9;'>📐 公式:</h3>
        <p style='font-size: 20px; font-family: "Times New Roman", serif; margin-left: 20px;'>
        {formula_info.get('公式', '')}
        </p>
        <h3 style='color:#2980b9;'>📋 说明:</h3>
        <p style='margin-left: 20px;'>{formula_info.get('说明', '')}</p>"""
        
        if formula_info.get('示例'):
            text += f"""<h3 style='color:#2980b9;'>🔍 示例:</h3>
            <p style='margin-left: 20px; font-family: "Courier New", monospace;'>
            {formula_info.get('示例', '')}
            </p>"""
        
        self.detail_text.setHtml(text)
    
    def on_search(self):
        """搜索公式"""
        keyword = self.search_input.text().strip()
        if not keyword:
            self.load_categories()
            if self.category_list.count() > 0:
                self.category_list.setCurrentRow(0)
                self.category_list.item(0).setSelected(True)
                self.on_category_selected(self.category_list.item(0))
            return
        
        self.formula_list.clear()
        self.detail_text.clear()
        
        results = self.db.search_formulas(keyword)
        for result in results:
            item = QListWidgetItem(f"[{result['category']}] {result['name']}")
            item.setData(Qt.UserRole, (result['category'], result['name']))
            self.formula_list.addItem(item)


class AddFormulaDialog(QDialog):
    """添加公式对话框"""
    def __init__(self, db, parent=None):
        super().__init__(parent)
        self.db = db
        self.setWindowTitle("➕ 添加新公式")
        self.setModal(True)
        self.init_ui()
    
    def init_ui(self):
        layout = QVBoxLayout()
        
        form_layout = QFormLayout()
        
        # 类别输入
        self.category_combo = QComboBox()
        self.category_combo.setEditable(True)
        self.category_combo.addItems(self.db.get_categories())
        form_layout.addRow("类别:", self.category_combo)
        
        # 公式名称
        self.name_input = QLineEdit()
        form_layout.addRow("公式名称:", self.name_input)
        
        # 公式表达式
        self.formula_input = QLineEdit()
        form_layout.addRow("公式表达式:", self.formula_input)
        
        # 公式说明
        self.description_input = QTextEdit()
        self.description_input.setMaximumHeight(60)
        form_layout.addRow("公式说明:", self.description_input)
        
        # 示例
        self.example_input = QTextEdit()
        self.example_input.setMaximumHeight(60)
        form_layout.addRow("使用示例:", self.example_input)
        
        layout.addLayout(form_layout)
        
        # 按钮
        button_layout = QHBoxLayout()
        add_btn = QPushButton("添加")
        add_btn.clicked.connect(self.accept)
        cancel_btn = QPushButton("取消")
        cancel_btn.clicked.connect(self.reject)
        
        button_layout.addWidget(add_btn)
        button_layout.addWidget(cancel_btn)
        layout.addLayout(button_layout)
        
        self.setLayout(layout)
        self.setFixedSize(400, 300)
    
    def get_data(self):
        """获取输入的数据"""
        return {
            'category': self.category_combo.currentText(),
            'name': self.name_input.text(),
            'formula': self.formula_input.text(),
            'description': self.description_input.toPlainText(),
            'example': self.example_input.toPlainText()
        }


class MainWindow(QMainWindow):
    """主窗口"""
    def __init__(self):
        super().__init__()
        self.db = FormulaDatabase()
        self.init_ui()
    
    def init_ui(self):
        self.setWindowTitle("🧮 数学公式查询系统")
        self.setGeometry(100, 100, 1200, 700)
        
        # 设置图标
        self.setWindowIcon(QIcon(self.create_icon()))
        
        # 创建中心部件
        central_widget = QWidget()
        self.setCentralWidget(central_widget)
        
        # 主布局
        main_layout = QVBoxLayout(central_widget)
        
        # 标题
        title_label = QLabel("📐 数学公式查询系统")
        title_label.setStyleSheet("""
            QLabel {
                font-size: 24px;
                font-weight: bold;
                color: #2c3e50;
                padding: 20px;
                qproperty-alignment: AlignCenter;
            }
        """)
        main_layout.addWidget(title_label)
        
        # 创建标签页
        self.tabs = QTabWidget()
        self.tabs.setStyleSheet("""
            QTabWidget::pane {
                border: 1px solid #bdc3c7;
                border-radius: 4px;
            }
            QTabBar::tab {
                background: #ecf0f1;
                padding: 8px 16px;
                margin-right: 2px;
                border: 1px solid #bdc3c7;
                border-bottom: none;
                border-top-left-radius: 4px;
                border-top-right-radius: 4px;
            }
            QTabBar::tab:selected {
                background: #3498db;
                color: white;
            }
            QTabBar::tab:hover {
                background: #d6dbdf;
            }
        """)
        
        # 公式浏览器标签页
        self.browser = FormulaBrowser(self.db)
        self.tabs.addTab(self.browser, "🔍 浏览查询")
        
        # 计算器标签页
        self.calculator = CalculatorWidget()
        self.tabs.addTab(self.calculator, "🧮 公式计算")
        
        main_layout.addWidget(self.tabs)
        
        # 工具栏
        self.create_toolbar()
        
        # 状态栏
        self.statusBar().showMessage("就绪")
    
    def create_icon(self):
        """创建应用图标"""
        pixmap = QPixmap(32, 32)
        pixmap.fill(Qt.transparent)
        painter = QPainter(pixmap)
        painter.setRenderHint(QPainter.Antialiasing)
        
        # 绘制一个简单的数学图标
        painter.setBrush(QColor("#3498db"))
        painter.setPen(QPen(QColor("#2980b9"), 2))
        painter.drawEllipse(4, 4, 24, 24)
        
        painter.setPen(QPen(Qt.white, 3))
        painter.drawText(QRect(4, 4, 24, 24), Qt.AlignCenter, "∑")
        
        painter.end()
        return QIcon(pixmap)
    
    def create_toolbar(self):
        """创建工具栏"""
        toolbar = self.addToolBar("工具")
        
        # 添加公式动作
        add_action = QAction("➕ 添加公式", self)
        add_action.triggered.connect(self.add_formula)
        toolbar.addAction(add_action)
        
        # 刷新动作
        refresh_action = QAction("🔄 刷新", self)
        refresh_action.triggered.connect(self.refresh)
        toolbar.addAction(refresh_action)
        
        toolbar.addSeparator()
        
        # 统计信息动作
        stats_action = QAction("📊 统计", self)
        stats_action.triggered.connect(self.show_stats)
        toolbar.addAction(stats_action)
        
        # 关于动作
        about_action = QAction("ℹ️ 关于", self)
        about_action.triggered.connect(self.show_about)
        toolbar.addAction(about_action)
    
    def add_formula(self):
        """添加公式"""
        dialog = AddFormulaDialog(self.db, self)
        if dialog.exec_():
            data = dialog.get_data()
            
            if not all([data['category'], data['name'], data['formula']]):
                QMessageBox.warning(self, "警告", "请填写必填字段！")
                return
            
            if self.db.add_formula(data['category'], data['name'], 
                                  data['formula'], data['description'], data['example']):
                QMessageBox.information(self, "成功", "公式添加成功！")
                self.browser.load_categories()
                self.statusBar().showMessage("公式添加成功")
            else:
                QMessageBox.warning(self, "警告", "公式已存在！")
    
    def refresh(self):
        """刷新数据"""
        self.db.formulas = self.db._load_formulas()
        self.browser.load_categories()
        self.statusBar().showMessage("数据已刷新")
    
    def show_stats(self):
        """显示统计信息"""
        categories = self.db.get_categories()
        total_formulas = 0
        
        stats_text = "📊 数据库统计信息\n"
        stats_text += "=" * 30 + "\n"
        
        for category in categories:
            formulas = self.db.get_formulas_by_category(category)
            count = len(formulas)
            total_formulas += count
            stats_text += f"📁 {category}: {count} 个公式\n"
        
        stats_text += "=" * 30 + "\n"
        stats_text += f"📈 总计: {len(categories)} 个类别, {total_formulas} 个公式"
        
        QMessageBox.information(self, "统计信息", stats_text)
    
    def show_about(self):
        """显示关于信息"""
        about_text = """<h2>数学公式查询系统</h2>
        <p><b>版本:</b> 2.0 (GUI版)</p>
        <p><b>功能:</b></p>
        <ul>
            <li>🔍 公式查询和浏览</li>
            <li>🧮 基本公式计算</li>
            <li>➕ 添加自定义公式</li>
            <li>📁 分类管理公式</li>
        </ul>
        <p>欢迎使用数学公式查询系统！</p>"""
        
        QMessageBox.about(self, "关于", about_text)


def main():
    app = QApplication(sys.argv)
    
    # 设置应用样式
    app.setStyle("Fusion")
    
    # 设置调色板
    palette = QPalette()
    palette.setColor(QPalette.Window, QColor(240, 245, 248))
    palette.setColor(QPalette.WindowText, QColor(44, 62, 80))
    palette.setColor(QPalette.Base, QColor(255, 255, 255))
    palette.setColor(QPalette.AlternateBase, QColor(233, 236, 239))
    palette.setColor(QPalette.ToolTipBase, QColor(255, 255, 255))
    palette.setColor(QPalette.ToolTipText, QColor(44, 62, 80))
    palette.setColor(QPalette.Text, QColor(44, 62, 80))
    palette.setColor(QPalette.Button, QColor(52, 152, 219))
    palette.setColor(QPalette.ButtonText, QColor(255, 255, 255))
    palette.setColor(QPalette.BrightText, Qt.red)
    palette.setColor(QPalette.Highlight, QColor(41, 128, 185))
    palette.setColor(QPalette.HighlightedText, Qt.white)
    app.setPalette(palette)
    
    # 创建主窗口
    window = MainWindow()
    window.show()
    
    sys.exit(app.exec_())


if __name__ == "__main__":
    main()