import sys
import requests
import threading
import pygame
import pyttsx3
from PyQt5.QtWidgets import QApplication, QMainWindow, QWidget, QVBoxLayout, QLineEdit, QPushButton, QLabel
from PyQt5.QtGui import QPalette, QColor, QFont
from PyQt5.QtCore import Qt

class CartoonWeatherApp(QMainWindow):
    def __init__(self):
        super().__init__()
        
        # 1. 窗口基础设置
        self.setWindowTitle("🌈 卡通天气小助手")
        self.setFixedSize(800, 600)
        
        # 2. 设置浅粉到浅蓝的渐变色背景
        palette = QPalette()
        gradient = QColor(255, 182, 193)  # 浅粉色 (LightPink)
        gradient2 = QColor(173, 216, 230) # 浅蓝色 (LightBlue)
        palette.setColor(QPalette.Window, gradient)
        palette.setColor(QPalette.AlternateBase, gradient2)
        self.setPalette(palette)
        
        # 3. 初始化核心组件 (语音引擎和音效)
        self.init_audio()
        
        # 4. 界面布局
        central_widget = QWidget()
        self.setCentralWidget(central_widget)
        layout = QVBoxLayout(central_widget)
        layout.setSpacing(20)
        layout.setContentsMargins(50, 50, 50, 50)
        
        # 标题
        self.title_label = QLabel("🌤️ 我的天气小助手")
        self.title_label.setFont(QFont("Microsoft YaHei", 36, QFont.Bold))
        self.title_label.setAlignment(Qt.AlignCenter)
        self.title_label.setStyleSheet("color: #333; background: transparent;")
        layout.addWidget(self.title_label)
        
        # 输入框
        self.entry = QLineEdit()
        self.entry.setPlaceholderText("输入城市名 (如: Beijing)")
        self.entry.setFont(QFont("Microsoft YaHei", 20))
        self.entry.setStyleSheet("""
            QLineEdit {
                padding: 10px; border-radius: 15px; border: 2px solid #FFB6C1;
                background: rgba(255, 255, 255, 0.8); color: #333;
            }
            QLineEdit:focus { border: 2px solid #87CEFA; }
        """)
        layout.addWidget(self.entry)
        
        # 查询按钮
        self.btn = QPushButton("✨ 查询天气")
        self.btn.setFont(QFont("Microsoft YaHei", 20, QFont.Bold))
        self.btn.setStyleSheet("""
            QPushButton {
                background-color: #FFB6C1; color: white; border-radius: 15px; padding: 10px;
            }
            QPushButton:hover { background-color: #87CEFA; }
        """)
        self.btn.clicked.connect(self.on_button_click)
        layout.addWidget(self.btn)
        
        # 结果展示
        self.result_label = QLabel("等待查询中...")
        self.result_label.setFont(QFont("Microsoft YaHei", 24))
        self.result_label.setAlignment(Qt.AlignCenter)
        self.result_label.setStyleSheet("color: #333; background: transparent;")
        self.result_label.setWordWrap(True)
        layout.addWidget(self.result_label)
        
        # 动画 Emoji 展示
        self.animation_label = QLabel("")
        self.animation_label.setFont(QFont("Segoe UI Emoji", 80))
        self.animation_label.setAlignment(Qt.AlignCenter)
        self.animation_label.setStyleSheet("background: transparent;")
        layout.addWidget(self.animation_label)

    def init_audio(self):
        """初始化 Pygame 音效和 Pyttsx3 语音引擎"""
        try:
            pygame.mixer.init()
            # 注意：请确保同级目录下有一个名为 'click.wav' 的音效文件
            self.click_sound = pygame.mixer.Sound("click.wav") 
        except Exception as e:
            print(f"音效初始化失败(可忽略): {e}")
            self.click_sound = None
            
        try:
            self.tts_engine = pyttsx3.init()
            self.tts_engine.setProperty('rate', 150)
        except Exception as e:
            print(f"语音引擎初始化失败: {e}")
            self.tts_engine = None

    def play_click_sound(self):
        """在子线程中播放按钮音效，防止界面卡顿"""
        if self.click_sound:
            self.click_sound.play()

    def speak_weather(self, text):
        """在子线程中播报天气"""
        if self.tts_engine:
            try:
                self.tts_engine.say(text)
                self.tts_engine.runAndWait()
            except Exception as e:
                print(f"播报失败: {e}")

    def on_button_click(self):
        """按钮点击事件"""
        # 播放音效
        threading.Thread(target=self.play_click_sound, daemon=True).start()
        
        # 执行查询
        self.btn.setEnabled(False)
        self.btn.setText("查询中...")
        self.result_label.setText("正在呼叫天气精灵...")
        thread = threading.Thread(target=self.get_weather)
        thread.start()

    def get_weather(self):
        city = self.entry.text().strip()
        if not city:
            self.update_ui("请输入城市名哦！", None, None)
            return
            
        try:
            url = f"http://wttr.in/{city}?format=j1"
            response = requests.get(url, timeout=10)
            data = response.json()
            
            current = data["current_condition"][0]
            temp = current["temp_C"]
            desc = current["weatherDesc"][0]["value"]
            humidity = current["humidity"]
            
            result_text = f"🏙️ {city} | 🌡️ {temp}°C | 💧 {humidity}%\n{desc}"
            
            # 匹配 Emoji
            weather_emoji = "🌤️"
            desc_lower = desc.lower()
            if "rain" in desc_lower or "drizzle" in desc_lower: weather_emoji = "🌧️"
            elif "snow" in desc_lower: weather_emoji = "❄️"
            elif "clear" in desc_lower: weather_emoji = "☀️"
            elif "cloud" in desc_lower: weather_emoji = "☁️"
                
            # 构造语音播报文本
            speak_text = f"为您播报{city}的天气，当前温度{temp}摄氏度，{desc}，湿度{humidity}%"
            
            self.update_ui(result_text, weather_emoji, speak_text)
            
        except Exception as e:
            self.update_ui(f"哎呀，查询失败了: {e}", None, None)

    def update_ui(self, text, emoji, speak_text):
        """在主线程中安全地更新UI"""
        self.result_label.setText(text)
        self.animation_label.setText(emoji if emoji else "")
        self.btn.setEnabled(True)
        self.btn.setText("✨ 查询天气")
        
        # 触发语音播报
        if speak_text:
            threading.Thread(target=self.speak_weather, args=(speak_text,), daemon=True).start()

if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = CartoonWeatherApp()
    window.show()
    sys.exit(app.exec_())