#!/usr/bin/env python3
"""
Stage S1: Ingest

Download or copy the source story text.
Supports: URLs (Gutenberg, etc.), local file paths.
Creates source.txt and references/ directory structure.
"""

import subprocess
import sys
import shutil
from pathlib import Path
from datetime import datetime, timezone

sys.path.insert(0, str(Path(__file__).parent.parent))

from lib import save_metadata, ensure_dir
from lib.path_utils_v3 import get_next_iteration


def execute(story_path: Path, source: str, feedback: str = None,
            refined_from: str = None) -> dict:
    """
    Execute Stage S1: Ingest story text.

    Args:
        story_path: Path to story project directory
        source: URL or local file path
        feedback: User feedback (for re-ingest)
        refined_from: Previous iteration
    """
    stage_dir = story_path / "S1-ingest"
    ensure_dir(stage_dir)
    iteration = get_next_iteration(stage_dir)
    iter_path = stage_dir / iteration
    ensure_dir(iter_path)

    print(f"Stage S1: Ingest (iteration {iteration})")
    print(f"Source: {source}")

    # Create references directory structure
    refs_path = story_path / "references"
    ensure_dir(refs_path / "people")
    ensure_dir(refs_path / "locations")
    ensure_dir(refs_path / "style")

    # Determine source type and fetch
    source_text = None
    source_type = None

    if source.startswith("http://") or source.startswith("https://"):
        # URL — download
        source_type = "url"
        print("Downloading from URL...")
        try:
            result = subprocess.run(
                ["curl", "-sL", "--max-time", "30", source],
                capture_output=True, text=True, timeout=60
            )
            if result.returncode != 0:
                error_detail = result.stderr or result.stdout
                return {"status": "error", "error": f"Download failed: {error_detail}"}
            source_text = result.stdout
            if not source_text.strip():
                return {"status": "error", "error": "Downloaded empty content"}
        except subprocess.TimeoutExpired:
            return {"status": "error", "error": "Download timed out"}
    else:
        # Local file
        source_type = "file"
        source_path = Path(source)
        if not source_path.exists():
            return {"status": "error", "error": f"File not found: {source}"}
        source_text = source_path.read_text()

    # Clean up text (remove Gutenberg headers/footers if present)
    source_text = _clean_gutenberg_text(source_text)

    # Save source.txt at project root (canonical location)
    source_file = story_path / "source.txt"
    source_file.write_text(source_text)
    print(f"Saved: source.txt ({len(source_text)} chars, {len(source_text.splitlines())} lines)")

    # Also save a copy in the iteration directory for provenance
    (iter_path / "source.txt").write_text(source_text)

    # Save metadata
    metadata = {
        "stage": "S1-ingest",
        "iteration": iteration,
        "created_at": datetime.now(timezone.utc).isoformat(),
        "source": source,
        "source_type": source_type,
        "char_count": len(source_text),
        "line_count": len(source_text.splitlines()),
        "refined_from": refined_from,
    }
    save_metadata(iter_path / "metadata.json", metadata)

    return {
        "status": "success",
        "iteration": iteration,
        "result": "source.txt",
        "user_message": f"Story ingested: {len(source_text.splitlines())} lines, {len(source_text)} characters.",
    }


def _clean_gutenberg_text(text: str) -> str:
    """Remove Project Gutenberg headers and footers if present."""
    lines = text.split("\n")
    start = 0
    end = len(lines)

    # Find start marker
    for i, line in enumerate(lines):
        if "*** START OF" in line.upper() and "PROJECT GUTENBERG" in line.upper():
            start = i + 1
            break
        if "***START OF" in line.upper() and "PROJECT GUTENBERG" in line.upper():
            start = i + 1
            break

    # Find end marker
    for i in range(len(lines) - 1, -1, -1):
        if "*** END OF" in lines[i].upper() and "PROJECT GUTENBERG" in lines[i].upper():
            end = i
            break
        if "***END OF" in lines[i].upper() and "PROJECT GUTENBERG" in lines[i].upper():
            end = i
            break

    if start > 0 or end < len(lines):
        # Skip any blank lines right after the start marker
        while start < end and not lines[start].strip():
            start += 1
        return "\n".join(lines[start:end]).strip()

    return text
