#!/usr/bin/env python3
"""
Cron wrapper for content pipeline.
Handles locking, logging, and error notification.
"""

import fcntl
import json
import logging
import sys
from datetime import datetime
from pathlib import Path

# Add project root to path
sys.path.insert(0, str(Path(__file__).parent))

from pipeline import run_pipeline

# Logging configuration
LOG_DIR = Path(__file__).parent / "logs"
LOG_DIR.mkdir(exist_ok=True)

LOCK_FILE = Path(__file__).parent / ".pipeline.lock"
PARENT_ERROR_LOG = Path(__file__).parent.parent / "logs" / "error.log"


def setup_logging():
    """Configure logging for cron execution."""
    log_file = LOG_DIR / f"pipeline_{datetime.now().strftime('%Y-%m-%d')}.log"

    # File handler
    file_handler = logging.FileHandler(log_file)
    file_handler.setLevel(logging.DEBUG)
    file_handler.setFormatter(
        logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s")
    )

    # Console handler (for cron output)
    console_handler = logging.StreamHandler()
    console_handler.setLevel(logging.INFO)
    console_handler.setFormatter(
        logging.Formatter("%(levelname)s: %(message)s")
    )

    # Root logger
    root_logger = logging.getLogger()
    root_logger.setLevel(logging.DEBUG)
    root_logger.addHandler(file_handler)
    root_logger.addHandler(console_handler)

    return logging.getLogger(__name__)


def acquire_lock() -> bool:
    """Acquire exclusive lock to prevent parallel runs."""
    try:
        lock_fd = open(LOCK_FILE, "w")
        fcntl.flock(lock_fd, fcntl.LOCK_EX | fcntl.LOCK_NB)
        lock_fd.write(str(datetime.now().isoformat()))
        lock_fd.flush()
        return True
    except (IOError, OSError):
        return False


def release_lock():
    """Release lock file."""
    try:
        LOCK_FILE.unlink()
    except FileNotFoundError:
        pass


def log_to_parent_error_log(message: str):
    """Log critical errors to parent project's error log."""
    try:
        PARENT_ERROR_LOG.parent.mkdir(exist_ok=True)
        with open(PARENT_ERROR_LOG, "a") as f:
            timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
            f.write(f"[{timestamp}] [content-pipeline] {message}\n")
    except Exception as e:
        print(f"Failed to write to parent error log: {e}", file=sys.stderr)


def save_run_result(result: dict):
    """Save pipeline run result for monitoring."""
    result_file = LOG_DIR / "last_run.json"
    try:
        with open(result_file, "w") as f:
            json.dump(result, f, indent=2, default=str)
    except Exception as e:
        print(f"Failed to save run result: {e}", file=sys.stderr)


def main():
    """Main cron entry point."""
    logger = setup_logging()
    logger.info("=" * 60)
    logger.info("Content Pipeline Cron Runner Started")
    logger.info("=" * 60)

    # Acquire lock
    if not acquire_lock():
        logger.warning("Pipeline already running, exiting")
        return 0

    try:
        # Run pipeline
        result = run_pipeline()

        # Save result for monitoring
        run_result = {
            "timestamp": datetime.now().isoformat(),
            "success": result.success,
            "topic_id": result.topic_id,
            "article_id": result.article_id,
            "wp_post_id": result.wp_post_id,
            "post_url": result.post_url,
            "error": result.error,
            "skipped_reason": result.skipped_reason,
            "stats": result.stats,
        }
        save_run_result(run_result)

        if result.success:
            logger.info(f"Pipeline completed successfully: {result.post_url}")
            return 0
        else:
            error_msg = result.error or result.skipped_reason or "Unknown error"
            logger.error(f"Pipeline failed: {error_msg}")

            # Log critical failures to parent error log
            if result.error:
                log_to_parent_error_log(f"Pipeline failed: {error_msg}")

            return 1

    except Exception as e:
        logger.exception("Unhandled exception in pipeline")
        log_to_parent_error_log(f"Unhandled exception: {str(e)}")
        return 1

    finally:
        release_lock()
        logger.info("Content Pipeline Cron Runner Finished")


if __name__ == "__main__":
    sys.exit(main())
