# Familiar - Self-Hosted AI Companion Platform
# Copyright (c) 2026 George Scott Foley
# ORCID: 0009-0006-4957-0540
# Licensed under the MIT License - see LICENSE file for details

"""
Import existing memory data into the MemoryTree.

Migrates data from:
- MarkdownMemoryStore (conversation logs as .md files)
- Memory (brain key-value facts, encrypted)
- FileStore (file attachment metadata)

All imports are idempotent — duplicate content_hash entries are skipped.

Usage:
    from familiar.core.memory_import import import_all
    stats = import_all()  # Imports from all sources
"""

import logging
from pathlib import Path
from typing import Optional

logger = logging.getLogger(__name__)


def import_markdown_memories(
    tree: "MemoryTree",
    memories_dir: Optional[Path] = None,
    user_id: str = "default",
) -> dict:
    """Import markdown memory files into the MemoryTree.

    Scans all .md files in the user's memories directory, parses
    YAML frontmatter, and creates long-tier entries. Does NOT move
    files — creates index entries pointing to existing paths.

    Returns:
        Dict with "imported", "skipped" (duplicate), "errors" counts.
    """
    from familiar.core.markdown_memory import parse_memory_file

    if memories_dir is None:
        from familiar.core.paths import MEMORIES_DIR

        memories_dir = MEMORIES_DIR

    user_dir = memories_dir / user_id
    stats = {"imported": 0, "skipped": 0, "errors": 0}

    if not user_dir.exists():
        return stats

    for md_file in sorted(user_dir.glob("*.md")):
        try:
            text = md_file.read_text(encoding="utf-8")
            meta, body = parse_memory_file(text)

            if meta is None:
                # No frontmatter — use filename as title
                title = md_file.stem.replace("-", " ").title()
                tags = []
                source = ""
                created = ""
            else:
                title = (meta.topic or md_file.stem).replace("-", " ").title()
                tags = list(meta.tags) if meta.tags else []
                source_list = meta.source_memories or []
                source = source_list[0] if source_list else ""
                created = meta.created or ""

            if not title.strip():
                title = md_file.stem

            # Normalize body before hashing
            body = body.strip()

            # Add provenance tag
            if "imported" not in tags:
                tags.append("imported")
            if "markdown" not in tags:
                tags.append("markdown")

            # Check for duplicate
            from familiar.core.memory_tree import _content_hash

            chash = _content_hash(title, body)
            existing = tree.get_by_hash(chash)
            if existing:
                stats["skipped"] += 1
                continue

            tree.store(
                title=title,
                body=body,
                tier="archival",
                tags=tags,
                source=source,
                importance=0.3,
                user_id=user_id,
                file_path=str(md_file),
                meta={"original_file": md_file.name, "import_source": "markdown"},
            )
            stats["imported"] += 1

        except Exception as e:
            logger.warning("Failed to import %s: %s", md_file.name, e)
            stats["errors"] += 1

    logger.info(
        "Markdown import: %d imported, %d skipped, %d errors",
        stats["imported"],
        stats["skipped"],
        stats["errors"],
    )
    return stats


def import_brain_memories(
    tree: "MemoryTree",
    memory: "Memory",
    user_id: str = "default",
) -> dict:
    """Import key-value facts from the brain Memory into MemoryTree.

    Each Memory entry becomes a working-tier entry with the key as
    title and value as body.

    Returns:
        Dict with "imported", "skipped", "errors" counts.
    """
    stats = {"imported": 0, "skipped": 0, "errors": 0}

    try:
        all_memories = memory.recall_all()
    except Exception as e:
        logger.warning("Failed to load brain memories: %s", e)
        stats["errors"] += 1
        return stats

    for key, entry in all_memories.items():
        try:
            title = key.replace("_", " ").title()
            body = entry.value

            # Check for duplicate
            from familiar.core.memory_tree import _content_hash

            chash = _content_hash(title, body)
            existing = tree.get_by_hash(chash)
            if existing:
                stats["skipped"] += 1
                continue

            tags = ["imported", "brain"]
            if entry.category:
                tags.append(entry.category)

            tree.store(
                title=title,
                body=body,
                tier="working",
                tags=tags,
                source=entry.source or "",
                importance=min(entry.importance / 10.0, 1.0),
                user_id=user_id,
                meta={
                    "original_key": key,
                    "category": entry.category,
                    "import_source": "brain",
                },
            )
            stats["imported"] += 1

        except Exception as e:
            logger.warning("Failed to import brain memory '%s': %s", key, e)
            stats["errors"] += 1

    logger.info(
        "Brain import: %d imported, %d skipped, %d errors",
        stats["imported"],
        stats["skipped"],
        stats["errors"],
    )
    return stats


def import_file_metadata(
    tree: "MemoryTree",
    file_store: "FileStore",
    user_id: str = "default",
) -> dict:
    """Import FileStore metadata into MemoryTree as long-tier entries.

    Creates searchable index entries for files (not the file content itself).
    Links file_id in metadata for cross-reference.

    Returns:
        Dict with "imported", "skipped", "errors" counts.
    """
    stats = {"imported": 0, "skipped": 0, "errors": 0}

    try:
        all_files = file_store.search(query="", limit=10000)
    except Exception as e:
        logger.warning("Failed to list files: %s", e)
        stats["errors"] += 1
        return stats

    for record in all_files:
        try:
            title = f"File: {record.filename}"
            body = (
                f"Filename: {record.filename}\n"
                f"Type: {record.mime_type}\n"
                f"Size: {record.size_bytes} bytes\n"
                f"Job class: {record.job_class}\n"
                f"Record: {record.record_type}/{record.record_id}\n"
            )
            if record.description:
                body += f"Description: {record.description}\n"

            from familiar.core.memory_tree import _content_hash

            chash = _content_hash(title, body)
            existing = tree.get_by_hash(chash)
            if existing:
                stats["skipped"] += 1
                continue

            tags = ["imported", "file", record.job_class]
            if record.mime_type:
                mime_tag = record.mime_type.split("/")[0]
                tags.append(mime_tag)

            tree.store(
                title=title,
                body=body,
                tier="long",
                tags=tags,
                importance=0.4,
                user_id=user_id,
                meta={
                    "file_id": record.file_id,
                    "job_class": record.job_class,
                    "record_type": record.record_type,
                    "record_id": record.record_id,
                    "sha256": record.sha256,
                    "import_source": "filestore",
                },
            )
            stats["imported"] += 1

        except Exception as e:
            logger.warning("Failed to import file '%s': %s", record.filename, e)
            stats["errors"] += 1

    logger.info(
        "FileStore import: %d imported, %d skipped, %d errors",
        stats["imported"],
        stats["skipped"],
        stats["errors"],
    )
    return stats


def import_all(
    user_id: str = "default",
    tree: "MemoryTree | None" = None,
) -> dict:
    """Run all importers. Idempotent — safe to call multiple times.

    Returns combined stats dict.
    """
    from familiar.core.memory_tree import get_memory_tree

    if tree is None:
        tree = get_memory_tree()

    combined = {
        "markdown": {"imported": 0, "skipped": 0, "errors": 0},
        "brain": {"imported": 0, "skipped": 0, "errors": 0},
        "files": {"imported": 0, "skipped": 0, "errors": 0},
    }

    # Import markdown memories
    try:
        combined["markdown"] = import_markdown_memories(tree, user_id=user_id)
    except Exception as e:
        logger.warning("Markdown import failed: %s", e)
        combined["markdown"]["errors"] = 1

    # Import brain memories
    try:
        from familiar.core.memory import Memory

        mem = Memory()
        if mem.memories:
            combined["brain"] = import_brain_memories(tree, mem, user_id=user_id)
    except Exception as e:
        logger.warning("Brain import failed: %s", e)
        combined["brain"]["errors"] = 1

    # Import file metadata
    try:
        from familiar.core.files import get_file_store

        fs = get_file_store()
        combined["files"] = import_file_metadata(tree, fs, user_id=user_id)
    except Exception as e:
        logger.warning("FileStore import failed: %s", e)
        combined["files"]["errors"] = 1

    total_imported = sum(s["imported"] for s in combined.values())
    total_skipped = sum(s["skipped"] for s in combined.values())
    logger.info(
        "Import complete: %d imported, %d skipped across all sources",
        total_imported,
        total_skipped,
    )

    return combined
