<?php

declare(strict_types=1);

namespace Core\Mod\Agentic\Console\Commands;

use Core\Mod\Agentic\Services\BrainService;
use Illuminate\Console\Command;

/**
 * Import MEMORY.md files from Claude Code project memory directories
 * into the OpenBrain knowledge store.
 *
 * Scans Claude Code project memory directories (~/.claude/projects)
 * for MEMORY.md and topic-specific markdown files, parses them into
 * individual memories, and stores each via BrainService::remember().
 */
class BrainSeedMemoryCommand extends Command
{
    protected $signature = 'brain:seed-memory
        {--workspace= : Workspace ID to import into (required)}
        {--agent=virgil : Agent ID to attribute memories to}
        {--path= : Override scan path (default: ~/.claude/projects/*/memory/)}
        {--dry-run : Preview what would be imported without storing}';

    protected $description = 'Import MEMORY.md files from Claude Code project memory into OpenBrain';

    public function handle(BrainService $brain): int
    {
        $workspaceId = $this->option('workspace');
        if (! $workspaceId) {
            $this->error('--workspace is required. Pass the workspace ID to import memories into.');

            return self::FAILURE;
        }

        $agentId = $this->option('agent') ?? 'virgil';
        $isDryRun = (bool) $this->option('dry-run');

        $scanPath = $this->option('path')
            ?? $this->expandHome('~/.claude/projects/*/memory/');

        $files = glob($scanPath.'*.md');
        if (empty($files)) {
            $this->info("No markdown files found in: {$scanPath}");

            return self::SUCCESS;
        }

        $this->info(sprintf('Found %d markdown file(s) to process.', count($files)));

        if (! $isDryRun) {
            $brain->ensureCollection();
        }

        $imported = 0;
        $skipped = 0;

        foreach ($files as $file) {
            $filename = basename($file, '.md');
            $project = $this->extractProject($file);
            $sections = $this->parseMarkdownSections($file);

            if (empty($sections)) {
                $this->line("  Skipped {$filename} (no sections found)");
                $skipped++;

                continue;
            }

            foreach ($sections as $section) {
                $type = $this->inferType($section['heading'], $section['content']);

                if ($isDryRun) {
                    $this->line(sprintf(
                        '  [DRY RUN] %s :: %s (%s) — %d chars',
                        $filename,
                        $section['heading'],
                        $type,
                        strlen($section['content']),
                    ));
                    $imported++;

                    continue;
                }

                try {
                    $brain->remember([
                        'workspace_id' => (int) $workspaceId,
                        'agent_id' => $agentId,
                        'type' => $type,
                        'content' => $section['heading']."\n\n".$section['content'],
                        'tags' => $this->extractTags($section['heading'], $filename),
                        'project' => $project,
                        'confidence' => 0.7,
                    ]);
                    $imported++;
                } catch (\Throwable $e) {
                    $this->warn("  Failed to import '{$section['heading']}': {$e->getMessage()}");
                    $skipped++;
                }
            }
        }

        $prefix = $isDryRun ? '[DRY RUN] ' : '';
        $this->info("{$prefix}Imported {$imported} memories, skipped {$skipped}.");

        return self::SUCCESS;
    }

    /**
     * Parse a markdown file into sections based on ## headings.
     *
     * @return array<array{heading: string, content: string}>
     */
    private function parseMarkdownSections(string $filePath): array
    {
        $content = file_get_contents($filePath);
        if ($content === false || trim($content) === '') {
            return [];
        }

        $sections = [];
        $lines = explode("\n", $content);
        $currentHeading = '';
        $currentContent = [];

        foreach ($lines as $line) {
            if (preg_match('/^#{1,3}\s+(.+)$/', $line, $matches)) {
                if ($currentHeading !== '' && ! empty($currentContent)) {
                    $sections[] = [
                        'heading' => $currentHeading,
                        'content' => trim(implode("\n", $currentContent)),
                    ];
                }
                $currentHeading = trim($matches[1]);
                $currentContent = [];
            } else {
                $currentContent[] = $line;
            }
        }

        // Flush last section
        if ($currentHeading !== '' && ! empty($currentContent)) {
            $text = trim(implode("\n", $currentContent));
            if ($text !== '') {
                $sections[] = [
                    'heading' => $currentHeading,
                    'content' => $text,
                ];
            }
        }

        return $sections;
    }

    /**
     * Extract a project name from the file path.
     *
     * Paths like ~/.claude/projects/-Users-snider-Code-eaas/memory/MEMORY.md
     * yield "eaas".
     */
    private function extractProject(string $filePath): ?string
    {
        if (preg_match('/projects\/[^\/]*-([^-\/]+)\/memory\//', $filePath, $matches)) {
            return $matches[1];
        }

        return null;
    }

    /**
     * Infer the memory type from the heading and content.
     */
    private function inferType(string $heading, string $content): string
    {
        $lower = strtolower($heading.' '.$content);

        $patterns = [
            'architecture' => ['architecture', 'stack', 'infrastructure', 'layer', 'service mesh'],
            'convention' => ['convention', 'standard', 'naming', 'pattern', 'rule', 'coding'],
            'decision' => ['decision', 'chose', 'strategy', 'approach', 'domain'],
            'bug' => ['bug', 'fix', 'broken', 'error', 'issue', 'lesson'],
            'plan' => ['plan', 'todo', 'roadmap', 'milestone', 'phase'],
            'research' => ['research', 'finding', 'discovery', 'analysis', 'rfc'],
        ];

        foreach ($patterns as $type => $keywords) {
            foreach ($keywords as $keyword) {
                if (str_contains($lower, $keyword)) {
                    return $type;
                }
            }
        }

        return 'observation';
    }

    /**
     * Extract topic tags from the heading and filename.
     *
     * @return array<string>
     */
    private function extractTags(string $heading, string $filename): array
    {
        $tags = [];

        if ($filename !== 'MEMORY') {
            $tags[] = str_replace(['-', '_'], ' ', $filename);
        }

        $tags[] = 'memory-import';

        return $tags;
    }

    /**
     * Expand ~ to the user's home directory.
     */
    private function expandHome(string $path): string
    {
        if (str_starts_with($path, '~/')) {
            $home = getenv('HOME') ?: ('/Users/'.get_current_user());

            return $home.substr($path, 1);
        }

        return $path;
    }
}
