import subprocess
import psutil
import os
import sys
import socket
import time
import json
from loguru import logger
from PySide6.QtWidgets import (QApplication, QMainWindow, QPushButton, QMessageBox,
                               QVBoxLayout, QWidget, QLabel, QGroupBox, QGridLayout,
                               QStatusBar, QFrame, QDialog, QLineEdit, QFormLayout,
                               QDialogButtonBox, QFileDialog, QHBoxLayout)
from PySide6.QtCore import Qt, QThread, Signal
from PySide6.QtGui import QFont

logger.remove()
APP_DIR = os.path.dirname(os.path.abspath(sys.executable if getattr(sys, 'frozen', False) else __file__))
log_file = os.path.join(APP_DIR, "push_screen.log")
logger.add(log_file, format="{time:YYYY-MM-DD HH:mm:ss} | {level} | {message}", level="INFO", encoding="utf-8")

CONFIG_FILE = os.path.join(APP_DIR, "config.json")

def load_config():
    if os.path.exists(CONFIG_FILE):
        with open(CONFIG_FILE, 'r', encoding='utf-8') as f:
            return json.load(f)
    return {
        "server_ip": "192.168.1.100",
        "ffmpeg_path": r"D:\ScreenCast\ffmpeg\bin\ffmpeg.exe",
        "stream_path": "screen"
    }

def save_config(config):
    with open(CONFIG_FILE, 'w', encoding='utf-8') as f:
        json.dump(config, f, ensure_ascii=False, indent=4)
    logger.info(f"配置已保存到 {CONFIG_FILE}")

class ConfigDialog(QDialog):
    def __init__(self, config, parent=None):
        super().__init__(parent)
        self.config = config
        self.setWindowTitle("设置")
        self.setFixedSize(450, 180)

        layout = QFormLayout(self)

        self.server_ip_edit = QLineEdit(config["server_ip"])
        self.ffmpeg_path_edit = QLineEdit(config["ffmpeg_path"])
        self.stream_path_edit = QLineEdit(config["stream_path"])

        self.ffmpeg_btn = QPushButton("浏览...")
        self.ffmpeg_btn.clicked.connect(lambda: self.browse("ffmpeg"))

        path_layout1 = QGridLayout()
        path_layout1.addWidget(self.ffmpeg_path_edit, 0, 0)
        path_layout1.addWidget(self.ffmpeg_btn, 0, 1)

        layout.addRow("服务器IP:", self.server_ip_edit)
        layout.addRow("FFmpeg路径:", self.ffmpeg_path_edit)
        layout.addRow("推流路径:", self.stream_path_edit)

        buttons = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
        buttons.accepted.connect(self.accept)
        buttons.rejected.connect(self.reject)
        layout.addRow(buttons)

    def browse(self, field):
        if field == "ffmpeg":
            path = QFileDialog.getOpenFileName(self, "选择FFmpeg", "", "Executable (*.exe)")[0]
            if path:
                self.ffmpeg_path_edit.setText(path)

    def get_config(self):
        return {
            "server_ip": self.server_ip_edit.text().strip(),
            "ffmpeg_path": self.ffmpeg_path_edit.text().strip(),
            "stream_path": self.stream_path_edit.text().strip()
        }

class ConnectionChecker(QThread):
    status_update = Signal(dict)

    def run(self):
        while True:
            cfg = self.config
            status = {
                "ffmpeg": self.check_ffmpeg(cfg["ffmpeg_path"]),
                "server": self.check_server(cfg["server_ip"]),
                "server_port": self.check_port(cfg["server_ip"], 8554),
            }
            self.status_update.emit(status)
            time.sleep(3)

    def set_config(self, config):
        self.config = config

    def check_ffmpeg(self, path):
        return os.path.exists(path)

    def check_server(self, ip):
        try:
            socket.create_connection((ip, 8554), timeout=2)
            return True
        except:
            return False

    def check_port(self, ip, port):
        try:
            sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            sock.settimeout(2)
            result = sock.connect_ex((ip, port))
            sock.close()
            return result == 0
        except:
            return False

class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.config = load_config()
        self.setWindowTitle("投屏源控制")
        self.setFixedSize(520, 420)

        self.status_bar = QStatusBar()
        self.setStatusBar(self.status_bar)

        central_widget = QWidget()
        self.setCentralWidget(central_widget)
        main_layout = QVBoxLayout(central_widget)

        title_layout = QHBoxLayout()
        title_layout.addStretch()
        self.btn_settings = QPushButton("⚙ 设置")
        self.btn_settings.setFixedSize(70, 30)
        self.btn_settings.clicked.connect(self.open_settings)
        title_layout.addWidget(self.btn_settings)

        title_label = QLabel("会议投屏系统 - 主播端")
        title_font = QFont("Microsoft YaHei", 14, QFont.Bold)
        title_label.setFont(title_font)
        title_label.setAlignment(Qt.AlignCenter)
        
        title_main_layout = QVBoxLayout()
        title_main_layout.addLayout(title_layout)
        title_main_layout.addWidget(title_label)
        main_layout.addLayout(title_main_layout)

        config_group = QGroupBox("本地配置")
        config_layout = QGridLayout()

        self.ffmpeg_label = QLabel("FFmpeg: 未检测")
        self.server_label = QLabel("服务器连接: 未检测")
        self.port_label = QLabel("RTSP端口: 未检测")

        self.ffmpeg_indicator = QLabel("●")
        self.ffmpeg_indicator.setFixedWidth(20)
        self.server_indicator = QLabel("●")
        self.server_indicator.setFixedWidth(20)
        self.port_indicator = QLabel("●")
        self.port_indicator.setFixedWidth(20)

        config_layout.addWidget(self.ffmpeg_indicator, 0, 0)
        config_layout.addWidget(self.ffmpeg_label, 0, 1)
        config_layout.addWidget(self.server_indicator, 1, 0)
        config_layout.addWidget(self.server_label, 1, 1)
        config_layout.addWidget(self.port_indicator, 2, 0)
        config_layout.addWidget(self.port_label, 2, 1)

        config_group.setLayout(config_layout)
        main_layout.addWidget(config_group)

        self.info_group = QGroupBox("流信息")
        self.update_info_group()
        main_layout.addWidget(self.info_group)

        self.btn_push = QPushButton("🎬 开始全屏投屏")
        self.btn_push.setFixedHeight(50)
        self.btn_push.setFont(QFont("Microsoft YaHei", 11))
        self.btn_push.setStyleSheet("""
            QPushButton {
                background-color: #2E7D32;
                color: white;
                border: none;
                border-radius: 8px;
                font-weight: bold;
            }
            QPushButton:hover {
                background-color: #388E3C;
            }
            QPushButton:pressed {
                background-color: #1B5E20;
            }
        """)
        self.btn_push.clicked.connect(self.push_full_screen)
        main_layout.addWidget(self.btn_push)

        self.log_label = QLabel("日志: 等待启动...")
        self.log_label.setWordWrap(True)
        self.log_label.setFrameShape(QFrame.Shape.StyledPanel)
        self.log_label.setFixedHeight(40)
        main_layout.addWidget(self.log_label)

        self.checker = ConnectionChecker()
        self.checker.set_config(self.config)
        self.checker.status_update.connect(self.update_status)
        self.checker.start()

        logger.info("投屏源控制界面已初始化")

    def update_info_group(self):
        cfg = self.config
        if self.info_group.layout():
            QWidget().setLayout(self.info_group.layout())
        info_layout = QGridLayout()
        info_layout.addWidget(QLabel("服务器IP:"), 0, 0)
        info_layout.addWidget(QLabel(cfg["server_ip"]), 0, 1)
        info_layout.addWidget(QLabel("推流地址:"), 1, 0)
        info_layout.addWidget(QLabel(f"rtsp://{cfg['server_ip']}:8554/{cfg['stream_path']}"), 1, 1)
        info_layout.addWidget(QLabel("访问地址:"), 2, 0)
        info_layout.addWidget(QLabel(f"http://{cfg['server_ip']}:8889/webrtc.html?src={cfg['stream_path']}"), 2, 1)
        self.info_group.setLayout(info_layout)

    def open_settings(self):
        dialog = ConfigDialog(self.config, self)
        if dialog.exec():
            self.config = dialog.get_config()
            save_config(self.config)
            self.checker.set_config(self.config)
            self.update_info_group()
            self.log_label.setText("日志: 配置已更新")

    def update_status(self, status):
        if status["ffmpeg"]:
            self.ffmpeg_indicator.setStyleSheet("color: green; font-size: 16px;")
            self.ffmpeg_label.setText("FFmpeg: ✓ 已安装")
        else:
            self.ffmpeg_indicator.setStyleSheet("color: red; font-size: 16px;")
            self.ffmpeg_label.setText("FFmpeg: ✗ 未找到")

        if status["server"]:
            self.server_indicator.setStyleSheet("color: green; font-size: 16px;")
            self.server_label.setText("服务器连接: ✓ 可连接")
        else:
            self.server_indicator.setStyleSheet("color: orange; font-size: 16px;")
            self.server_label.setText("服务器连接: ✗ 连接失败")

        if status["server_port"]:
            self.port_indicator.setStyleSheet("color: green; font-size: 16px;")
            self.port_label.setText("RTSP端口: ✓ 端口开放")
        else:
            self.port_indicator.setStyleSheet("color: orange; font-size: 16px;")
            self.port_label.setText("RTSP端口: ✗ 端口关闭")

    def push_full_screen(self):
        cfg = self.config
        logger.info("开始全屏投屏")

        if not os.path.exists(cfg["ffmpeg_path"]):
            logger.error("FFmpeg未安装")
            QMessageBox.warning(self, "错误", "FFmpeg未安装，请检查配置！")
            return

        cmd = [
            cfg["ffmpeg_path"],
            "-f", "gdigrab", "-framerate", "30", "-i", "desktop",
            "-c:v", "libx264", "-preset", "ultrafast", "-tune", "zerolatency",
            "-f", "rtsp", f"rtsp://{cfg['server_ip']}:8554/{cfg['stream_path']}"
        ]
        logger.info(f"执行FFmpeg命令: {' '.join(cmd)}")
        subprocess.Popen(cmd, creationflags=subprocess.CREATE_NEW_CONSOLE)
        logger.info("FFmpeg推流已启动")
        self.log_label.setText("日志: FFmpeg推流已启动，正在向服务器推送...")
        QMessageBox.information(self, "提示", f"全屏投屏已启动！\n\n接收端可打开浏览器访问：\nhttp://{cfg['server_ip']}:8889/webrtc.html?src={cfg['stream_path']}")

    def closeEvent(self, event):
        self.checker.terminate()
        event.accept()

if __name__ == "__main__":
    logger.info("应用程序启动")
    app = QApplication(sys.argv)
    app.setStyle("Fusion")
    window = MainWindow()
    window.show()
    sys.exit(app.exec())