#!/usr/bin/env nu
# Export KOGRAL to Logseq format
#
# Usage: nu kogral-export-logseq.nu <output-path> [--kogral-dir <path>] [--dry-run]

def main [
    output_path: string          # Path for Logseq graph output
    --kogral-dir: string = ".kogral"     # KOGRAL directory
    --dry-run                    # Show what would be exported without making changes
    --skip-journals              # Skip exporting journal entries
] {
    print $"(ansi green_bold)Logseq Export(ansi reset)"
    print $"Source: ($kogral_dir)"
    print $"Target: ($output_path)"

    if $dry_run {
        print $"(ansi yellow)DRY RUN MODE - No changes will be made(ansi reset)"
    }

    # Check if .kogral directory exists
    if not ($kogral_dir | path exists) {
        print $"(ansi red)Error: KOGRAL directory not found: ($kogral_dir)(ansi reset)"
        exit 1
    }

    # Count files to export
    let stats = get_export_stats $kogral_dir $skip_journals

    print $"\n(ansi cyan_bold)Files to export:(ansi reset)"
    print $"  Notes:      ($stats.notes)"
    print $"  Decisions:  ($stats.decisions)"
    print $"  Guidelines: ($stats.guidelines)"
    print $"  Patterns:   ($stats.patterns)"
    print $"  Journals:   ($stats.journals)"
    print $"  Total:      ($stats.total)"

    if $stats.total == 0 {
        print $"\n(ansi yellow)No files to export(ansi reset)"
        exit 0
    }

    if $dry_run {
        print $"\n(ansi yellow)[DRY RUN] Would export ($stats.total) files(ansi reset)"
        exit 0
    }

    # Create Logseq directory structure
    print $"\n(ansi cyan_bold)Creating Logseq directory structure...(ansi reset)"
    create_logseq_structure $output_path

    # Export files
    print $"\n(ansi cyan_bold)Exporting files...(ansi reset)"

    export_nodes $"($kogral_dir)/notes" $"($output_path)/pages" "note"
    export_nodes $"($kogral_dir)/decisions" $"($output_path)/pages" "decision"
    export_nodes $"($kogral_dir)/guidelines" $"($output_path)/pages" "guideline"
    export_nodes $"($kogral_dir)/patterns" $"($output_path)/pages" "pattern"

    if not $skip_journals {
        export_journals $"($kogral_dir)/journal" $"($output_path)/journals"
    }

    # Create Logseq config
    print $"\n(ansi cyan_bold)Creating Logseq configuration...(ansi reset)"
    create_logseq_config $output_path

    print $"\n(ansi green_bold)✓ Export completed(ansi reset)"
    print $"Exported ($stats.total) files to ($output_path)"
}

def get_export_stats [kogral_dir: string, skip_journals: bool] {
    let notes = if ($"($kogral_dir)/notes" | path exists) {
        glob $"($kogral_dir)/notes/**/*.md" | length
    } else { 0 }

    let decisions = if ($"($kogral_dir)/decisions" | path exists) {
        glob $"($kogral_dir)/decisions/**/*.md" | length
    } else { 0 }

    let guidelines = if ($"($kogral_dir)/guidelines" | path exists) {
        glob $"($kogral_dir)/guidelines/**/*.md" | length
    } else { 0 }

    let patterns = if ($"($kogral_dir)/patterns" | path exists) {
        glob $"($kogral_dir)/patterns/**/*.md" | length
    } else { 0 }

    let journals = if not $skip_journals and ($"($kogral_dir)/journal" | path exists) {
        glob $"($kogral_dir)/journal/**/*.md" | length
    } else { 0 }

    {
        notes: $notes,
        decisions: $decisions,
        guidelines: $guidelines,
        patterns: $patterns,
        journals: $journals,
        total: ($notes + $decisions + $guidelines + $patterns + $journals)
    }
}

def create_logseq_structure [output_path: string] {
    mkdir $output_path
    mkdir $"($output_path)/pages"
    mkdir $"($output_path)/journals"
    mkdir $"($output_path)/assets"
    mkdir $"($output_path)/logseq"

    print $"  (ansi green)✓ Directory structure created(ansi reset)"
}

def export_nodes [source_dir: string, target_dir: string, node_type: string] {
    if not ($source_dir | path exists) {
        return
    }

    let files = glob $"($source_dir)/**/*.md"
    if ($files | length) == 0 {
        return
    }

    print $"\n  Exporting ($node_type)s..."

    mut exported = 0
    let total = $files | length

    for file in $files {
        let filename = $file | path basename

        # Phase 1: Read KOGRAL markdown file
        let content = open $file

        # Phase 2: Convert to Logseq format
        let logseq_content = convert_kogral_to_logseq $content $node_type

        # Phase 3: Save to Logseq pages directory
        $logseq_content | save $"($target_dir)/($filename)"

        $exported = $exported + 1
    }

    print $"  (ansi green)✓ Exported ($exported)/($total) ($node_type)s(ansi reset)"
}

def export_journals [source_dir: string, target_dir: string] {
    if not ($source_dir | path exists) {
        return
    }

    let files = glob $"($source_dir)/**/*.md"
    if ($files | length) == 0 {
        return
    }

    print $"\n  Exporting journals..."

    mut exported = 0
    let total = $files | length

    for file in $files {
        let filename = $file | path basename

        # Phase 1: Read KOGRAL journal file
        let content = open $file

        # Phase 2: Convert to Logseq format
        let logseq_content = convert_kogral_to_logseq $content "journal"

        # Phase 3: Save to Logseq journals directory
        $logseq_content | save $"($target_dir)/($filename)"

        $exported = $exported + 1
    }

    print $"  (ansi green)✓ Exported ($exported)/($total) journals(ansi reset)"
}

def convert_kogral_to_logseq [content: string, node_type: string] {
    let lines = $content | lines

    # Phase 1: Check for and parse YAML frontmatter
    let has_frontmatter = ($lines | get 0 | str trim) == "---"

    if not $has_frontmatter {
        # No frontmatter, return content as-is with minimal properties
        return $"type:: ($node_type)\n\n$content"
    }

    # Phase 2: Extract frontmatter and body
    let frontmatter_end = get_frontmatter_end_index $lines
    let frontmatter_lines = $lines | take $frontmatter_end
    let body_lines = $lines | skip $frontmatter_end

    # Phase 3: Parse YAML fields
    let fm = parse_yaml_frontmatter $frontmatter_lines

    # Phase 4: Convert to Logseq properties format
    mut logseq_props = ""

    # Add type property
    $logseq_props = $logseq_props + $"type:: ($node_type)\n"

    # Add title if present
    if not ($fm.title? | is-empty) {
        $logseq_props = $logseq_props + $"title:: ($fm.title?)\n"
    }

    # Add created date if present
    if not ($fm.created? | is-empty) {
        let created_date = convert_date_to_logseq $fm.created?
        $logseq_props = $logseq_props + $"created:: [[$created_date]]\n"
    }

    # Add tags if present
    if not ($fm.tags? | is-empty) {
        $logseq_props = $logseq_props + "tags:: "
        let tags_list = $fm.tags? | str replace '\[' '' | str replace '\]' '' | split row ','
        for tag in $tags_list {
            let trimmed = $tag | str trim | str replace '"' ''
            $logseq_props = $logseq_props + $"[[($trimmed)]] "
        }
        $logseq_props = $logseq_props + "\n"
    }

    # Add status if present
    if not ($fm.status? | is-empty) {
        $logseq_props = $logseq_props + $"status:: ($fm.status?)\n"
    }

    # Add relationships if present
    if not ($fm.relates_to? | is-empty) {
        $logseq_props = $logseq_props + "relates-to:: "
        let refs = parse_yaml_list $fm.relates_to?
        let refs_formatted = $refs | each { |r| $'[[($r)]]' }
        $logseq_props = $logseq_props + ($refs_formatted | str join ", ") + "\n"
    }

    if not ($fm.depends_on? | is-empty) {
        $logseq_props = $logseq_props + "depends-on:: "
        let refs = parse_yaml_list $fm.depends_on?
        let refs_formatted = $refs | each { |r| $'[[($r)]]' }
        $logseq_props = $logseq_props + ($refs_formatted | str join ", ") + "\n"
    }

    # Phase 5: Build final output
    let body = $body_lines | str join "\n"
    $"$logseq_props\n$body"
}

def get_frontmatter_end_index [lines: list] {
    mut idx = 1  # Skip first "---"

    for line in ($lines | skip 1) {
        if ($line | str trim) == "---" {
            return ($idx + 1)
        }
        $idx = $idx + 1
    }

    $idx
}

def parse_yaml_frontmatter [lines: list] {
    mut fm = {}

    for line in $lines {
        if ($line | str trim) == "---" {
            continue
        }

        # Match YAML key: value format
        if ($line =~ '^[\w]+:') {
            let key = $line | str replace '^(\w+):.*' '$1'
            let value = $line | str replace '^[\w]+:\s*' '' | str trim
            $fm = ($fm | insert $key $value)
        }
    }

    $fm
}

def convert_date_to_logseq [date_str: string] {
    # Convert ISO 8601 (2026-01-17T10:30:00Z) to Logseq format (Jan 17th, 2026)
    # For simplicity, extract date part and format
    let date_part = $date_str | str substring 0..10
    let year = $date_part | str substring 0..4
    let month = $date_part | str substring 5..7
    let day = $date_part | str substring 8..10 | str replace '^0+' ''

    let month_name = match $month {
        "01" => "Jan",
        "02" => "Feb",
        "03" => "Mar",
        "04" => "Apr",
        "05" => "May",
        "06" => "Jun",
        "07" => "Jul",
        "08" => "Aug",
        "09" => "Sep",
        "10" => "Oct",
        "11" => "Nov",
        "12" => "Dec",
        _ => "Unknown"
    }

    let day_suffix = match ($day | into int) {
        1 | 21 | 31 => "st",
        2 | 22 => "nd",
        3 | 23 => "rd",
        _ => "th"
    }

    $"($month_name) ($day)($day_suffix), ($year)"
}

def parse_yaml_list [yaml_str: string] {
    # Parse YAML list format: [item1, item2] or list format with dashes
    # For now, handle bracket format
    let cleaned = $yaml_str | str replace '\[' '' | str replace '\]' ''
    let items = $cleaned | split row ',' | map { |i| $i | str trim | str replace '"' '' }
    $items
}

def create_logseq_config [output_path: string] {
    let config = {
        "preferred-format": "markdown",
        "preferred-workflow": ":now",
        "hidden": [".git"],
        "journal/page-title-format": "yyyy-MM-dd",
        "start-of-week": 1,
        "feature/enable-block-timestamps": false,
        "feature/enable-search-remove-accents": true
    }

    $config | to json | save $"($output_path)/logseq/config.edn"
    print $"  (ansi green)✓ Logseq configuration created(ansi reset)"
}
