#!/usr/bin/env python3
"""
Generation Log for V4 Orchestrator

Verbose text logging for human-readable debugging and audit trail.
Format: Plain text with timestamps and log levels.

Example:
2026-02-03 12:00:00 [INFO] Orchestrator started: story=truck-stop-revenge, take=003
2026-02-03 12:00:01 [DEBUG] Next task: id=4, stage=06-grids, action=await_feedback
2026-02-03 12:00:02 [ERROR] Failed to generate characteristic: API timeout
"""

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


class GenerationLogger:
    """
    Text-based logger for orchestrator operations.

    Writes to {take_path}/generation.log with timestamps and log levels.
    """

    def __init__(self, take_path: Path):
        """
        Initialize logger.

        Args:
            take_path: Path to take directory
        """
        self.take_path = take_path
        self.log_file = take_path / "generation.log"

        # Ensure log file exists
        self.log_file.touch()

    def _write(self, level: str, message: str) -> None:
        """
        Write log entry to file and stdout.

        Args:
            level: Log level (INFO/DEBUG/WARNING/ERROR)
            message: Log message
        """
        timestamp = datetime.now(timezone.utc).strftime("%Y-%m-%d %H:%M:%S")
        log_line = f"{timestamp} [{level}] {message}\n"

        # Write to file
        with open(self.log_file, 'a') as f:
            f.write(log_line)

        # Also print to stdout
        print(log_line.rstrip())

    def info(self, message: str) -> None:
        """Log info message."""
        self._write("INFO", message)

    def debug(self, message: str) -> None:
        """Log debug message."""
        self._write("DEBUG", message)

    def warning(self, message: str) -> None:
        """Log warning message."""
        self._write("WARNING", message)

    def error(self, message: str) -> None:
        """Log error message."""
        self._write("ERROR", message)

    def section(self, title: str) -> None:
        """Log section header."""
        separator = "=" * 60
        self._write("INFO", separator)
        self._write("INFO", title)
        self._write("INFO", separator)

    def task_start(self, task: Dict[str, Any]) -> None:
        """
        Log task execution start.

        Args:
            task: Task dictionary
        """
        task_id = task['id']
        stage = task['stage']
        action = task['action']
        iteration = task.get('iteration', 'N/A')

        self.info(f"Task {task_id} START: {stage} / {action} (iteration={iteration})")

    def task_complete(self, task: Dict[str, Any], result: Optional[str] = None) -> None:
        """
        Log task completion.

        Args:
            task: Task dictionary
            result: Optional result path
        """
        task_id = task['id']
        stage = task['stage']
        result_str = f" → {result}" if result else ""

        self.info(f"Task {task_id} COMPLETE: {stage}{result_str}")

    def task_waiting(self, task: Dict[str, Any], message: str) -> None:
        """
        Log task waiting for feedback.

        Args:
            task: Task dictionary
            message: Message for user
        """
        task_id = task['id']
        stage = task['stage']

        self.info(f"Task {task_id} WAITING: {stage}")
        self.info(f"  Message: {message}")

    def task_failed(self, task: Dict[str, Any], error: str) -> None:
        """
        Log task failure.

        Args:
            task: Task dictionary
            error: Error message
        """
        task_id = task['id']
        stage = task['stage']

        self.error(f"Task {task_id} FAILED: {stage}")
        self.error(f"  Error: {error}")

    def feedback_received(
        self,
        task: Dict[str, Any],
        feedback_type: str,
        feedback_text: str
    ) -> None:
        """
        Log user feedback received.

        Args:
            task: Task dictionary
            feedback_type: Type of feedback (approve/regenerate/edit/skip)
            feedback_text: Feedback text
        """
        task_id = task['id']
        stage = task['stage']

        self.info(f"FEEDBACK for task {task_id} ({stage}): {feedback_type}")
        self.info(f"  Text: {feedback_text}")

    def api_request(
        self,
        api_name: str,
        endpoint: str,
        params: Optional[Dict[str, Any]] = None
    ) -> None:
        """
        Log API request.

        Args:
            api_name: API name (e.g., "NanoBanana", "Kling")
            endpoint: API endpoint
            params: Request parameters (will be truncated)
        """
        self.debug(f"API REQUEST: {api_name} → {endpoint}")

        if params:
            # Truncate long parameters (e.g., base64 images)
            params_str = json.dumps(params, indent=2)
            if len(params_str) > 500:
                params_str = params_str[:500] + "... (truncated)"
            self.debug(f"  Params: {params_str}")

    def api_response(
        self,
        api_name: str,
        status_code: int,
        response: Optional[Any] = None,
        error: Optional[str] = None
    ) -> None:
        """
        Log API response.

        Args:
            api_name: API name
            status_code: HTTP status code
            response: Response data (will be truncated)
            error: Error message if request failed
        """
        if error:
            self.error(f"API RESPONSE: {api_name} → {status_code} ERROR")
            self.error(f"  Error: {error}")
        else:
            self.debug(f"API RESPONSE: {api_name} → {status_code} OK")

            if response:
                response_str = json.dumps(response, indent=2) if isinstance(response, dict) else str(response)
                if len(response_str) > 500:
                    response_str = response_str[:500] + "... (truncated)"
                self.debug(f"  Response: {response_str}")

    def file_operation(self, operation: str, path: Path) -> None:
        """
        Log file operation.

        Args:
            operation: Operation type (created/read/updated/deleted)
            path: File path
        """
        self.debug(f"FILE {operation.upper()}: {path}")

    def queue_status(
        self,
        total: int,
        completed: int,
        waiting: int,
        pending: int,
        failed: int
    ) -> None:
        """
        Log task queue status summary.

        Args:
            total: Total tasks
            completed: Completed tasks
            waiting: Waiting tasks
            pending: Pending tasks
            failed: Failed tasks
        """
        self.info(f"Queue status: {total} total | {completed} completed | {waiting} waiting | {pending} pending | {failed} failed")

    def stage_start(self, stage: str, iteration: str) -> None:
        """
        Log stage start.

        Args:
            stage: Stage identifier
            iteration: Iteration number
        """
        self.section(f"Stage {stage} - Iteration {iteration}")

    def stage_complete(self, stage: str, iteration: str, output_path: Path) -> None:
        """
        Log stage completion.

        Args:
            stage: Stage identifier
            iteration: Iteration number
            output_path: Output file path
        """
        self.info(f"Stage {stage}/{iteration} complete → {output_path}")

    def user_prompt(self, message: str) -> None:
        """
        Log user prompt message.

        Args:
            message: Prompt message
        """
        self.info(f"USER PROMPT: {message}")

    def orchestrator_start(self, story_name: str, take: str) -> None:
        """
        Log orchestrator start.

        Args:
            story_name: Story name
            take: Take number
        """
        self.section(f"Orchestrator V4 - {story_name} / {take}")
        self.info(f"Started at {datetime.now(timezone.utc).isoformat()}")

    def orchestrator_complete(self) -> None:
        """Log orchestrator completion."""
        self.section("Orchestrator Complete")
        self.info(f"Finished at {datetime.now(timezone.utc).isoformat()}")

    def orchestrator_paused(self, reason: str) -> None:
        """
        Log orchestrator pause.

        Args:
            reason: Reason for pause (e.g., "waiting for feedback")
        """
        self.info(f"Orchestrator paused: {reason}")


def setup_generation_log(take_path: Path) -> GenerationLogger:
    """
    Set up generation logger for a take.

    Args:
        take_path: Path to take directory

    Returns:
        GenerationLogger instance
    """
    return GenerationLogger(take_path)
