"""
Main initialization module for Synapsis DSAI Agent Rules.

This module provides the core functionality for initializing agent rules by
copying template directories (.agent, .agents, .claude, .cursor, .github) from the package
into the user's current working directory.

Functions:
    run(): Main entry point for the initialization CLI tool.
"""

import shutil
import sys
import argparse
import re
from pathlib import Path
from importlib.resources import files

# Marker to identify files managed by this tool at the user side
MANAGED_MARKER = "<!-- synapsis-dsai-managed -->"

# Tuple of template folder names that will be initialized
FOLDERS_TO_INIT = (".agent", ".agents", ".claude", ".cursor", ".github")

# Files that need the core block injection
STANDALONE_FILES = ("GEMINI.md", "CLAUDE.md", "AGENTS.md", ".cursorrules")

START_MARKER = "<!-- synapsis-dsai-core-start -->"
END_MARKER = "<!-- synapsis-dsai-core-end -->"

# Extensions that should be treated as text and receive markers
TEXT_EXTENSIONS = {'.md', '.mdc', '.txt', '.json', '.yaml', '.yml', '.py', '.sh', '.ps1'}


def _get_template_path() -> Path:
    """
    Retrieve the path to the package's templates directory.
    """
    return files("dsai_synapsis_agent_init") / "templates"


def _update_standalone_file(target_path: Path, template_block: str) -> None:
    """
    Safely injects or updates the Synapsis Core Block in a standalone file.
    """
    file_name = target_path.name
    
    if not target_path.exists():
        try:
            target_path.write_text(template_block, encoding="utf-8")
            print(f"✅ Berhasil membuat {file_name}")
            return
        except Exception as e:
            print(f"❌ Gagal membuat {file_name}: {e}")
            return

    content = target_path.read_text(encoding="utf-8")
    
    start_idx = content.find(START_MARKER)
    end_idx = content.find(END_MARKER)

    if start_idx != -1 and end_idx != -1:
        if start_idx > end_idx:
            print(f"⚠️  Marker di {file_name} rusak (Start setelah End). Melewati auto-update.")
            return
            
        new_content = content[:start_idx] + template_block.strip() + content[end_idx + len(END_MARKER):]
        if content != new_content:
            target_path.write_text(new_content, encoding="utf-8")
            print(f"🔄 Berhasil memperbarui blok standar di {file_name}")
        else:
            print(f"✨ Blok standar di {file_name} sudah versi terbaru.")
    elif start_idx == -1 and end_idx == -1:
        new_content = content.rstrip() + "\n\n" + template_block.strip() + "\n"
        target_path.write_text(new_content, encoding="utf-8")
        print(f"➕ Berhasil menambahkan blok standar ke {file_name}")
    else:
        print(f"⚠️  Tag pembatas di {file_name} tidak lengkap. Melewati auto-update untuk keamanan.")


def _inject_managed_marker(content: str, file_name: str) -> str:
    """
    Injects the managed marker into the content based on file type.
    """
    if MANAGED_MARKER in content:
        return content

    # For SKILL.md with frontmatter, insert after the second ---
    if file_name == "SKILL.md" and content.lstrip().startswith("---"):
        match = re.search(r'^(---.*?---\s*)', content, re.DOTALL)
        if match:
            sep_end = match.end()
            return content[:sep_end] + MANAGED_MARKER + "\n" + content[sep_end:].lstrip()
    
    return MANAGED_MARKER + "\n" + content


def _sync_file(source: Path, destination: Path, verbose: bool = False) -> None:
    """
    Syncs a single file from source to destination.
    Distinguishes between Text (with markers) and Binary (direct copy).
    """
    rel_path = destination.name
    # Ensure source is treated as a Path to get suffix
    source_path = Path(str(source))
    suffix = source_path.suffix.lower()
    
    is_text = suffix in TEXT_EXTENSIONS or rel_path == ".cursorrules"

    if is_text:
        try:
            source_raw_content = source_path.read_text(encoding="utf-8")
            target_content = _inject_managed_marker(source_raw_content, rel_path)
        except Exception as e:
            # If UTF-8 fails, treat as binary fallback
            is_text = False

    if is_text:
        if not destination.exists():
            destination.parent.mkdir(parents=True, exist_ok=True)
            destination.write_text(target_content, encoding="utf-8")
            if verbose: print(f"🆕 Created: {rel_path}")
            return

        try:
            dest_current = destination.read_text(encoding="utf-8")
            if MANAGED_MARKER in dest_current:
                if dest_current.strip() != target_content.strip():
                    destination.write_text(target_content, encoding="utf-8")
                    if verbose: print(f"🔄 Updating managed file: {rel_path}")
                elif verbose: print(f"✨ Already up-to-date: {rel_path}")
            else:
                if verbose: print(f"⏭️  Skipping customized file: {rel_path}")
        except Exception as e:
            print(f"❌ Error syncing text {rel_path}: {e}")
    else:
        # Binary file (assets, images, etc.) - Direct copy
        try:
            destination.parent.mkdir(parents=True, exist_ok=True)
            # Use shutil.copy2 to preserve metadata and handle binary
            shutil.copy2(str(source_path), str(destination))
            if verbose: print(f"✨ Synced asset: {rel_path}")
        except Exception as e:
            print(f"❌ Gagal menyalin asset {rel_path}: {e}")


def _sync_template_folder(source: Path, destination: Path, folder_name: str, verbose: bool = False) -> None:
    """
    Recursively syncs a template folder using the ownership marker system.
    """
    source_path = Path(str(source))
    if not source_path.exists():
        print(f"⚠️  Template {folder_name} tidak ditemukan di dalam package.")
        return

    destination.mkdir(parents=True, exist_ok=True)
    for src_file in source_path.rglob('*'):
        if src_file.is_file():
            rel_path = src_file.relative_to(source_path)
            dest_file = destination / rel_path
            _sync_file(src_file, dest_file, verbose)

    print(f"✅ Berhasil memproses {folder_name}")


def run() -> None:
    """
    Initialize Synapsis DSAI Agent Rules in the current working directory.
    """
    parser = argparse.ArgumentParser(description="Initialize Synapsis DSAI Agent Rules.")
    parser.add_argument("--verbose", action="store_true", help="Show detailed sync information.")
    args = parser.parse_args()

    print("🚀 [Synapsis DSAI] Initializing agent rules...")

    try:
        template_base = _get_template_path()
    except Exception as e:
        print(f"❌ Error internal: {e}")
        sys.exit(1)
        return
        
    current_work_dir = Path.cwd()

    if not (current_work_dir / ".git").exists():
        print("⚠️  Direktori .git tidak ditemukan. Pastikan Anda menjalankan ini di root repository.")

    for folder_name in FOLDERS_TO_INIT:
        source = template_base / folder_name
        destination = current_work_dir / folder_name
        _sync_template_folder(source, destination, folder_name, args.verbose)

    try:
        core_block_path = template_base / "standalone" / "core-rules-block.md"
        if core_block_path.exists():
            template_block = core_block_path.read_text(encoding="utf-8")
            for file_name in STANDALONE_FILES:
                target_path = current_work_dir / file_name
                _update_standalone_file(target_path, template_block)
        else:
            print("⚠️  Template standalone tidak ditemukan. Melewati pembaruan file tunggal.")
    except Exception as e:
        print(f"❌ Gagal memproses file standalone: {e}")

    print("\n✨ Berhasil! Tim sekarang bisa mulai bekerja dengan standar Agent Skills, Rules & Standalone Templates DS-AI Synapsis.")


if __name__ == "__main__":
    run()
