#!/usr/bin/env python3
"""Fetch TradeWhisperer Patreon data and save state to /tmp/tw_state.json"""
import json, re, subprocess, sys

COOKIES = "/root/.hermes/patreon/cookies.txt"
HEADERS = [
    "-H", "User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
    "-H", "Accept: application/json",
]

def curl(url):
    r = subprocess.run(
        ["curl", "-s", "-b", COOKIES, "--max-time", "30", "-g"] + HEADERS + [url],
        capture_output=True, text=True
    )
    return json.loads(r.stdout)

# Fetch post list — paginate until we have enough to cover the weekly colour list
# The weekly colour list is posted once/week; by Monday night it can be >50 posts back
BASE_URL = "https://www.patreon.com/api/posts?filter[campaign_id]=12722890&filter[contains_exclusive_posts]=true&sort=-published_at&page[count]=50&fields[post]=title,published_at,post_type&json-api-version=1.0"
posts = []
next_url = BASE_URL
pages_fetched = 0

while next_url and pages_fetched < 6:  # max 300 posts (6 × 50)
    data = curl(next_url)
    if data.get('errors'):
        print(f"ERROR: API error — {data['errors']}", file=sys.stderr)
        sys.exit(1)
    batch = data.get('data', [])
    if not batch:
        break
    posts.extend(batch)
    pages_fetched += 1
    # Check if we've found both colour list posts — stop early
    titles = [p['attributes']['title'] for p in posts]
    has_daily_cl = any('DAILY' in t and 'CANDLE COLOR LIST' in t and 'PLUS TIER' not in t for t in titles)
    has_weekly_cl = any('WEEKLY' in t and 'CANDLE COLOR LIST' in t and 'PLUS TIER' not in t for t in titles)
    if has_daily_cl and has_weekly_cl:
        break
    # Follow cursor to next page
    next_cursor = data.get('meta', {}).get('pagination', {}).get('cursors', {}).get('next')
    if next_cursor:
        next_url = BASE_URL + f"&page[cursor]={next_cursor}"
    else:
        break

if not posts:
    print("ERROR: No posts returned — cookie may be expired", file=sys.stderr)
    sys.exit(1)

daily_posts = [p for p in posts if 'DAILY' in p['attributes']['title'] and p['attributes']['post_type'] == 'image_file' and 'COLOR LIST' not in p['attributes']['title'] and 'PLUS TIER' not in p['attributes']['title']]
weekly_posts = [p for p in posts if 'WEEKLY' in p['attributes']['title'] and p['attributes']['post_type'] == 'image_file' and 'COLOR LIST' not in p['attributes']['title'] and 'PLUS TIER' not in p['attributes']['title']]
date = daily_posts[0]['attributes']['published_at'][:10] if daily_posts else posts[0]['attributes']['published_at'][:10]

def get_charts(post_list):
    charts = {}
    for p in post_list:
        media_data = curl(f"https://www.patreon.com/api/posts/{p['id']}?include=media&json-api-version=1.0&fields[media]=image_urls,file_name")
        for item in media_data.get('included', []):
            if item['type'] == 'media':
                fname = item['attributes'].get('file_name', '')
                urls = item['attributes'].get('image_urls', {})
                url = urls.get('original') or urls.get('default') or urls.get('url', '')
                m = re.match(r'^([A-Z0-9.:]+)_\d{4}', fname)
                if m and m.group(1) not in charts:  # first-seen wins (posts sorted newest-first)
                    charts[m.group(1)] = url
    return charts

daily_charts = get_charts(daily_posts)
weekly_charts = get_charts(weekly_posts)

def fetch_colour_list(title_keyword):
    for p in posts:
        t = p['attributes']['title']
        if title_keyword in t and 'CANDLE COLOR LIST' in t and 'PLUS TIER' not in t:
            pd = curl(f"https://www.patreon.com/api/posts/{p['id']}?json-api-version=1.0")
            attrs = pd['data']['attributes']
            content = json.loads(attrs['content_json_string'])
            lines = []
            for node in content.get('content', []):
                texts = [c['text'] for c in node.get('content', []) if c.get('type') == 'text']
                lines.append(''.join(texts))
            colours, bull, bear = {}, '?', '?'
            for line in lines:
                mm = re.match(r'^(BLUE-GREEN|BLUE|GREEN|PINK-RED|PINK|RED|TRIM-OPTION):\s*(.*)', line.strip())
                if mm:
                    for t2 in mm.group(2).split():
                        colours[t2] = mm.group(1)
                mb = re.search(r'Bullish Candles:\s*([\d.]+%)', line)
                if mb: bull = mb.group(1)
                me = re.search(r'Bearish Candles:\s*([\d.]+%)', line)
                if me: bear = me.group(1)
            return colours, bull, bear
    return {}, '?', '?'

daily_colours, bull_d, bear_d = fetch_colour_list('DAILY')
weekly_colours, bull_w, bear_w = fetch_colour_list('WEEKLY')

state = {
    'date': date,
    'daily_charts': daily_charts, 'weekly_charts': weekly_charts,
    'daily_colours': daily_colours, 'weekly_colours': weekly_colours,
    'bull_d': bull_d, 'bear_d': bear_d, 'bull_w': bull_w, 'bear_w': bear_w,
}
with open('/tmp/tw_state.json', 'w') as f:
    json.dump(state, f)

print(f"State saved: {len(daily_charts)} daily charts, {len(weekly_charts)} weekly charts, {len(daily_colours)} daily colours, {len(weekly_colours)} weekly colours, date={date}")
