import sys
import os
import cv2
import easyocr
import torch
import subprocess
from PyQt5.QtWidgets import QApplication, QWidget, QVBoxLayout, QLabel
from PyQt5.QtCore import Qt, QThread, pyqtSignal

def get_resource_path(relative_path):
    """获取打包后临时目录的绝对路径，确保无损访问封装资源"""
    if hasattr(sys, '_MEIPASS'):
        return os.path.join(sys._MEIPASS, relative_path)
    return os.path.join(os.path.abspath("."), relative_path)

class VideoOcrProcessor(QThread):
    update_status = pyqtSignal(str)

    def __init__(self, file_path):
        super().__init__()
        self.file_path = file_path
        self.keywords = ["新葡京", "019019", "娱乐城", "PG游戏", "麻将胡了", "寻宝黄金城", "招财"]

    def run(self):
        # 动态定位打包在 EXE 内部的 FFmpeg 和 AI 模型路径
        ffmpeg_bin = get_resource_path("ffmpeg.exe")
        ffprobe_bin = get_resource_path("ffprobe.exe")
        model_dir = get_resource_path("easyocr_models")

        # 硬件加速自动检测提醒
        has_cuda = torch.cuda.is_available()
        if has_cuda:
            self.update_status.emit("检测到支持 CUDA 的显卡，已自动开启 AI 显卡硬件加速喵！")
        else:
            self.update_status.emit("未检测到可用独立显卡，当前使用 CPU 运行（速度较慢）喵！")

        self.update_status.emit("正在初始化全包版 AI 文本识别引擎...")
        try:
            # 强制指定读取内部打包的模型文件夹，不再依赖用户电脑的网络下载
            reader = easyocr.Reader(['ch_sim', 'en'], model_storage_directory=model_dir, gpu=has_cuda)
        except Exception as e:
            self.update_status.emit(f"AI 引擎初始化失败: {str(e)}，请检查模型文件是否打包完整。")
            return

        self.update_status.emit("AI 引擎准备完毕，正在读取视频信息...")
        cap = cv2.VideoCapture(self.file_path)
        fps = cap.get(cv2.CAP_PROP_FPS)
        total_frames = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
        
        if fps == 0 or total_frames == 0:
            self.update_status.emit("错误：无法读取视频文件。")
            return

        duration = total_frames / fps
        self.update_status.emit(f"视频总时长: {int(duration)}秒，开始全自动字幕扫描...")

        step = int(fps * 2)
        if step == 0:
            step = 50
            
        ad_bins = [False] * (int(duration) + 1)
        curr_frame = 0
        
        while cap.isOpened():
            ret = cap.grab()
            if not ret:
                break
            
            curr_frame += 1
            if curr_frame % step == 0:
                ret, frame = cap.retrieve()
                if not ret:
                    continue
                    
                current_second = int(curr_frame / fps)
                frame_resize = cv2.resize(frame, (640, 360))
                results = reader.readtext(frame_resize, detail=0)
                detected_text = "".join(results).replace(" ", "")
                
                is_ad = any(keyword in detected_text for keyword in self.keywords)
                if is_ad:
                    if current_second < len(ad_bins):
                        ad_bins[current_second] = True
                        
            if curr_frame % (step * 2) == 0:
                progress = int((curr_frame / total_frames) * 100)
                self.update_status.emit(f"正在进行 OCR 文本扫描... 进度: {progress}%")

        cap.release()
        self.update_status.emit("扫描完成，正在计算并优化正片时间轴...")

        smoothed_ad = [False] * len(ad_bins)
        for i, is_ad in enumerate(ad_bins):
            if is_ad:
                for j in range(max(0, i - 4), min(len(ad_bins), i + 5)):
                    smoothed_ad[j] = True

        valid_segments = []
        start_time = None
        for i, is_ad in enumerate(smoothed_ad):
            if not is_ad:
                if start_time is None:
                    start_time = i
            else:
                if start_time is not None:
                    if (i - start_time) >= 15:
                        valid_segments.append((start_time, i))
                    start_time = None
        if start_time is not None:
            if (len(smoothed_ad) - start_time) >= 15:
                valid_segments.append((start_time, len(smoothed_ad)))

        if not valid_segments:
            self.update_status.emit("未检测到电影正片。")
            return

        self.update_status.emit(f"成功识别出 {len(valid_segments)} 段正片，正在调用内部 FFmpeg 无损合并...")

        chunk_files = []
        for i, (start, end) in enumerate(valid_segments):
            chunk_name = f"part_{i}.ts"
            chunk_files.append(chunk_name)
            cmd_cut = [
                ffmpeg_bin, '-y', '-ss', str(start), '-to', str(end),
                '-i', self.file_path, '-c', 'copy', chunk_name
            ]
            subprocess.run(cmd_cut, creationflags=subprocess.CREATE_NO_WINDOW)

        concat_list = "concat_list.txt"
        with open(concat_list, "w", encoding="utf-8") as f:
            for chunk in chunk_files:
                f.write(f"file '{chunk}'\n")

        out_file = self.file_path.replace(".ts", "_ocr_cleared.ts")
        cmd_concat = [
            ffmpeg_bin, '-y', '-f', 'concat', '-safe', '0',
            '-i', concat_list, '-c', 'copy', out_file
        ]
        subprocess.run(cmd_concat, creationflags=subprocess.CREATE_NO_WINDOW)

        if os.path.exists(concat_list):
            os.remove(concat_list)
        for chunk in chunk_files:
            if os.path.exists(chunk):
                os.remove(chunk)

        self.update_status.emit(f"大功告成！全独立无广告版已生成: {os.path.basename(out_file)}")

class DropWindow(QWidget):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("AI 文本识图去广告独立版")
        self.resize(450, 220)
        self.setAcceptDrops(True)
        
        layout = QVBoxLayout()
        self.label = QLabel("全独立离线全包版\n\n直接把带广告的 TS 电影拖到这里来", self)
        self.label.setAlignment(Qt.AlignCenter)
        layout.addWidget(self.label)
        self.setLayout(layout)
        self.processor = None
        
    def dragEnterEvent(self, event):
        if event.mimeData().hasUrls():
            event.accept()
        else:
            event.ignore()
            
    def dropEvent(self, event):
        urls = event.mimeData().urls()
        if urls:
            file_path = urls[0].toLocalFile()
            if file_path.lower().endswith('.ts'):
                self.processor = VideoOcrProcessor(file_path)
                self.processor.update_status.connect(self.update_label)
                self.processor.start()
            else:
                self.label.setText("只支持拖入 .ts 格式的电影文件")

    def update_label(self, text):
        self.label.setText(text)

if __name__ == '__main__':
    app = QApplication(sys.argv)
    window = DropWindow()
    window.show()
    sys.exit(app.exec_())