import sqlite3
import math
from PySide6.QtWidgets import (
    QApplication, QMainWindow, QPushButton, QLabel, QVBoxLayout,
    QWidget, QTableWidget, QTableWidgetItem, QLineEdit, QFormLayout,
    QDialog, QFileDialog, QMessageBox, QComboBox, QHBoxLayout
)
from PySide6.QtCore import Qt
from reportlab.lib.pagesizes import letter
from reportlab.pdfgen import canvas


class ModernMainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("مدیریت هزینه‌های کافی شاپ")
        self.setGeometry(100, 100, 800, 600)
        self.setStyleSheet("background-color: #2E2E2E; color: white; font-family: B Nazanin;")

        # Main layout
        main_widget = QWidget()
        self.setCentralWidget(main_widget)
        layout = QVBoxLayout(main_widget)

        # Title label
        title_label = QLabel("مدیریت کافی‌شاپ")
        title_label.setStyleSheet("font-size: 24px; font-weight: bold; color: Gold;")
        title_label.setAlignment(Qt.AlignCenter)
        layout.addWidget(title_label)

        # Buttons
        btn_materials = self.create_styled_button("مواد اولیه")
        btn_materials.clicked.connect(self.manage_materials)
        layout.addWidget(btn_materials)

        btn_recipes = self.create_styled_button("رسپی‌ها")
        btn_recipes.clicked.connect(self.manage_recipes)
        layout.addWidget(btn_recipes)

        btn_menu = self.create_styled_button("نمایش منو")
        btn_menu.clicked.connect(self.show_menu)
        layout.addWidget(btn_menu)

        # Footer
        footer_label = QLabel("Made By LoGiT3X with 🧡")
        footer_label.setStyleSheet("font-size: 12px; font-weight: bold; color: #f024b3;")
        footer_label.setAlignment(Qt.AlignCenter)
        layout.addWidget(footer_label)

    def create_styled_button(self, text):
        """Create a styled button with rounded corners and hover effects."""
        button = QPushButton(text)
        button.setStyleSheet("""
            QPushButton {
                background-color: #0786b0;
                color: black;
                border: 2px solid #fcd40d;
                border-radius: 25px;
                font-size: 20px;
                padding: 10px;
                text-align: center;
            }
            QPushButton:hover {
                background-color: #17627a;
                border-color: fcd40d;
            }
            QPushButton:pressed {
                background-color: #fcd40d;
                border-color: #FF0000;
            }
        """)
        return button

    def manage_materials(self):
        """Open the materials management window."""
        dialog = MaterialsDialog(self)
        dialog.exec()

    def manage_recipes(self):
        """Open the recipes management window."""
        dialog = RecipesDialog(self)
        dialog.exec()

    def show_menu(self):
        """Open the menu display window."""
        dialog = MenuDialog(self)
        dialog.exec()


class MaterialsDialog(QDialog):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.setWindowTitle("مدیریت مواد اولیه")
        self.setStyleSheet("background-color: #2E2E2E; color: white; font-family: B Nazanin;")
        self.setGeometry(100, 100, 600, 400)

        layout = QVBoxLayout(self)

        # Table
        self.table = QTableWidget()
        self.table.setColumnCount(2)
        self.table.setHorizontalHeaderLabels(["نام مواد", "قیمت هر گرم"])
        self.refresh_materials()
        layout.addWidget(self.table)

        # Add form
        form_layout = QFormLayout()
        self.name_input = QLineEdit()
        self.price_input = QLineEdit()
        form_layout.addRow("نام:", self.name_input)
        form_layout.addRow("قیمت هر گرم:", self.price_input)

        add_button = QPushButton("اضافه کردن")
        add_button.clicked.connect(self.add_material)
        form_layout.addWidget(add_button)

        layout.addLayout(form_layout)

    def refresh_materials(self):
        """Refresh the materials table."""
        conn = sqlite3.connect("coffee_shop.db")
        cursor = conn.cursor()
        cursor.execute("SELECT name, price_per_gram FROM materials")
        materials = cursor.fetchall()
        conn.close()

        self.table.setRowCount(len(materials))
        for row, material in enumerate(materials):
            self.table.setItem(row, 0, QTableWidgetItem(material[0]))
            self.table.setItem(row, 1, QTableWidgetItem(str(material[1])))

    def add_material(self):
        """Add a new material."""
        name = self.name_input.text()
        price = self.price_input.text()

        if not name or not price:
            QMessageBox.warning(self, "خطا", "تمام فیلدها را پر کنید.")
            return

        try:
            price = float(price)
        except ValueError:
            QMessageBox.warning(self, "خطا", "قیمت باید عدد باشد.")
            return

        conn = sqlite3.connect("coffee_shop.db")
        cursor = conn.cursor()
        try:
            cursor.execute("INSERT INTO materials (name, price_per_gram) VALUES (?, ?)", (name, price))
            conn.commit()
        except sqlite3.IntegrityError:
            QMessageBox.warning(self, "خطا", "این ماده قبلاً ثبت شده است.")
        finally:
            conn.close()

        self.refresh_materials()
        self.name_input.clear()
        self.price_input.clear()


class RecipesDialog(QDialog):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.setWindowTitle("مدیریت رسپی‌ها")
        self.setStyleSheet("background-color: #2E2E2E; color: white; font-family: B Nazanin;")
        self.setGeometry(100, 100, 800, 500)

        layout = QVBoxLayout(self)

        # Table
        self.table = QTableWidget()
        self.table.setColumnCount(2)
        self.table.setHorizontalHeaderLabels(["نام رسپی", "تعداد مواد اولیه"])
        self.refresh_recipes()
        layout.addWidget(self.table)

        # Buttons
        button_layout = QHBoxLayout()
        add_button = QPushButton("اضافه کردن رسپی")
        add_button.clicked.connect(self.add_recipe)
        button_layout.addWidget(add_button)

        edit_button = QPushButton("ویرایش رسپی")
        edit_button.clicked.connect(self.edit_recipe)
        button_layout.addWidget(edit_button)

        delete_button = QPushButton("حذف رسپی")
        delete_button.clicked.connect(self.delete_recipe)
        button_layout.addWidget(delete_button)

        layout.addLayout(button_layout)

    def refresh_recipes(self):
        """Fetch recipes and display them in the table."""
        conn = sqlite3.connect("coffee_shop.db")
        cursor = conn.cursor()
        cursor.execute("""
            SELECT r.id, r.name, COUNT(rd.material_id) 
            FROM recipes r
            LEFT JOIN recipe_details rd ON r.id = rd.recipe_id
            GROUP BY r.id
        """)
        recipes = cursor.fetchall()
        conn.close()

        self.table.setRowCount(len(recipes))
        for row, (recipe_id, name, material_count) in enumerate(recipes):
            self.table.setItem(row, 0, QTableWidgetItem(name))
            self.table.setItem(row, 1, QTableWidgetItem(str(material_count)))

    def add_recipe(self):
        """Open a dialog to add a new recipe."""
        dialog = RecipeEditDialog(self)
        dialog.exec()
        self.refresh_recipes()

    def edit_recipe(self):
        """Open a dialog to edit the selected recipe."""
        selected_row = self.table.currentRow()
        if selected_row == -1:
            QMessageBox.warning(self, "خطا", "لطفاً یک رسپی را انتخاب کنید.")
            return

        recipe_name = self.table.item(selected_row, 0).text()
        dialog = RecipeEditDialog(self, recipe_name)
        dialog.exec()
        self.refresh_recipes()

    def delete_recipe(self):
        """Delete the selected recipe."""
        selected_row = self.table.currentRow()
        if selected_row == -1:
            QMessageBox.warning(self, "خطا", "لطفاً یک رسپی را انتخاب کنید.")
            return

        recipe_name = self.table.item(selected_row, 0).text()
        confirm = QMessageBox.question(
            self, "حذف رسپی", f"آیا مطمئن هستید که می‌خواهید رسپی '{recipe_name}' را حذف کنید؟",
            QMessageBox.Yes | QMessageBox.No
        )
        if confirm == QMessageBox.Yes:
            conn = sqlite3.connect("coffee_shop.db")
            cursor = conn.cursor()
            cursor.execute("DELETE FROM recipes WHERE name = ?", (recipe_name,))
            cursor.execute("DELETE FROM recipe_details WHERE recipe_id = (SELECT id FROM recipes WHERE name = ?)",
                           (recipe_name,))
            conn.commit()
            conn.close()
            self.refresh_recipes()


class RecipeEditDialog(QDialog):
    def __init__(self, parent=None, recipe_name=None):
        super().__init__(parent)
        self.recipe_name = recipe_name
        self.setWindowTitle("ویرایش رسپی" if recipe_name else "اضافه کردن رسپی")
        self.setStyleSheet("background-color: #2E2E2E; color: white; font-family: B Nazanin;")
        self.setGeometry(100, 100, 600, 400)

        layout = QVBoxLayout(self)

        # Recipe name
        self.name_input = QLineEdit()
        if recipe_name:
            self.name_input.setText(recipe_name)
        layout.addWidget(QLabel("نام رسپی:"))
        layout.addWidget(self.name_input)

        # Materials table
        self.table = QTableWidget()
        self.table.setColumnCount(2)
        self.table.setHorizontalHeaderLabels(["مواد اولیه", "مقدار (گرم)"])
        layout.addWidget(self.table)

        # Add material
        form_layout = QFormLayout()
        self.material_combo = QComboBox()
        self.material_combo.addItems(self.get_material_names())
        self.quantity_input = QLineEdit()
        form_layout.addRow("مواد اولیه:", self.material_combo)
        form_layout.addRow("مقدار (گرم):", self.quantity_input)

        add_material_button = QPushButton("اضافه کردن ماده")
        add_material_button.clicked.connect(self.add_material)
        form_layout.addWidget(add_material_button)
        layout.addLayout(form_layout)

        # Save button
        save_button = QPushButton("ذخیره رسپی")
        save_button.clicked.connect(self.save_recipe)
        layout.addWidget(save_button)

        if recipe_name:
            self.load_recipe()

    def get_material_names(self):
        """Get all material names from the database."""
        conn = sqlite3.connect("coffee_shop.db")
        cursor = conn.cursor()
        cursor.execute("SELECT name FROM materials")
        materials = [row[0] for row in cursor.fetchall()]
        conn.close()
        return materials

    def load_recipe(self):
        """Load the selected recipe details."""
        conn = sqlite3.connect("coffee_shop.db")
        cursor = conn.cursor()
        cursor.execute("""
            SELECT m.name, rd.quantity
            FROM recipe_details rd
            JOIN materials m ON rd.material_id = m.id
            WHERE rd.recipe_id = (SELECT id FROM recipes WHERE name = ?)
        """, (self.recipe_name,))
        materials = cursor.fetchall()
        conn.close()

        self.table.setRowCount(len(materials))
        for row, (material_name, quantity) in enumerate(materials):
            self.table.setItem(row, 0, QTableWidgetItem(material_name))
            self.table.setItem(row, 1, QTableWidgetItem(str(quantity)))

    def add_material(self):
        """Add a material to the recipe."""
        material_name = self.material_combo.currentText()
        quantity = self.quantity_input.text()
        if not quantity:
            QMessageBox.warning(self, "خطا", "لطفاً مقدار را وارد کنید.")
            return

        try:
            quantity = float(quantity)
        except ValueError:
            QMessageBox.warning(self, "خطا", "مقدار باید عدد باشد.")
            return

        current_row_count = self.table.rowCount()
        self.table.insertRow(current_row_count)
        self.table.setItem(current_row_count, 0, QTableWidgetItem(material_name))
        self.table.setItem(current_row_count, 1, QTableWidgetItem(str(quantity)))

    def save_recipe(self):
        """Save the recipe to the database."""
        recipe_name = self.name_input.text()
        if not recipe_name:
            QMessageBox.warning(self, "خطا", "لطفاً نام رسپی را وارد کنید.")
            return

        materials = []
        for row in range(self.table.rowCount()):
            material_name = self.table.item(row, 0).text()
            quantity = self.table.item(row, 1).text()
            try:
                quantity = float(quantity)
                materials.append((material_name, quantity))
            except ValueError:
                QMessageBox.warning(self, "خطا", f"مقدار برای '{material_name}' نامعتبر است.")
                return

        conn = sqlite3.connect("coffee_shop.db")
        cursor = conn.cursor()

        if self.recipe_name:  # Update existing recipe
            cursor.execute("UPDATE recipes SET name = ? WHERE name = ?", (recipe_name, self.recipe_name))
            cursor.execute("DELETE FROM recipe_details WHERE recipe_id = (SELECT id FROM recipes WHERE name = ?)",
                           (recipe_name,))
        else:  # Insert new recipe
            cursor.execute("INSERT INTO recipes (name) VALUES (?)", (recipe_name,))
        recipe_id = cursor.execute("SELECT id FROM recipes WHERE name = ?", (recipe_name,)).fetchone()[0]

        for material_name, quantity in materials:
            material_id = cursor.execute("SELECT id FROM materials WHERE name = ?", (material_name,)).fetchone()[0]
            cursor.execute("INSERT INTO recipe_details (recipe_id, material_id, quantity) VALUES (?, ?, ?)",
                           (recipe_id, material_id, quantity))

        conn.commit()
        conn.close()
        QMessageBox.information(self, "موفقیت", "رسپی با موفقیت ذخیره شد.")
        self.accept()


class MenuDialog(QDialog):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.setWindowTitle("نمایش منو")
        self.setStyleSheet("background-color: #2E2E2E; color: white; font-family: B Nazanin;")
        self.setGeometry(100, 100, 800, 500)

        layout = QVBoxLayout(self)

        # Table
        self.table = QTableWidget()
        self.table.setColumnCount(2)
        self.table.setHorizontalHeaderLabels(["نام محصول", "قیمت نهایی (تومان)"])
        self.refresh_menu()
        layout.addWidget(self.table)

        # Export button
        export_button = QPushButton("ذخیره به PDF")
        export_button.clicked.connect(self.export_to_pdf)
        layout.addWidget(export_button)

    def refresh_menu(self):
        """Fetch menu items and display them in the table."""
        prices = self.calculate_prices()
        self.table.setRowCount(len(prices))
        for row, (name, final_price) in enumerate(prices):
            self.table.setItem(row, 0, QTableWidgetItem(name))
            self.table.setItem(row, 1, QTableWidgetItem(str(final_price)))

    def calculate_prices(self):
        """Calculate prices for each recipe."""
        conn = sqlite3.connect("coffee_shop.db")
        cursor = conn.cursor()
        cursor.execute("""
            SELECT r.name, 
                   SUM(rd.quantity * m.price_per_gram) AS raw_price
            FROM recipes r
            JOIN recipe_details rd ON r.id = rd.recipe_id
            JOIN materials m ON rd.material_id = m.id
            GROUP BY r.id
        """)
        data = cursor.fetchall()
        conn.close()

        prices = []
        for name, raw_price in data:
            if raw_price is None:
                continue
            raw_price = round(raw_price, 2)
            selling_price = round(raw_price * 3.3, 2)
            price_with_tax = round(selling_price * 1.1, 2)
            final_price = math.ceil(price_with_tax)
            prices.append((name, final_price))
        return prices

    def export_to_pdf(self):
        """Export the menu to a PDF file."""
        file_path, _ = QFileDialog.getSaveFileName(self, "ذخیره فایل", filter="PDF Files (*.pdf)")
        if not file_path:
            return

        prices = self.calculate_prices()
        if not prices:
            QMessageBox.warning(self, "خطا", "هیچ محصولی برای ذخیره وجود ندارد.")
            return

        try:
            c = canvas.Canvas(file_path, pagesize=letter)
            c.setFont("Helvetica", 12)
            c.drawString(30, 750, "گزارش منوی کافی‌شاپ")
            y = 730
            for name, final_price in prices:
                c.drawString(30, y, f"{name}: {final_price} تومان")
                y -= 20
                if y < 50:  # Create a new page if the content exceeds one page
                    c.showPage()
                    c.setFont("Helvetica", 12)
                    y = 750
            c.save()
            QMessageBox.information(self, "موفقیت", "منو با موفقیت به PDF ذخیره شد.")
        except Exception as e:
            QMessageBox.critical(self, "خطا", f"خطایی رخ داد: {str(e)}")


if __name__ == "__main__":
    # Initialize SQLite database
    def init_db():
        conn = sqlite3.connect("coffee_shop.db")
        cursor = conn.cursor()
        cursor.execute("""
            CREATE TABLE IF NOT EXISTS materials (
                id INTEGER PRIMARY KEY,
                name TEXT UNIQUE NOT NULL,
                price_per_gram REAL NOT NULL
            )
        """)
        cursor.execute("""
            CREATE TABLE IF NOT EXISTS recipes (
                id INTEGER PRIMARY KEY,
                name TEXT UNIQUE NOT NULL
            )
        """)
        cursor.execute("""
            CREATE TABLE IF NOT EXISTS recipe_details (
                recipe_id INTEGER NOT NULL,
                material_id INTEGER NOT NULL,
                quantity REAL NOT NULL,
                FOREIGN KEY(recipe_id) REFERENCES recipes(id),
                FOREIGN KEY(material_id) REFERENCES materials(id)
            )
        """)
        conn.commit()
        conn.close()

    init_db()

    app = QApplication([])
    window = ModernMainWindow()
    window.show()
    app.exec() 

به بخش نمایش منو ویژگیهای زیر رو اضافه کن:

قیمت اولیه : قیمت خام مجموع مواد اولیه
قیمت ثانویه : قیمت اولیه ضربدر 3.3
قیمت : قیمت ثانویه + 10% مالیات

همچنین جداول و صفحات جدید برنامه رو زیباتر و خواناتر کن
و در انتها کل کد رو با این تغییرات بهم بده
و مطمئن شو همه ی بخش های برنامه سالم کار کنند