"""
Knowledge Pack Importer

Imports knowledge from .khb (Knowledge Hub Bundle) files with conflict resolution.
Supports dry-run mode for previewing imports before applying.
"""

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

from .knowledge_manager import KnowledgeManager
from .file_utils import write_knowledge_file


def import_knowledge_pack(
    pack_path: str,
    conflict_resolution: str = 'ask',
    dry_run: bool = False,
    skip_validation: bool = False
) -> Dict[str, Any]:
    """
    Import knowledge from a package (.khb file).

    Args:
        pack_path: Path to .khb file
        conflict_resolution: How to handle ID conflicts:
            - 'skip': Skip conflicting items (keep existing)
            - 'overwrite': Overwrite existing items
            - 'merge': Merge metadata (preserve higher score)
            - 'ask': Return conflicts for user decision (default)
            - 'rename': Create new item with different ID
        dry_run: If True, preview import without applying changes
        skip_validation: If True, skip validation checks (faster but risky)

    Returns:
        dict: Import summary with:
            - success: bool
            - imported_count: int
            - skipped_count: int
            - conflicts: list (if conflict_resolution='ask')
            - errors: list (if any errors occurred)

    Example:
        >>> result = import_knowledge_pack(
        ...     "frontend-skills.khb",
        ...     conflict_resolution='skip',
        ...     dry_run=False
        ... )
        >>> print(f"Imported {result['imported_count']} items")
    """
    pack_path = Path(pack_path)

    if not pack_path.exists():
        return {
            "success": False,
            "error": f"Pack file not found: {pack_path}"
        }

    # Read pack file
    try:
        with open(pack_path, 'r', encoding='utf-8') as f:
            if pack_path.suffix == '.yaml' or pack_path.suffix == '.yml':
                import yaml
                pack = yaml.safe_load(f)
            else:  # json
                pack = json.load(f)
    except Exception as e:
        return {
            "success": False,
            "error": f"Failed to read pack file: {str(e)}"
        }

    # Validate pack structure
    if not skip_validation:
        validation_result = _validate_pack(pack)
        if not validation_result['valid']:
            return {
                "success": False,
                "error": f"Invalid pack format: {validation_result['error']}"
            }

    # Extract pack metadata and knowledge items
    pack_metadata = pack.get('metadata', {})
    knowledge_items = pack.get('knowledge', [])

    if not knowledge_items:
        return {
            "success": False,
            "error": "Pack contains no knowledge items"
        }

    # Initialize knowledge manager
    km = KnowledgeManager()

    # Process items
    imported = []
    skipped = []
    conflicts = []
    errors = []

    for item in knowledge_items:
        try:
            # Check if item already exists
            existing_item = km.read(item['id'])

            if existing_item:
                # Handle conflict
                if conflict_resolution == 'skip':
                    skipped.append({
                        "id": item['id'],
                        "title": item['title'],
                        "reason": "Already exists (skipped)"
                    })
                    continue

                elif conflict_resolution == 'overwrite':
                    if not dry_run:
                        _overwrite_item(km, item)
                    imported.append({
                        "id": item['id'],
                        "title": item['title'],
                        "action": "overwritten"
                    })

                elif conflict_resolution == 'merge':
                    if not dry_run:
                        _merge_item(km, existing_item, item)
                    imported.append({
                        "id": item['id'],
                        "title": item['title'],
                        "action": "merged"
                    })

                elif conflict_resolution == 'rename':
                    new_id = _generate_unique_id(km, item['id'])
                    item['id'] = new_id
                    if not dry_run:
                        _import_new_item(km, item)
                    imported.append({
                        "id": new_id,
                        "title": item['title'],
                        "action": "imported with new ID",
                        "original_id": item['id']
                    })

                elif conflict_resolution == 'ask':
                    conflicts.append({
                        "id": item['id'],
                        "title": item['title'],
                        "existing_score": existing_item['frontmatter'].get('score', 0.0),
                        "new_score": item.get('score', 0.0),
                        "existing_updated": existing_item['frontmatter'].get('updated'),
                        "new_updated": item.get('updated')
                    })

            else:
                # No conflict - import new item
                if not dry_run:
                    _import_new_item(km, item)
                imported.append({
                    "id": item['id'],
                    "title": item['title'],
                    "action": "imported"
                })

        except Exception as e:
            errors.append({
                "id": item.get('id', 'unknown'),
                "title": item.get('title', 'unknown'),
                "error": str(e)
            })

    # Build summary
    summary = {
        "success": len(errors) == 0,
        "dry_run": dry_run,
        "pack_metadata": pack_metadata,
        "total_items": len(knowledge_items),
        "imported_count": len(imported),
        "skipped_count": len(skipped),
        "conflict_count": len(conflicts),
        "error_count": len(errors),
        "imported": imported,
        "skipped": skipped,
        "conflicts": conflicts,
        "errors": errors
    }

    return summary


def _validate_pack(pack: Dict[str, Any]) -> Dict[str, Any]:
    """Validate pack structure."""
    if not isinstance(pack, dict):
        return {"valid": False, "error": "Pack must be a dictionary"}

    if 'version' not in pack:
        return {"valid": False, "error": "Missing 'version' field"}

    if 'metadata' not in pack:
        return {"valid": False, "error": "Missing 'metadata' field"}

    if 'knowledge' not in pack:
        return {"valid": False, "error": "Missing 'knowledge' field"}

    if not isinstance(pack['knowledge'], list):
        return {"valid": False, "error": "'knowledge' must be a list"}

    # Validate each knowledge item
    required_fields = ['id', 'type', 'title', 'content']
    for idx, item in enumerate(pack['knowledge']):
        for field in required_fields:
            if field not in item:
                return {
                    "valid": False,
                    "error": f"Item {idx} missing required field: {field}"
                }

    return {"valid": True}


def _import_new_item(km: KnowledgeManager, item: Dict[str, Any]) -> None:
    """Import a new knowledge item."""
    # Build frontmatter
    frontmatter = {
        'id': item['id'],
        'type': item['type'],
        'title': item['title'],
        'created': item.get('created', datetime.now().isoformat()),
        'updated': datetime.now().isoformat(),  # Update timestamp on import
        'score': item.get('score', 0.0),
        'factors': item.get('factors', {}),
        'tags': item.get('tags', []),
        'keywords': item.get('keywords', []),
        'source': 'import',
        'metadata': item.get('metadata', {})
    }

    # Add import metadata
    frontmatter['metadata']['imported_at'] = datetime.now().isoformat()
    frontmatter['metadata']['original_source'] = item.get('source', 'unknown')

    # Determine file path
    dir_name = km.TYPE_TO_DIR.get(item['type'])
    if not dir_name:
        raise ValueError(f"Invalid knowledge type: {item['type']}")

    file_path = km.base_path / dir_name / f"{item['id']}.md"

    # Write file
    write_knowledge_file(file_path, frontmatter, item['content'])


def _overwrite_item(km: KnowledgeManager, item: Dict[str, Any]) -> None:
    """Overwrite existing knowledge item."""
    # Same as import_new_item but updates existing file
    _import_new_item(km, item)


def _merge_item(
    km: KnowledgeManager,
    existing_item: Dict[str, Any],
    new_item: Dict[str, Any]
) -> None:
    """
    Merge existing and new knowledge items.
    Strategy: Keep item with higher score, merge tags/keywords.
    """
    existing_fm = existing_item['frontmatter']
    existing_score = existing_fm.get('score', 0.0)
    new_score = new_item.get('score', 0.0)

    # Decide which content to keep
    if new_score > existing_score:
        # Use new item's content and frontmatter
        content = new_item['content']
        frontmatter = {
            'id': new_item['id'],
            'type': new_item['type'],
            'title': new_item['title'],
            'created': existing_fm.get('created'),  # Keep original creation date
            'updated': datetime.now().isoformat(),
            'score': new_score,
            'factors': new_item.get('factors', {}),
            'tags': existing_fm.get('tags', []),
            'keywords': existing_fm.get('keywords', []),
            'source': 'merge',
            'metadata': existing_fm.get('metadata', {})
        }
    else:
        # Keep existing item's content
        content = existing_item['content']
        frontmatter = existing_fm.copy()
        frontmatter['updated'] = datetime.now().isoformat()

    # Merge tags and keywords (union)
    existing_tags = set(existing_fm.get('tags', []))
    new_tags = set(new_item.get('tags', []))
    frontmatter['tags'] = sorted(existing_tags | new_tags)

    existing_keywords = set(existing_fm.get('keywords', []))
    new_keywords = set(new_item.get('keywords', []))
    frontmatter['keywords'] = sorted(existing_keywords | new_keywords)

    # Add merge metadata
    frontmatter['metadata']['merged_at'] = datetime.now().isoformat()
    frontmatter['metadata']['merge_score_comparison'] = {
        'existing': existing_score,
        'new': new_score,
        'kept': 'new' if new_score > existing_score else 'existing'
    }

    # Write merged item
    dir_name = km.TYPE_TO_DIR.get(frontmatter['type'])
    file_path = km.base_path / dir_name / f"{frontmatter['id']}.md"
    write_knowledge_file(file_path, frontmatter, content)


def _generate_unique_id(km: KnowledgeManager, original_id: str) -> str:
    """Generate a unique ID by appending counter."""
    from .file_utils import generate_id

    # Extract prefix from original ID (e.g., "sk" from "sk-20260205-abc123")
    parts = original_id.split('-')
    prefix = parts[0] if parts else 'kn'

    # Generate new ID
    counter = 1
    while True:
        new_id = f"{generate_id(prefix)}-{counter}"
        if km.read(new_id) is None:
            return new_id
        counter += 1


def resolve_conflicts_batch(
    conflicts: List[Dict[str, Any]],
    resolutions: List[str]
) -> List[Dict[str, Any]]:
    """
    Resolve multiple conflicts at once.
    Used when conflict_resolution='ask'.

    Args:
        conflicts: List of conflicts from import_knowledge_pack
        resolutions: List of resolutions ('skip', 'overwrite', 'merge', 'rename')
                    Must match length of conflicts

    Returns:
        list: List of resolved actions
    """
    if len(conflicts) != len(resolutions):
        raise ValueError("Resolutions list must match conflicts list length")

    resolved = []
    for conflict, resolution in zip(conflicts, resolutions):
        resolved.append({
            "id": conflict['id'],
            "resolution": resolution
        })

    return resolved
