#!/usr/bin/env python3
"""
Feedback Logging for V4 Orchestrator

JSONL-based append-only logging of user feedback interactions.
Format: One JSON object per line (JSONL), never modified after write.

Feedback entry structure:
{
  "timestamp": "2026-02-03T12:15:00Z",
  "stage": "06-characteristic",
  "iteration": "001",
  "feedback_type": "regenerate" | "approve" | "edit" | "skip",
  "text": "Make it darker, more ominous",
  "action": "create_iteration_002",
  "scene_num": 1,  # Optional: for video/frame feedback
  "frame_num": 3   # Optional: for frame feedback
}
"""

import json
from pathlib import Path
from typing import List, Dict, Any, Optional, Tuple
from datetime import datetime, timezone


def append_feedback(
    take_path: Path,
    stage: str,
    feedback_type: str,
    text: str,
    iteration: Optional[str] = None,
    action: Optional[str] = None,
    **kwargs
) -> None:
    """
    Append feedback entry to feedback.jsonl.

    Args:
        take_path: Path to take directory
        stage: Stage identifier (e.g., "06-characteristic")
        feedback_type: Type of feedback (approve/regenerate/edit/skip)
        text: Feedback text from user
        iteration: Current iteration being reviewed
        action: Action taken (e.g., "create_iteration_002")
        **kwargs: Additional fields (scene_num, frame_num, etc.)
    """
    feedback_file = take_path / "feedback.jsonl"

    entry = {
        "timestamp": datetime.now(timezone.utc).isoformat(),
        "stage": stage,
        "iteration": iteration,
        "feedback_type": feedback_type,
        "text": text,
        "action": action
    }

    # Add any additional fields
    entry.update(kwargs)

    # Append to JSONL file
    with open(feedback_file, 'a') as f:
        f.write(json.dumps(entry) + '\n')


def read_feedback(take_path: Path) -> List[Dict[str, Any]]:
    """
    Read all feedback entries from feedback.jsonl.

    Args:
        take_path: Path to take directory

    Returns:
        List of feedback entries (dicts), empty list if file doesn't exist
    """
    feedback_file = take_path / "feedback.jsonl"

    if not feedback_file.exists():
        return []

    entries = []
    with open(feedback_file, 'r') as f:
        for line in f:
            line = line.strip()
            if line:
                entries.append(json.loads(line))

    return entries


def get_stage_feedback(
    take_path: Path,
    stage: str,
    iteration: Optional[str] = None
) -> List[Dict[str, Any]]:
    """
    Get feedback entries for specific stage (and optionally iteration).

    Args:
        take_path: Path to take directory
        stage: Stage identifier
        iteration: Optional iteration filter

    Returns:
        List of matching feedback entries
    """
    all_feedback = read_feedback(take_path)

    filtered = [f for f in all_feedback if f['stage'] == stage]

    if iteration:
        filtered = [f for f in filtered if f.get('iteration') == iteration]

    return filtered


def get_latest_feedback(take_path: Path, stage: str) -> Optional[Dict[str, Any]]:
    """
    Get most recent feedback for a stage.

    Args:
        take_path: Path to take directory
        stage: Stage identifier

    Returns:
        Latest feedback entry, or None
    """
    stage_feedback = get_stage_feedback(take_path, stage)

    if not stage_feedback:
        return None

    return stage_feedback[-1]  # Last entry is most recent


def parse_feedback(text: str) -> Tuple[str, str]:
    """
    Parse user feedback text to determine type and extract content.

    Recognizes patterns:
    - "approve", "ok", "good", "yes", "y" → ("approve", text)
    - "skip", "no references", "generic" → ("skip", text)
    - "regenerate", "redo", "try again" → ("regenerate", text)
    - Other text → ("edit", text)

    Args:
        text: User feedback text

    Returns:
        Tuple of (feedback_type, cleaned_text)
    """
    text_lower = text.lower().strip()

    # Approve patterns
    if text_lower in ['approve', 'ok', 'good', 'yes', 'y', 'accept', 'looks good']:
        return ('approve', text)

    # Skip patterns
    if any(word in text_lower for word in ['skip', 'no references', 'generic', 'don\'t need']):
        return ('skip', text)

    # Regenerate patterns
    if any(word in text_lower for word in ['regenerate', 'redo', 'try again', 'different', 'another']):
        return ('regenerate', text)

    # Default to edit if text contains actionable feedback
    return ('edit', text)


def format_feedback_summary(take_path: Path, stage: Optional[str] = None) -> str:
    """
    Format feedback history as human-readable text.

    Args:
        take_path: Path to take directory
        stage: Optional stage filter

    Returns:
        Formatted feedback summary
    """
    if stage:
        feedback = get_stage_feedback(take_path, stage)
        title = f"Feedback for {stage}"
    else:
        feedback = read_feedback(take_path)
        title = "All Feedback"

    if not feedback:
        return f"{title}: None"

    lines = [f"{title}:", "=" * 60]

    for entry in feedback:
        timestamp = entry['timestamp']
        stage_name = entry['stage']
        iter_num = entry.get('iteration', '?')
        fb_type = entry['feedback_type']
        text = entry['text']
        action = entry.get('action', 'N/A')

        lines.append(f"[{timestamp}] {stage_name}/{iter_num}")
        lines.append(f"  Type: {fb_type}")
        lines.append(f"  Text: {text}")
        lines.append(f"  Action: {action}")
        lines.append("")

    return '\n'.join(lines)


def count_feedback_by_type(take_path: Path) -> Dict[str, int]:
    """
    Count feedback entries by type.

    Args:
        take_path: Path to take directory

    Returns:
        Dict with counts: {'approve': 5, 'regenerate': 3, 'edit': 2, 'skip': 1}
    """
    feedback = read_feedback(take_path)

    counts = {}
    for entry in feedback:
        fb_type = entry['feedback_type']
        counts[fb_type] = counts.get(fb_type, 0) + 1

    return counts


def get_rejection_count(take_path: Path, stage: str) -> int:
    """
    Count how many times a stage was regenerated (not approved on first try).

    Args:
        take_path: Path to take directory
        stage: Stage identifier

    Returns:
        Number of regenerations (0 means approved on first try)
    """
    stage_feedback = get_stage_feedback(take_path, stage)

    # Count regenerate/edit feedback types
    rejections = [f for f in stage_feedback if f['feedback_type'] in ['regenerate', 'edit']]

    return len(rejections)


def get_feedback_history_for_claude(take_path: Path, stage: str) -> str:
    """
    Format feedback history for a stage to include in Claude prompts.

    This provides context about previous attempts and what didn't work.

    Args:
        take_path: Path to take directory
        stage: Stage identifier

    Returns:
        Formatted feedback history suitable for Claude context
    """
    stage_feedback = get_stage_feedback(take_path, stage)

    if not stage_feedback:
        return "No previous feedback for this stage."

    lines = ["Previous feedback for this stage:", ""]

    for i, entry in enumerate(stage_feedback, 1):
        iter_num = entry.get('iteration', '?')
        fb_type = entry['feedback_type']
        text = entry['text']

        lines.append(f"{i}. Iteration {iter_num} - {fb_type.upper()}")
        lines.append(f"   User said: \"{text}\"")
        lines.append("")

    lines.append("Please incorporate this feedback into your next generation.")

    return '\n'.join(lines)
