#!/usr/bin/env python3
"""
OCI Deal Accelerator — Output Orchestrator

Routes output generation based on the architect's format selection.
Supports: deck (default), deck+drawio, deck+doc, deck+xlsx, deck+pdf,
full, pdf, doc only.

Usage:
    python oci_output.py --spec proposal.yaml --format deck --output-dir ./output
    python oci_output.py --spec proposal.yaml --format full --output-dir ./output
"""

import yaml
import argparse
import os
import sys
from pathlib import Path

# Output format definitions
FORMATS = {
    "deck": ["pptx"],
    "deck+drawio": ["pptx", "drawio"],
    "deck+doc": ["pptx", "docx"],
    "deck+xlsx": ["pptx", "xlsx"],
    "deck+pdf": ["pptx", "pdf"],
    "full": ["pptx", "drawio", "docx", "xlsx", "pdf"],
    "doc": ["docx"],
    "pdf": ["pdf"],
    "bom": ["bom"],
}

GENERATORS = {
    "pptx": {
        "module": "oci_deck_gen",
        "class": "OCIDeckGenerator",
        "method": "from_spec",
        "description": "Slide deck (.pptx)",
    },
    "drawio": {
        "module": "oci_diagram_gen",
        "class": "OCIDiagramGenerator",
        "method": "from_spec",
        "description": "Architecture diagram (.drawio)",
    },
    "docx": {
        "module": "oci_doc_gen",
        "class": "OCIDocGenerator",
        "method": "from_spec",
        "description": "Technical document (.docx)",
        "optional": True,
    },
    "xlsx": {
        "module": "oci_cost_gen",
        "class": "OCICostGenerator",
        "method": "from_spec",
        "description": "Cost spreadsheet (.xlsx)",
        "optional": True,
    },
    "pdf": {
        "module": "oci_pdf_gen",
        "class": "OCIPDFGenerator",
        "method": "from_spec",
        "description": "Customer-facing PDF (.pdf)",
    },
    "bom": {
        "module": "oci_bom_gen",
        "class": "OCIBomGenerator",
        "method": "from_spec",
        "description": "Bill of Materials (.xlsx)",
        "optional": True,
    },
}


def resolve_format(format_str: str) -> list:
    """Resolve a format string to a list of output types."""
    normalized = format_str.lower().strip().replace(" ", "")
    # Handle common variations
    for key in FORMATS:
        if normalized == key.replace("+", "").replace(" ", ""):
            return FORMATS[key]
    if normalized in FORMATS:
        return FORMATS[normalized]
    # Default to deck
    print(f"Warning: Unknown format '{format_str}', defaulting to 'deck'")
    return FORMATS["deck"]


def generate_output(spec: dict, output_type: str, output_dir: str,
                    base_name: str) -> str | None:
    """Generate a single output type. Returns the output path or None."""
    gen_config = GENERATORS.get(output_type)
    if not gen_config:
        print(f"  Skip: No generator for .{output_type}")
        return None

    output_path = os.path.join(output_dir, f"{base_name}.{output_type}")

    try:
        # Dynamic import
        module = __import__(gen_config["module"])
        gen_class = getattr(module, gen_config["class"])
        factory = getattr(gen_class, gen_config["method"])
        gen = factory(spec)
        gen.save(output_path)
        print(f"  Generated: {output_path}")
        return output_path
    except ImportError:
        if gen_config.get("optional"):
            print(f"  Skip: {gen_config['description']} "
                  f"(generator not available)")
            return None
        raise
    except Exception as e:
        print(f"  Error generating {gen_config['description']}: {e}")
        return None


def orchestrate(spec_path: str, format_str: str = "deck",
                output_dir: str = ".", base_name: str = None) -> list:
    """Main orchestration: load spec, generate all requested outputs."""
    with open(spec_path, 'r') as f:
        spec = yaml.safe_load(f)

    if not base_name:
        base_name = Path(spec_path).stem

    os.makedirs(output_dir, exist_ok=True)

    output_types = resolve_format(format_str)
    print(f"Output format: {format_str}")
    print(f"Generating: {', '.join(f'.{t}' for t in output_types)}")
    print(f"Output directory: {output_dir}")
    print()

    results = []
    for output_type in output_types:
        result = generate_output(spec, output_type, output_dir, base_name)
        if result:
            results.append(result)

    print(f"\nDone. Generated {len(results)} file(s).")
    return results


def main():
    parser = argparse.ArgumentParser(
        description="OCI Deal Accelerator — Output Orchestrator"
    )
    parser.add_argument(
        "--spec", required=True,
        help="Path to YAML spec file",
    )
    parser.add_argument(
        "--format", default="deck",
        choices=list(FORMATS.keys()),
        help="Output format selection (default: deck)",
    )
    parser.add_argument(
        "--output-dir", default=".",
        help="Output directory (default: current directory)",
    )
    parser.add_argument(
        "--name", default=None,
        help="Base name for output files (default: spec filename)",
    )
    args = parser.parse_args()

    # Add tools/ to path so generators can be imported
    tools_dir = os.path.dirname(os.path.abspath(__file__))
    if tools_dir not in sys.path:
        sys.path.insert(0, tools_dir)

    orchestrate(args.spec, args.format, args.output_dir, args.name)


if __name__ == "__main__":
    main()
