"""
Knowledge Pack Exporter

Exports knowledge items to shareable .khb (Knowledge Hub Bundle) files.
Supports filtering by type, score, tags, and format (JSON/YAML).
"""

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

from .knowledge_manager import KnowledgeManager
from .file_utils import read_knowledge_file


def export_knowledge_pack(
    output_path: str,
    filter_criteria: Optional[Dict[str, Any]] = None,
    format: str = 'json',
    metadata: Optional[Dict[str, Any]] = None
) -> Dict[str, Any]:
    """
    Export knowledge to a shareable package (.khb file).

    Args:
        output_path: Path to .khb file (will auto-add extension if missing)
        filter_criteria: Optional filters:
            - type: knowledge type (skill, rule, pattern, etc.)
            - min_score: minimum score threshold
            - tags: list of tags to filter by
            - limit: maximum number of items
        format: 'json' or 'yaml' (default: json for better compatibility)
        metadata: Optional metadata to include in pack:
            - name: Pack name
            - author: Author name
            - description: Pack description
            - tags: Pack-level tags

    Returns:
        dict: Export summary with count, path, metadata

    Example:
        >>> export_knowledge_pack(
        ...     "frontend-skills.khb",
        ...     filter_criteria={"type": "skill", "tags": ["frontend", "react"], "min_score": 0.6},
        ...     metadata={"name": "Frontend Best Practices", "author": "DevOnn"}
        ... )
        {
            "success": True,
            "count": 45,
            "path": "/path/to/frontend-skills.khb",
            "size_bytes": 123456,
            "metadata": {...}
        }
    """
    # Ensure output path has .khb extension
    output_path = Path(output_path)
    if output_path.suffix != '.khb':
        output_path = output_path.with_suffix('.khb')

    # Initialize knowledge manager
    km = KnowledgeManager()

    # Apply filters
    filter_criteria = filter_criteria or {}
    knowledge_type = filter_criteria.get('type')
    min_score = filter_criteria.get('min_score')
    tags = filter_criteria.get('tags')
    limit = filter_criteria.get('limit')

    # Get filtered knowledge items
    items = km.list(
        knowledge_type=knowledge_type,
        min_score=min_score,
        tags=tags,
        limit=limit
    )

    if not items:
        return {
            "success": False,
            "error": "No knowledge items match the filter criteria",
            "count": 0
        }

    # Build knowledge pack structure
    pack_metadata = {
        "name": metadata.get("name", "Knowledge Pack") if metadata else "Knowledge Pack",
        "author": metadata.get("author", "Unknown") if metadata else "Unknown",
        "created": datetime.now().isoformat(),
        "description": metadata.get("description", "") if metadata else "",
        "tags": metadata.get("tags", []) if metadata else [],
        "count": len(items),
        "format": format
    }

    # Convert items to export format
    knowledge_items = []
    for item in items:
        fm = item['frontmatter']
        knowledge_items.append({
            "id": fm.get('id'),
            "type": fm.get('type'),
            "title": fm.get('title'),
            "content": item['content'],
            "score": fm.get('score', 0.0),
            "factors": fm.get('factors', {}),
            "tags": fm.get('tags', []),
            "keywords": fm.get('keywords', []),
            "created": fm.get('created'),
            "updated": fm.get('updated'),
            "metadata": fm.get('metadata', {}),
            "source": fm.get('source', 'unknown')
        })

    pack = {
        "version": "1.0.0",
        "metadata": pack_metadata,
        "knowledge": knowledge_items
    }

    # Ensure output directory exists
    output_path.parent.mkdir(parents=True, exist_ok=True)

    # Write pack file
    if format == 'yaml':
        import yaml
        with open(output_path, 'w', encoding='utf-8') as f:
            yaml.safe_dump(pack, f, default_flow_style=False, allow_unicode=True, sort_keys=False)
    else:  # json
        with open(output_path, 'w', encoding='utf-8') as f:
            json.dump(pack, f, indent=2, ensure_ascii=False)

    # Get file size
    size_bytes = output_path.stat().st_size

    return {
        "success": True,
        "count": len(items),
        "path": str(output_path.absolute()),
        "size_bytes": size_bytes,
        "size_kb": round(size_bytes / 1024, 2),
        "metadata": pack_metadata
    }


def export_to_directory(
    output_dir: str,
    filter_criteria: Optional[Dict[str, Any]] = None,
    preserve_structure: bool = True
) -> Dict[str, Any]:
    """
    Export knowledge to a directory (preserving folder structure).
    Useful for git-based sharing or manual inspection.

    Args:
        output_dir: Directory to export to
        filter_criteria: Same as export_knowledge_pack
        preserve_structure: If True, maintains skills/, rules/, etc. structure

    Returns:
        dict: Export summary
    """
    from shutil import copy2

    output_dir = Path(output_dir)
    output_dir.mkdir(parents=True, exist_ok=True)

    # Initialize knowledge manager
    km = KnowledgeManager()

    # Apply filters
    filter_criteria = filter_criteria or {}
    items = km.list(
        knowledge_type=filter_criteria.get('type'),
        min_score=filter_criteria.get('min_score'),
        tags=filter_criteria.get('tags'),
        limit=filter_criteria.get('limit')
    )

    if not items:
        return {
            "success": False,
            "error": "No knowledge items match the filter criteria",
            "count": 0
        }

    # Copy files
    copied_files = []
    for item in items:
        source_path = Path(item['file_path'])

        if preserve_structure:
            # Maintain directory structure (skills/skill-123.md)
            rel_path = source_path.relative_to(km.base_path)
            dest_path = output_dir / rel_path
            dest_path.parent.mkdir(parents=True, exist_ok=True)
        else:
            # Flat structure (skill-123.md)
            dest_path = output_dir / source_path.name

        copy2(source_path, dest_path)
        copied_files.append(str(dest_path))

    return {
        "success": True,
        "count": len(copied_files),
        "output_dir": str(output_dir.absolute()),
        "files": copied_files
    }


def get_export_preview(
    filter_criteria: Optional[Dict[str, Any]] = None
) -> Dict[str, Any]:
    """
    Preview what would be exported without actually exporting.
    Useful for users to confirm before exporting.

    Args:
        filter_criteria: Same as export_knowledge_pack

    Returns:
        dict: Preview with count, items summary, estimated size
    """
    km = KnowledgeManager()

    filter_criteria = filter_criteria or {}
    items = km.list(
        knowledge_type=filter_criteria.get('type'),
        min_score=filter_criteria.get('min_score'),
        tags=filter_criteria.get('tags'),
        limit=filter_criteria.get('limit')
    )

    # Calculate summary
    type_counts = {}
    total_size_estimate = 0
    items_summary = []

    for item in items:
        fm = item['frontmatter']
        ktype = fm.get('type', 'unknown')
        type_counts[ktype] = type_counts.get(ktype, 0) + 1

        # Estimate size (frontmatter + content)
        size_estimate = len(json.dumps(fm)) + len(item['content'])
        total_size_estimate += size_estimate

        items_summary.append({
            "id": fm.get('id'),
            "type": ktype,
            "title": fm.get('title'),
            "score": fm.get('score', 0.0),
            "tags": fm.get('tags', [])
        })

    return {
        "count": len(items),
        "type_counts": type_counts,
        "estimated_size_kb": round(total_size_estimate / 1024, 2),
        "items_summary": items_summary
    }
