#!/usr/bin/env python3
"""Label positions with Stockfish evaluations."""

import json
import chess.engine
import sys
import os
from pathlib import Path
from tqdm import tqdm

def label_positions_with_stockfish(positions_file, output_file, stockfish_path, batch_size=100, depth=12, verbose=False):
    """Read positions and label them with Stockfish evaluations.

    Args:
        positions_file: Path to positions.txt
        output_file: Path to training_data.jsonl
        stockfish_path: Path to stockfish binary
        batch_size: Batch size (not used, kept for compatibility)
        depth: Stockfish depth
        verbose: Print detailed error messages
    """

    # Check if stockfish exists
    if not Path(stockfish_path).exists():
        print(f"Error: Stockfish not found at {stockfish_path}")
        print(f"Tried: {stockfish_path}")
        print(f"Set STOCKFISH_PATH environment variable or pass as argument")
        sys.exit(1)

    print(f"Using Stockfish: {stockfish_path}")

    # Check if positions file exists
    if not Path(positions_file).exists():
        print(f"Error: Positions file not found at {positions_file}")
        sys.exit(1)

    # Load existing evaluations if resuming
    evaluated_fens = set()
    position_count = 0

    if Path(output_file).exists():
        with open(output_file, 'r') as f:
            for line in f:
                try:
                    data = json.loads(line)
                    evaluated_fens.add(data['fen'])
                    position_count += 1
                except json.JSONDecodeError:
                    pass
        print(f"Resuming from {position_count} already evaluated positions")

    # Count total positions
    with open(positions_file, 'r') as f:
        total_lines = sum(1 for _ in f)

    if total_lines == 0:
        print(f"Error: Positions file is empty ({positions_file})")
        sys.exit(1)

    print(f"Total positions to process: {total_lines}")
    print(f"Using depth: {depth}")
    print()

    # Initialize engine
    try:
        engine = chess.engine.SimpleEngine.popen_uci(stockfish_path)
    except Exception as e:
        print(f"Error: Could not start Stockfish engine")
        print(f"  Stockfish path: {stockfish_path}")
        print(f"  Error: {e}")
        sys.exit(1)

    # Track statistics
    evaluated = 0
    skipped_invalid = 0
    skipped_duplicate = 0
    errors = 0

    try:
        with open(positions_file, 'r') as f:
            with open(output_file, 'a') as out:
                with tqdm(total=total_lines, initial=position_count, desc="Labeling positions") as pbar:
                    for fen in f:
                        fen = fen.strip()

                        # Skip empty lines
                        if not fen:
                            skipped_invalid += 1
                            pbar.update(1)
                            continue

                        # Skip already evaluated
                        if fen in evaluated_fens:
                            skipped_duplicate += 1
                            pbar.update(1)
                            continue

                        try:
                            # Validate FEN
                            board = chess.Board(fen)
                            if not board.is_valid():
                                skipped_invalid += 1
                                pbar.update(1)
                                continue

                            # Evaluate at specified depth
                            info = engine.analyse(board, chess.engine.Limit(depth=depth))

                            if info.get('score') is None:
                                skipped_invalid += 1
                                pbar.update(1)
                                continue

                            score = info['score'].white()

                            # Convert to centipawns
                            if score.is_mate():
                                # Use large values for mate scores
                                eval_cp = 2000 if score.mate() > 0 else -2000
                            else:
                                eval_cp = score.cp

                            # Clamp to [-2000, 2000]
                            eval_cp = max(-2000, min(2000, eval_cp))

                            # Save evaluation
                            data = {"fen": fen, "eval": eval_cp}
                            out.write(json.dumps(data) + '\n')
                            out.flush()  # Force write to disk
                            evaluated += 1

                        except Exception as e:
                            errors += 1
                            if verbose:
                                print(f"Error evaluating position: {fen[:50]}...")
                                print(f"  {type(e).__name__}: {e}")
                            pbar.update(1)
                            continue

                        pbar.update(1)

    finally:
        engine.quit()

    # Print summary
    print()
    print("=" * 60)
    print("LABELING SUMMARY")
    print("=" * 60)
    print(f"Successfully evaluated: {evaluated}")
    print(f"Skipped (duplicates):   {skipped_duplicate}")
    print(f"Skipped (invalid):      {skipped_invalid}")
    print(f"Errors:                 {errors}")
    print(f"Total processed:        {evaluated + skipped_duplicate + skipped_invalid + errors}")
    print("=" * 60)
    print()

    if evaluated == 0:
        print("WARNING: No positions were successfully evaluated!")
        print("Check that:")
        print("  1. positions.txt is not empty")
        print("  2. positions.txt contains valid FENs")
        print("  3. Stockfish is installed and working")
        print("  4. Stockfish path is correct")
        return False

    print(f"✓ Labeling complete. Output saved to {output_file}")
    return True

if __name__ == "__main__":
    import argparse

    parser = argparse.ArgumentParser(description="Label chess positions with Stockfish evaluations")
    parser.add_argument("positions_file", nargs="?", default="positions.txt",
                        help="Input positions file (default: positions.txt)")
    parser.add_argument("output_file", nargs="?", default="training_data.jsonl",
                        help="Output file (default: training_data.jsonl)")
    parser.add_argument("stockfish_path", nargs="?", default=None,
                        help="Path to Stockfish binary (default: $STOCKFISH_PATH or 'stockfish')")
    parser.add_argument("--depth", type=int, default=12,
                        help="Stockfish depth (default: 12)")
    parser.add_argument("--verbose", action="store_true",
                        help="Print detailed error messages")

    args = parser.parse_args()

    # Determine Stockfish path
    stockfish_path = args.stockfish_path or os.environ.get("STOCKFISH_PATH", "stockfish")

    success = label_positions_with_stockfish(
        positions_file=args.positions_file,
        output_file=args.output_file,
        stockfish_path=stockfish_path,
        depth=args.depth,
        verbose=args.verbose
    )

    sys.exit(0 if success else 1)
