import tkinter as tk
from tkinter import filedialog, messagebox, colorchooser
import qrcode
from PIL import Image, ImageDraw, ImageOps
import os
from reportlab.lib.pagesizes import A4
from reportlab.pdfgen import canvas
from reportlab.lib.utils import ImageReader
from io import BytesIO
import base64
from PIL import ImageFilter

class QRCodeGeneratorApp:
    def __init__(self, root):
        self.root = root
        self.root.title("Tạo QR Code Logo - Phiên bản miễn phí tạo @NhanNguyen - Zalo 0938.616.563")
        self.root.geometry("600x300")
        
        # Variables
        self.logo_path = None
        self.qr_content = tk.StringVar()
        self.qr_color_1 = "#ff0000"  # Color 1
        self.qr_color_2 = "#0000ff"  # Color 2
        self.output_format = tk.StringVar(value="PNG")
        
        # User Interface
        self.create_widgets()

    def create_widgets(self):
        padding = {'padx': 10, 'pady': 10}
        
        # Select logo
        btn_select_logo = tk.Button(self.root, text="Chọn Logo", command=self.select_logo)
        btn_select_logo.grid(row=0, column=0, sticky='w', **padding)
        
        self.lbl_logo = tk.Label(self.root, text="Không có logo được chọn")
        self.lbl_logo.grid(row=0, column=1, sticky='w', **padding)
        
        # Enter QR code content
        lbl_content = tk.Label(self.root, text="Nội dung QR Code:")
        lbl_content.grid(row=1, column=0, sticky='w', **padding)
        
        entry_content = tk.Entry(self.root, textvariable=self.qr_content, width=50)
        entry_content.grid(row=1, column=1, **padding)
        
        # Select QR code color 1 and 2
        btn_choose_color_1 = tk.Button(self.root, text="Chọn Màu QR Code 1", command=lambda: self.choose_color(1))
        btn_choose_color_2 = tk.Button(self.root, text="Chọn Màu QR Code 2", command=lambda: self.choose_color(2))
        btn_choose_color_1.grid(row=2, column=0, sticky='w', **padding)
        btn_choose_color_2.grid(row=2, column=1, sticky='w', **padding)
        
        self.lbl_color_1 = tk.Label(self.root, text="Màu QR 1: Đỏ", bg=self.qr_color_1, fg=self.get_contrast_color(self.qr_color_1), width=20)
        self.lbl_color_2 = tk.Label(self.root, text="Màu QR 2: Xanh", bg=self.qr_color_2, fg=self.get_contrast_color(self.qr_color_2), width=20)
        self.lbl_color_1.grid(row=3, column=0, sticky='w', **padding)
        self.lbl_color_2.grid(row=3, column=1, sticky='w', **padding)
        
        # Place export buttons closer together in the same row and column span
        btn_export_png = tk.Button(self.root, text="Xuất PNG", command=lambda: self.save_file("PNG"))
        btn_export_pdf = tk.Button(self.root, text="Xuất PDF", command=lambda: self.save_file("PDF"))

        # Adjust buttons to be in the same row and closer together
        btn_export_png.grid(row=4, column=0, sticky='w', padx=(5, 10), pady=2)
        btn_export_pdf.grid(row=4, column=1, sticky='w', padx=(100, 0), pady=2)

    def select_logo(self):
        file_path = filedialog.askopenfilename(title="Chọn Logo", filetypes=[("Image Files", "*.png *.jpg *.jpeg *.bmp")])
        if file_path:
            self.logo_path = file_path
            logo_name = os.path.basename(file_path)
            self.lbl_logo.config(text=logo_name)
        else:
            self.logo_path = None
            self.lbl_logo.config(text="Không có logo được chọn")
    
    def choose_color(self, color_num):
        color_code = colorchooser.askcolor(title="Chọn màu cho QR Code")
        if color_code:
            if color_num == 1:
                self.qr_color_1 = color_code[1]
                color_display = self.get_color_name(self.qr_color_1)
                self.lbl_color_1.config(text=f"Màu QR 1: {color_display}", bg=self.qr_color_1, fg=self.get_contrast_color(self.qr_color_1))
            elif color_num == 2:
                self.qr_color_2 = color_code[1]
                color_display = self.get_color_name(self.qr_color_2)
                self.lbl_color_2.config(text=f"Màu QR 2: {color_display}", bg=self.qr_color_2, fg=self.get_contrast_color(self.qr_color_2))
    
    def get_color_name(self, hex_color):
        return hex_color
    
    def get_contrast_color(self, hex_color):
        hex_color = hex_color.lstrip('#')
        r, g, b = tuple(int(hex_color[i:i+2], 16) for i in (0, 2, 4))
        brightness = (r*299 + g*587 + b*114) / 1000
        return 'white' if brightness < 128 else 'black'

    def save_file(self, output_format):
        content = self.qr_content.get()
        if not content:
            messagebox.showerror("Lỗi", "Vui lòng nhập nội dung cho QR Code.")
            return
        
        file_path = filedialog.asksaveasfilename(defaultextension=f".{output_format.lower()}",
                                                 filetypes=[(f"{output_format} files", f"*.{output_format.lower()}")],
                                                 title=f"Lưu QR Code dưới dạng {output_format}")
        if not file_path:
            return
        
        if output_format == "PNG":
            self.generate_qr_png(content, file_path)
        elif output_format == "PDF":
            self.generate_qr_pdf(content, file_path)
    
    def generate_qr_png(self, content, file_path):
        try:
            qr = qrcode.QRCode(
                error_correction=qrcode.constants.ERROR_CORRECT_H
            )
            qr.add_data(content)
            qr.make(fit=True)
            img = self.draw_rounded_qr(qr)

            if self.logo_path:
                logo = Image.open(self.logo_path)
                basewidth = int(img.size[0] / 4)
                wpercent = (basewidth / float(logo.size[0]))
                hsize = int((float(logo.size[1]) * float(wpercent)))
                logo = logo.resize((basewidth, hsize), Image.Resampling.LANCZOS)
                
                if logo.mode in ('RGBA', 'LA'):
                    img.paste(logo, ((img.size[0] - logo.size[0]) // 2,
                                     (img.size[1] - logo.size[1]) // 2), logo)
                else:
                    img.paste(logo, ((img.size[0] - logo.size[0]) // 2,
                                     (img.size[1] - logo.size[1]) // 2))
            
            img.save(file_path, dpi=(300, 300))  # Save at 300 DPI
            messagebox.showinfo("Thành công", f"QR Code đã được lưu tại:\n{file_path}")
        except Exception as e:
            messagebox.showerror("Lỗi", f"Không thể tạo QR Code PNG:\n{e}")

    def draw_rounded_qr(self, qr):
        # Prepare the image to draw rounded QR code
        size = qr.modules_count * 10
        img = Image.new("RGB", (size, size), "white")
        draw = ImageDraw.Draw(img)
        
        module_size = size // qr.modules_count
        
        # Draw the QR code with rounded corners and two-color scheme
        for row in range(qr.modules_count):
            for col in range(qr.modules_count):
                if qr.modules[row][col]:
                    # Use different colors for different regions (e.g., top-left is qr_color_1, bottom-right is qr_color_2)
                    fill_color = self.qr_color_1 if (row < qr.modules_count // 2) else self.qr_color_2
                    left_up = (col * module_size, row * module_size)
                    right_down = (left_up[0] + module_size, left_up[1] + module_size)
                    draw.rounded_rectangle([left_up, right_down], radius=module_size // 2, fill=fill_color)
        
        return img
    
    def generate_qr_pdf(self, content, file_path):
        # This can be left similar to your original code if PDF output does not require rounded corners
        pass

if __name__ == "__main__":
    root = tk.Tk()
    app = QRCodeGeneratorApp(root)
    root.mainloop()
có thể tùy chỉnh cho mã tạo ra nhiều mẫu QR khác nhau kiểu artis ko