import sys
import os
import platform
import time

sys.path.append(os.path.dirname(sys.path[0]))
import multiprocessing
import traceback
from utils.db_connect import BaseUtils
from amazon_spider.VPS_IP import pppoe_ip


def _reset_stale_state2(site, timeout_minutes=15):
    """回滚超过 N 分钟的 state=2 为 state=1"""
    try:
        engine = BaseUtils(site_name=site).mysql_connect()
        sql = (f"UPDATE {site}_asin_competitor_syn SET state=1 "
               f"WHERE state=2 AND updated_at < NOW() - INTERVAL {timeout_minutes} MINUTE")
        with engine.begin() as conn:
            conn.execute(sql)
        print(f'{site} 回滚超时 state=2 完成')
    except Exception as e:
        print(f'_reset_stale_state2 失败: {e}\n{traceback.format_exc()}')


def check_competitor_tasks(site) -> bool:
    """快速检查是否有待处理的竞品抓取任务"""
    try:
        engine = BaseUtils(site_name=site).mysql_connect()
        sql = f"SELECT id FROM {site}_asin_competitor_syn WHERE state=1 LIMIT 1"
        df = engine.read_sql(sql)
        return not df.empty
    except Exception as e:
        print(f'check_competitor_tasks 查询失败: {e}\n{traceback.format_exc()}')
        return False


def _read_competitor_tasks(site, read_size=200) -> list:
    """主进程：read_then_update 原子拿任务 state=1→2，返回按 asin_competitor 去重的列表"""
    try:
        engine = BaseUtils(site_name=site).mysql_connect()
        table = f'{site}_asin_competitor_syn'
        sql_read = (
            f"SELECT id, asin FROM {table} "
            f"WHERE state=1 LIMIT {read_size} FOR UPDATE"
        )
        df = engine.read_then_update(
            select_sql=sql_read,
            update_table=table,
            set_values={'state': 2},
            where_keys=['id'],
        )
        if df is None or df.empty:
            return []
        return df['asin'].drop_duplicates().tolist()
    except Exception as e:
        print(f'_read_competitor_tasks 失败: {e}\n{traceback.format_exc()}')
        return []


def _competitor_task_worker(site, data_chunk):
    """子进程入口：实例化爬虫并执行"""
    print(f"竞品子进程 {os.getpid()} 分配到 {len(data_chunk)} 条")
    from amazon_spider.asin_competitor_spider import AsinCompetitorSpider
    spider = AsinCompetitorSpider(site_name=site)
    spider.run_with_data(data_chunk)


def run_competitor_spider(site, num_processes=5):
    """主入口：读任务 → 分片 → 多进程抓取"""
    _reset_stale_state2(site)
    all_data = _read_competitor_tasks(site)
    if not all_data:
        print(f'{site} 竞品无待处理任务')
        return
    if platform.system() == 'Linux':
        pppoe_ip()
    print(f'竞品 {site}: 共 {len(all_data)} 条，启动子进程')
    if len(all_data) < 300:
        actual_processes = max(1, len(all_data) // 60)
    else:
        actual_processes = num_processes
    chunks = [all_data[i::actual_processes] for i in range(actual_processes)]
    processes = []
    for chunk in chunks:
        if chunk:
            p = multiprocessing.Process(target=_competitor_task_worker, args=(site, chunk))
            processes.append(p)
            p.start()
    # 10 分钟超时兜底：防止子进程卡死（socket 卡住 / 线程死锁等）
    for p in processes:
        p.join(timeout=600)
        if p.is_alive():
            print(f'子进程 {p.pid} 超时未完成，强制 terminate')
            p.terminate()
            p.join(timeout=5)
            if p.is_alive():
                p.kill()
    print(f'竞品 {site}: 全部子进程完成')


if __name__ == '__main__':
    # 由 crontab 每 3 分钟启动一次（外层 flock 文件锁防并发）
    # VPS Linux 启动前切 IP；Windows 本地调试跳过

    site_list = ['us']
    for site in site_list:
        run_competitor_spider(site, num_processes=3)
