#!/usr/bin/env python3
"""
L1-S2-U17-L5 笨蛋坏蛋？ — 英文台词批量生产
读取 F 列(编剧台词) → LLM 润色 → 写入 G 列(英文台词)
"""

import json
import subprocess
import sys
import os
import re
import time

# Import LLM client
sys.path.insert(0, '/root/.openclaw/workspace-xiaoyan/business_production/组件配置/interactive-component-json/scripts')
from llm_client import LLMClient

# Knowledge points for L1-S2-U17-L5
KNOWLEDGE_WORDS = ["talk", "understand", "point", "a lot of"]

SYSTEM_PROMPT = """You are an English script polisher for children's educational content (ages 6-8, L2 English learners). 

## TASK
Polish the given Chinese-created English line. The lines are already in English but need polishing for naturalness, brevity, and kid-friendliness.

## STRICT RULES
1. **Preserve knowledge point words**: "talk", "understand", "point", "a lot of" MUST appear in the output if the input has them. Do NOT replace or delete them.
2. **Sentence length**: ≤ 8 words per sentence. Split longer sentences with periods or exclamation marks.
3. **British spelling**: colour (not color), centre (not center), realise (not realize), travelling (not traveling), favourite (not favorite), neighbour (not neighbor).
4. **Colloquial**: Use natural spoken English. Add kid-friendly interjections where natural: Haha, Oops, Uh-oh, Oh, Hey, Well, Hmm, Wow, Oh boy.
5. **Match emotion**: Match the character's current mood through word choice and punctuation.
6. **No Markdown**: Plain text only. No **bold**, *italic*, etc.
7. **For robot "Bip bop" lines**: Keep them exactly as-is. Do NOT change robot sounds.
8. **Output ONLY the polished English line**: No row numbers, no labels, no explanations, no Chinese — just the line.
9. **Do not add content**: Don't add words or ideas not in the original.
10. **Preserve meaning**: Keep the original intent and information.

## CHARACTER VOICES
- **Ben**: Excitable, impulsive boy → short, bouncy sentences; uses exclamation marks
- **User**: Calm, thoughtful child → measured, careful speech
- **Tom**: Adult mayor → calm, kind, authoritative
- **11/Robot**: Simple/broken English + "Bip bop" sounds
- **Jay & Lin**: Sad Speedy Monkey employees → emotional, hurt

## EPISODE CONTEXT
Classroom. Ben and User discover a bear robot. They think it's a spy. Turns out it's a helper robot — a gift from Speedy Monkey. Jay and Lin are sad because everyone judges them by looks.

## FORMAT (MANDATORY)
For every input, output EXACTLY ONE polished line. No line numbers, no prefixes, no explanations.
For each input line, output your polished version on a new line."""

def get_token():
    """Get feishu tenant access token"""
    r = subprocess.run([
        'curl', '-s', '-X', 'POST',
        'https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal',
        '-H', 'Content-Type: application/json',
        '-d', '{"app_id":"cli_a931175d41799cc7","app_secret":"Iw2vEfbjT6GtV0GhbxbZqfQ4nAPtbR14"}'
    ], capture_output=True, text=True, timeout=10)
    return json.loads(r.stdout)['tenant_access_token']

def write_cell(token, row, value):
    """Write a single cell to G column"""
    range_str = f"wMQVyV!G{row}:G{row}"
    result = subprocess.run([
        'curl', '-s', '-X', 'PUT',
        'https://open.feishu.cn/open-apis/sheets/v2/spreadsheets/DCcKsLbrmhfXgrtB7N2c9GA4ntf/values',
        '-H', 'Content-Type: application/json',
        '-H', f'Authorization: Bearer {token}',
        '-d', json.dumps({"valueRange": {"range": range_str, "values": [[value]]}})
    ], capture_output=True, text=True, timeout=10)
    return json.loads(result.stdout).get('code', -1) == 0

def verify_cell(token, row, expected):
    """Verify a cell value"""
    range_str = f"wMQVyV!G{row}:G{row}"
    result = subprocess.run([
        'curl', '-s',
        f'https://open.feishu.cn/open-apis/sheets/v2/spreadsheets/DCcKsLbrmhfXgrtB7N2c9GA4ntf/values/{range_str}?valueRenderOption=ToString',
        '-H', f'Authorization: Bearer {token}'
    ], capture_output=True, text=True, timeout=10)
    try:
        values = json.loads(result.stdout).get('data', {}).get('valueRange', {}).get('values', [])
        if values and values[0]:
            return values[0][0].strip() == expected.strip()
    except:
        pass
    return False

def main():
    # Load data
    with open('/tmp/l5_need_work.json') as f:
        items = json.load(f)
    
    print(f"Total rows to process: {len(items)}")
    
    # Init LLM
    llm = LLMClient()
    token = get_token()
    
    # Process in batches of 10
    batch_size = 10
    total_batches = (len(items) + batch_size - 1) // batch_size
    written = 0
    failed = 0
    
    for bi in range(0, len(items), batch_size):
        batch = items[bi:bi + batch_size]
        bn = bi // batch_size + 1
        print(f"\n{'='*60}")
        print(f"Batch {bn}/{total_batches} ({len(batch)} rows)")
        print(f"{'='*60}")
        
        # Build prompt: numbered list
        prompt_lines = []
        for idx, item in enumerate(batch):
            prompt_lines.append(f"[{idx+1}] {item['character']}: {item['cn_line']}")
        user_prompt = "\n".join(prompt_lines)
        
        # Call LLM
        try:
            content, usage = llm.call(SYSTEM_PROMPT, user_prompt, max_tokens=2000, temperature=0.2)
            print(f"  Tokens: {usage['prompt_tokens']}+{usage['completion_tokens']}")
        except Exception as e:
            print(f"  ❌ LLM call failed: {e}")
            # Use original lines as fallback
            for item in batch:
                success = write_cell(token, item['row'], item['cn_line'])
            failed += len(batch)
            continue
        
        # Parse response
        lines = content.strip().split('\n')
        parsed = [l.strip() for l in lines if l.strip()]
        
        # Match parsed lines to batch items
        # Strategy: remove [N] prefixes if present, then match by position
        cleaned = []
        for l in parsed:
            # Remove [N] or N. prefix
            l = re.sub(r'^\[\d+\]\s*', '', l)
            l = re.sub(r'^\d+[\.\)]\s*', '', l)
            l = l.strip()
            if l:
                cleaned.append(l)
        
        # Write
        for idx, item in enumerate(batch):
            if idx < len(cleaned) and cleaned[idx]:
                en_line = cleaned[idx]
            else:
                en_line = item['cn_line']  # fallback
            
            # Clean up any trailing punctuation artifacts
            en_line = en_line.strip().strip('"').strip("'")
            
            success = write_cell(token, item['row'], en_line)
            if success:
                written += 1
                print(f"  ✅ R{item['row']:4d} | {item['character']:8s} → {en_line[:70]}")
            else:
                failed += 1
                print(f"  ❌ R{item['row']:4d} | write failed")
        
        # Rate limit
        time.sleep(0.5)
    
    # Summary
    print(f"\n{'='*60}")
    print(f"🎉 Done! Written: {written}, Failed: {failed}, Total: {len(items)}")
    print(f"{'='*60}")
    
    # Final count verification
    range_str = "wMQVyV!G1:G190"
    result = subprocess.run([
        'curl', '-s',
        f'https://open.feishu.cn/open-apis/sheets/v2/spreadsheets/DCcKsLbrmhfXgrtB7N2c9GA4ntf/values/{range_str}?valueRenderOption=ToString',
        '-H', f'Authorization: Bearer {token}'
    ], capture_output=True, text=True, timeout=10)
    values = json.loads(result.stdout).get('data', {}).get('valueRange', {}).get('values', [])
    filled = sum(1 for v in values if v and v[0] and str(v[0]).strip())
    print(f"Total G column non-empty cells: {filled}")

if __name__ == '__main__':
    main()
