#!/usr/bin/env python3
"""
Chess Activity Sync - Fetches games from Chess.com and Lichess APIs.

Automatically syncs chess games to the activity tracking system.
Run daily via cron or manually.

Usage:
    python sync-chess.py              # Sync today's games
    python sync-chess.py --days 7     # Sync last 7 days
    python sync-chess.py --test       # Test API connection without saving

Configuration:
    Set usernames in .claude/context/activity-config.json:
    {
      "api_sources": {
        "chess.com": { "activity": "chess", "username": "your_username", "enabled": true },
        "lichess": { "activity": "chess", "username": "your_username", "enabled": true }
      }
    }
"""

import json
import hashlib
import sys
from datetime import datetime, timedelta
from pathlib import Path
from urllib.request import urlopen, Request
from urllib.error import URLError, HTTPError

# Add skills directory to path for imports
sys.path.insert(0, str(Path(__file__).parent / '.claude' / 'skills' / 'supabase-connector'))

CONFIG_PATH = Path(__file__).parent / '.claude' / 'context' / 'activity-config.json'


def load_config():
    """Load activity configuration"""
    try:
        with open(CONFIG_PATH) as f:
            return json.load(f)
    except Exception as e:
        print(f"Error loading config: {e}")
        return None


def fetch_json(url, headers=None):
    """Fetch JSON from URL"""
    req = Request(url, headers=headers or {})
    req.add_header('User-Agent', 'CHL-Activity-Tracker/1.0')
    try:
        with urlopen(req, timeout=30) as response:
            return json.loads(response.read().decode())
    except HTTPError as e:
        if e.code == 404:
            return None
        raise
    except URLError as e:
        print(f"Network error: {e}")
        return None


def fetch_chesscom_games(username, start_date, end_date):
    """Fetch games from Chess.com API"""
    games = []

    # Chess.com API returns games by month
    current = start_date.replace(day=1)
    while current <= end_date:
        year = current.year
        month = current.month
        url = f"https://api.chess.com/pub/player/{username}/games/{year}/{month:02d}"

        print(f"  Fetching Chess.com {year}/{month:02d}...")
        data = fetch_json(url)

        if data and 'games' in data:
            for game in data['games']:
                # Parse game end time
                end_time = game.get('end_time', 0)
                game_date = datetime.fromtimestamp(end_time).date()

                # Filter to date range
                if start_date.date() <= game_date <= end_date.date():
                    # Determine result
                    white = game.get('white', {})
                    black = game.get('black', {})

                    if white.get('username', '').lower() == username.lower():
                        result = white.get('result', 'unknown')
                        opponent = black.get('username', 'unknown')
                        color = 'white'
                    else:
                        result = black.get('result', 'unknown')
                        opponent = white.get('username', 'unknown')
                        color = 'black'

                    games.append({
                        'date': game_date.strftime('%Y-%m-%d'),
                        'time': datetime.fromtimestamp(end_time).strftime('%H:%M:%S'),
                        'time_class': game.get('time_class', 'unknown'),
                        'result': result,
                        'opponent': opponent,
                        'color': color,
                        'url': game.get('url', '')
                    })

        # Move to next month
        if month == 12:
            current = current.replace(year=year + 1, month=1)
        else:
            current = current.replace(month=month + 1)

    return games


def fetch_lichess_games(username, start_date, end_date):
    """Fetch games from Lichess API"""
    games = []

    # Lichess API uses milliseconds
    since = int(start_date.timestamp() * 1000)
    until = int(end_date.timestamp() * 1000)

    url = f"https://lichess.org/api/games/user/{username}?since={since}&until={until}&max=100"

    print(f"  Fetching Lichess games...")

    # Lichess returns NDJSON (newline-delimited JSON)
    req = Request(url)
    req.add_header('User-Agent', 'CHL-Activity-Tracker/1.0')
    req.add_header('Accept', 'application/x-ndjson')

    try:
        with urlopen(req, timeout=30) as response:
            for line in response:
                if line.strip():
                    game = json.loads(line.decode())

                    # Parse game timestamp
                    created_at = game.get('createdAt', 0) // 1000
                    game_date = datetime.fromtimestamp(created_at)

                    # Get players
                    players = game.get('players', {})
                    white = players.get('white', {}).get('user', {})
                    black = players.get('black', {}).get('user', {})

                    if white.get('name', '').lower() == username.lower():
                        winner = game.get('winner', 'draw')
                        result = 'win' if winner == 'white' else ('loss' if winner == 'black' else 'draw')
                        opponent = black.get('name', 'unknown')
                        color = 'white'
                    else:
                        winner = game.get('winner', 'draw')
                        result = 'win' if winner == 'black' else ('loss' if winner == 'white' else 'draw')
                        opponent = white.get('name', 'unknown')
                        color = 'black'

                    games.append({
                        'date': game_date.strftime('%Y-%m-%d'),
                        'time': game_date.strftime('%H:%M:%S'),
                        'time_class': game.get('speed', 'unknown'),
                        'result': result,
                        'opponent': opponent,
                        'color': color,
                        'url': f"https://lichess.org/{game.get('id', '')}"
                    })
    except HTTPError as e:
        if e.code == 404:
            print(f"  User not found: {username}")
        else:
            print(f"  Lichess API error: {e}")
    except Exception as e:
        print(f"  Error fetching Lichess games: {e}")

    return games


def sync_games(games, source, activity='chess', test_mode=False):
    """Sync games to Supabase"""
    if not games:
        print(f"  No games to sync from {source}")
        return 0

    if test_mode:
        print(f"  TEST MODE: Would sync {len(games)} games from {source}")
        for game in games[:3]:
            print(f"    {game['date']} {game['time_class']} vs {game['opponent']}: {game['result']}")
        if len(games) > 3:
            print(f"    ... and {len(games) - 3} more")
        return len(games)

    try:
        from client import get_supabase_client
        supabase = get_supabase_client()
    except Exception as e:
        print(f"  Error connecting to Supabase: {e}")
        return 0

    synced = 0
    for game in games:
        # Create unique ID for this game
        game_id = hashlib.md5(
            f"{game['date']}{game['time']}{source}{game.get('url', '')}".encode()
        ).hexdigest()[:8]

        entry = {
            "id": game_id,
            "date": game['date'],
            "time": game['time'],
            "activity": activity,
            "source": source,
            "metadata": {
                "time_class": game['time_class'],
                "result": game['result'],
                "opponent": game['opponent'],
                "color": game['color'],
                "url": game['url']
            }
        }

        try:
            supabase.table('chl_activity_logs').upsert(entry).execute()
            synced += 1
        except Exception as e:
            # Likely duplicate, skip
            pass

    print(f"  Synced {synced} games from {source}")
    return synced


def main():
    import argparse

    parser = argparse.ArgumentParser(description='Sync chess games to activity tracker')
    parser.add_argument('--days', type=int, default=1, help='Number of days to sync (default: 1)')
    parser.add_argument('--test', action='store_true', help='Test mode - no database writes')
    args = parser.parse_args()

    config = load_config()
    if not config:
        print("Failed to load configuration")
        return 1

    api_sources = config.get('api_sources', {})

    # Date range
    end_date = datetime.now()
    start_date = end_date - timedelta(days=args.days)

    print(f"\nChess Activity Sync")
    print(f"Period: {start_date.strftime('%Y-%m-%d')} to {end_date.strftime('%Y-%m-%d')}")
    if args.test:
        print("MODE: Test (no database writes)\n")
    else:
        print()

    total_synced = 0

    # Chess.com
    chesscom = api_sources.get('chess.com', {})
    if chesscom.get('enabled') and chesscom.get('username'):
        print(f"Chess.com ({chesscom['username']}):")
        games = fetch_chesscom_games(chesscom['username'], start_date, end_date)
        total_synced += sync_games(games, 'chess.com', chesscom.get('activity', 'chess'), args.test)
    elif chesscom.get('username'):
        print(f"Chess.com: Disabled (set enabled: true in config)")
    else:
        print("Chess.com: No username configured")

    # Lichess
    lichess = api_sources.get('lichess', {})
    if lichess.get('enabled') and lichess.get('username'):
        print(f"\nLichess ({lichess['username']}):")
        games = fetch_lichess_games(lichess['username'], start_date, end_date)
        total_synced += sync_games(games, 'lichess', lichess.get('activity', 'chess'), args.test)
    elif lichess.get('username'):
        print(f"\nLichess: Disabled (set enabled: true in config)")
    else:
        print("\nLichess: No username configured")

    print(f"\nTotal: {total_synced} games synced")
    return 0


if __name__ == "__main__":
    sys.exit(main())
