from abc import ABC, abstractmethod
import time, os, shutil
from config import SAVED_DIR, DOWNLOAD_DIR

class PaperDownloader(ABC):
    
    def __init__(self, driver_manager):
        """Initialize the paper downloader with a driver manager."""
        self.driver_manager = driver_manager
        self.download_dir = DOWNLOAD_DIR
        self.saved_dir = SAVED_DIR
        print("Driver Manager initialized.")

    
    # @abstractmethod
    def download(self, url: str):
        pass

    @abstractmethod
    def get_author_institution_journal(self, url: str):
        pass
    
    @staticmethod
    def clear_download_dir(download_dir):
        for f in os.listdir(download_dir):
            if f.endswith('.crdownload') or f.endswith('.pdf'):
                os.remove(os.path.join(download_dir, f))

    @staticmethod
    def wait_for_pdf_download(download_dir, timeout=120, check_interval=1, stable_times=3):
        start_time = time.time()
        file_path = None
        last_size = -1
        stable_count = 0
        while True:
            files = [f for f in os.listdir(download_dir) if f.endswith('.pdf') or f.endswith('.pdf.crdownload')]
            if files:
                files = sorted(files, key=lambda x: os.path.getmtime(os.path.join(download_dir, x)), reverse=True)
                file_path = os.path.join(download_dir, files[0])
                try:
                    curr_size = os.path.getsize(file_path)
                except Exception:
                    curr_size = -1

                if curr_size == last_size and curr_size > 0:
                    stable_count += 1
                else:
                    stable_count = 0
                last_size = curr_size

                if stable_count >= stable_times:
                    if file_path.endswith('.crdownload'):
                        final_pdf = file_path[:-11]
                        if os.path.exists(final_pdf):
                            file_path = final_pdf
                        else:
                            file_path = None
                    break
            else:
                file_path = None

            if time.time() - start_time > timeout:
                print("等待下载超时")
                file_path = None
                break

            time.sleep(check_interval)

        if file_path and file_path.endswith('.pdf') and os.path.exists(file_path):
            return file_path
        else:
            return None


    def trigger_and_save_pdf(self, driver, pdf_url, download_dir, saved_dir, paper_idx, wait_sec=15):
        # 清空下载目录
        self.clear_download_dir(download_dir)

        # 跳转PDF，触发下载
        try:
            driver.get(pdf_url)
        except Exception as e:
            print(f"打开PDF链接失败: {e}")
            return False

        # TODO: 改成轮询, self.wait_for_pdf_download
        time.sleep(wait_sec)

        # 查找pdf文件
        files = [f for f in os.listdir(download_dir) if f.endswith('.pdf')]
        if not files:
            print("下载超时或失败")
            return False
        file_path = os.path.join(download_dir, files[0])
        file_name = files[0]

        # 文件重命名与保存
        save_path = os.path.join(saved_dir, f"{paper_idx}-{file_name}")
        try:
            shutil.move(file_path, save_path)
            print("[✓] PDF saved:", save_path)
            return True
        except Exception as e:
            print("重命名或保存失败:", e)
            return False