#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import json
import re
import sys
import subprocess
from datetime import datetime
from pathlib import Path


def ensure_package(mod_name, pip_name=None):
    try:
        __import__(mod_name)
        return True
    except Exception:
        pkg = pip_name or mod_name
        print(f"正在安装依赖：{pkg} ...")
        subprocess.check_call([sys.executable, '-m', 'pip', 'install', pkg])
        __import__(mod_name)
        return True


ensure_package('requests')
ensure_package('browser_cookie3', 'browser-cookie3')

import requests
import browser_cookie3

BASE_DIR = Path(__file__).resolve().parent
ACCOUNTS = ["1z1352", "aubreegorant", "anna.chan666", "whhikfh", "lin.xuma", "hakk.li8", "mattie9663", "moli.li29", "alinassaaa7", "ethanlinda86", "dava4829", "abiafven", "user3344334509", "ali.cia229", "aik.luxi", "grace.allen216", "kbojsn", "annascot49", "kian.smitham", "jen.ben46", "ainaa878", "annanade1", "fielddruat6", "pkbhon", "bella.parker895", "lily.evans848", "zoe968716", "bqhiwszu5aq", "elara.voss83", "derekhilp", "sndosje", "joannxjsuup", "carys5303", "shaynerat", "tamika.dylan", "lila.soctt", "julio.dic", "vena.haley", "londyn.brooks52", "perenathan0", "winona.kun", "kaliya.davis7", "anna.carter52", "amari.clark62", "dougcremi", "biobff", "rodrivdce7u", "peyton9837", "aria75489", "jeromy286", "fuivfd3", "lindalia0b8", "ougokg", "tess65837", "phibfd", "grayyson78", "tyrelvebwz4", "ralrh.dou", "veda4731", "hgvgajj", "jbcvce", "deonlang50", "tellyjaco", "effieerko17", "jevon.huelsacr", "nyahsan3", "raycormier1", "gfdcutch", "ovalooag4au", "sala01800", "clark.win", "aydentuy1xv", "virgildietr", "amydanie4", "boddy.hod", "emely.luettg", "jimmiucnhkt", "nelsonk769", "zitasqygq7e", "vancepia3k1", "reytondhmuo", "lilyan2270", "randal0294", "huberflzytz", "ovamanny", "stantwqbsbe", "ilenexhhc1x", "ethelpoll", "isomkntf15r", "markudew3u7", "molijack0", "delphffyyi1", "edenhkxphzz", "lonspvjpctw", "rylanpmeri2", "brielkfapsj", "nonaczfx8gg", "magdavejuu5", "denisbauch1", "freddpziwbu", "alidarjjqhb", "coltoyyvig1", "adelaabbottak", "pearleszzsw", "emilytjq4vv", "immanue.105", "norvayaeq3i", "elnagdqv9pq", "wilberaztqc", "janieqzn1x4", "madlison7", "raisy617", "reidgreen53", "merlwusv8l6", "orensbyqy45", "albinlvqaob", "elzabeth93", "flolemken", "jules.kriscu", "jeraliuoeea", "immanryk676", "henr6520", "faysppofemt", "sheagluylee", "emile.an", "buddytkki1w", "minnialhi80", "bellabuck07", "zoe107452", "harleygisla", "heidixrzub3", "alexmwjosmi", "aria15576", "lvy3081", "jiexik", "jalentgk34s", "joeldxqxc94", "agustctxntu", "josebreupe0", "consufoa713", "celia.klein08", "angelscbqt5", "jeromrggqjx"]
OUTPUT_FILE = BASE_DIR / 'client_capture_results.json'
ENDPOINT = "https://aitkjk666.xyz/api/browser-capture/ingest"
FALLBACK_ENDPOINT = 'http://59.110.225.215/api/browser-capture/ingest'
TOKEN = 'tk_auto_ingest_20260326'


def parse_followers(text: str):
    patterns = [
        r'"followerCount"\s*:\s*(\d+)',
        r'"follower_count"\s*:\s*(\d+)',
        r'"stats"\s*:\s*\{[^\}]*"followerCount"\s*:\s*(\d+)',
    ]
    for p in patterns:
        m = re.search(p, text)
        if m:
            return int(m.group(1))
    return None


def pick_cookie_header():
    loaders = [
        ('chrome', browser_cookie3.chrome),
        ('edge', browser_cookie3.edge),
    ]
    last_err = None
    for name, fn in loaders:
        try:
            cj = fn(domain_name='tiktok.com')
            pairs = []
            for c in cj:
                if c.name and c.value:
                    pairs.append(f'{c.name}={c.value}')
            if pairs:
                print(f'已自动读取 {name} 的 TikTok Cookie')
                return '; '.join(pairs)
        except Exception as e:
            last_err = e
    raise RuntimeError(f'未能自动读取 Chrome/Edge 的 TikTok Cookie：{last_err}')


def capture_account(username: str, cookie_header: str):
    url = f'https://www.tiktok.com/@{username}'
    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36',
        'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
        'Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8',
        'Cookie': cookie_header,
    }
    try:
        r = requests.get(url, headers=headers, timeout=20)
        text = r.text
        followers = parse_followers(text) if r.status_code == 200 else None
        return {
            'username': username,
            'followers': followers,
            'status': 'ok' if followers is not None else f'http_{r.status_code}' if r.status_code != 200 else 'follower_not_found',
            'message': 'success' if followers is not None else (f'HTTP {r.status_code}' if r.status_code != 200 else 'follower_not_found'),
            'captured_at': datetime.now().isoformat(),
        }
    except Exception as e:
        return {
            'username': username,
            'followers': None,
            'status': 'request_error',
            'message': str(e),
            'captured_at': datetime.now().isoformat(),
        }


def main():
    if not ACCOUNTS:
        print('当前没有可抓取账号')
        sys.exit(1)
    print('正在自动读取本机浏览器登录态...')
    print(f'本次计划抓取账号数：{len(ACCOUNTS)}')
    print('账号列表预览（前10个）：', ACCOUNTS[:10])
    print('账号列表预览（后10个）：', ACCOUNTS[-10:])
    cookie_header = pick_cookie_header()
    out = {
        'task_type': 'local_capture_runner_auto_cookie',
        'generated_at': datetime.now().isoformat(),
        'count': len(ACCOUNTS),
        'results': [],
    }
    success = []
    failed = []
    processed = []
    for i, username in enumerate(ACCOUNTS, 1):
        print(f'[{i}/{len(ACCOUNTS)}] 抓取 @{username} ...')
        result = capture_account(username, cookie_header)
        out['results'].append(result)
        processed.append(username)
        if result.get('status') == 'ok' and result.get('followers') is not None:
            success.append(username)
            print(f"   ✅ 成功 @{username} -> {result.get('followers')}")
        else:
            failed.append({'username': username, 'status': result.get('status'), 'message': result.get('message')})
            print(f"   ❌ 失败 @{username} -> {result.get('status')} / {result.get('message')}")
    missing = [x for x in ACCOUNTS if x not in processed]
    out['summary'] = {
        'planned_count': len(ACCOUNTS),
        'processed_count': len(processed),
        'success_count': len(success),
        'failed_count': len(failed),
        'missing_count': len(missing),
        'success_usernames': success,
        'failed_items': failed,
        'missing_usernames': missing,
    }
    OUTPUT_FILE.write_text(json.dumps(out, indent=2, ensure_ascii=False), encoding='utf-8')
    print(f'已生成结果文件：{OUTPUT_FILE}')
    print('--- 抓取汇总 ---')
    print('计划抓取：', len(ACCOUNTS))
    print('实际处理：', len(processed))
    print('成功：', len(success))
    print('失败：', len(failed))
    print('未执行到：', len(missing))
    if failed:
        print('失败账号（前20个）：', failed[:20])
    if missing:
        print('未执行到的账号：', missing)
    try:
        resp = requests.post(ENDPOINT, headers={'Content-Type': 'application/json', 'X-Capture-Token': TOKEN}, data=json.dumps(out, ensure_ascii=False).encode('utf-8'), timeout=30)
        print('回传状态：', resp.status_code, resp.text)
    except Exception as e:
        print('HTTPS 自动回传失败：', e)
        try:
            resp = requests.post(
                FALLBACK_ENDPOINT,
                headers={'Content-Type': 'application/json', 'X-Capture-Token': TOKEN},
                data=json.dumps(out, ensure_ascii=False).encode('utf-8'),
                timeout=30,
            )
            print('HTTP 回退回传状态：', resp.status_code, resp.text)
        except Exception as e2:
            print('自动回传失败：', e2)


if __name__ == '__main__':
    main()
