using ClawdDotNet.Core.Storage;
using ClawdDotNet.Core.Tasks;
using Microsoft.Extensions.Logging.Abstractions;
using Shouldly;

namespace ClawdDotNet.Core.Tests.Tasks;

/// <summary>
/// Schritt 4: die Übernahme der alten <c>coordination/*.md</c>-Dateien. Geprüft an den
/// tatsächlichen Altformaten (freies Markdown, kein Frontmatter). Kernanspruch: nur echte
/// Aufgaben (<c>task_*</c>) wandern ins Board, alles andere bleibt unangetastet, und die
/// Migration ist idempotent.
/// </summary>
public sealed class CoordinationMigrationTests : IDisposable
{
    private readonly string _directory;
    private readonly string _coordinationDir;
    private readonly SqliteStorage _storage;
    private readonly SqliteTaskRepository _repo;
    private readonly TaskboardService _board;
    private readonly CoordinationMigration _migration;

    public CoordinationMigrationTests()
    {
        _directory = Path.Combine(Path.GetTempPath(), "clawd-tests", Guid.NewGuid().ToString("N"));
        var shared = Path.Combine(_directory, "SharedWorkspace");
        _coordinationDir = Path.Combine(shared, "coordination");
        Directory.CreateDirectory(_coordinationDir);

        _storage = new SqliteStorage(Path.Combine(_directory, "state.db"));
        _repo = new SqliteTaskRepository(_storage);
        _board = new TaskboardService(_repo, Path.Combine(shared, "tasks"));
        _migration = new CoordinationMigration(_board, _coordinationDir, NullLoggerFactory.Instance);
    }

    public void Dispose()
    {
        Microsoft.Data.Sqlite.SqliteConnection.ClearAllPools();
        try { Directory.Delete(_directory, recursive: true); }
        catch { /* Aufräumen ist Nebensache */ }
    }

    private void Write(string name, string content)
        => File.WriteAllText(Path.Combine(_coordinationDir, name), content);

    [Fact]
    public async Task Nur_task_Dateien_werden_uebernommen()
    {
        Write("task_video.md", "# Task: Video-Zusammenfassung\n## Status: ASSIGNED\nAnalysiere das Video.");
        Write("status_senior.md", "# Senior Developer - Status\n## Status: ONLINE");
        Write("broadcast.md", "# Broadcast\nBitte meldet euren Status.");
        Write("incident_x.md", "# Incident Report\nProblem-Chain ...");
        Write("data.json", "{ \"foo\": 1 }");

        var migrated = await _migration.RunAsync(default);

        migrated.ShouldBe(1);
        var tasks = await _repo.ListAsync(new TaskQuery { IncludeArchived = true }, default);
        tasks.Count.ShouldBe(1);
        tasks[0].Title.ShouldBe("Video-Zusammenfassung");
        tasks[0].Status.ShouldBe(TaskItemStatus.Backlog, "erst nach menschlicher Sichtung bereit");
        tasks[0].Assignee.ShouldBe(TaskAssignee.Human);
        tasks[0].Body.ShouldContain("Analysiere das Video.");
    }

    [Fact]
    public async Task Die_uebernommene_Datei_wandert_nach_migrated_und_bleibt_erhalten()
    {
        Write("task_a.md", "# Task: Etwas\nInhalt.");

        await _migration.RunAsync(default);

        File.Exists(Path.Combine(_coordinationDir, "task_a.md")).ShouldBeFalse("aus der obersten Ebene entfernt");
        File.Exists(Path.Combine(_coordinationDir, "migrated", "task_a.md")).ShouldBeTrue("aber nicht gelöscht");
    }

    [Fact]
    public async Task Nicht_Aufgaben_bleiben_unangetastet()
    {
        Write("status_x.md", "# Status\nONLINE");
        Write("report.json", "{}");

        await _migration.RunAsync(default);

        File.Exists(Path.Combine(_coordinationDir, "status_x.md")).ShouldBeTrue();
        File.Exists(Path.Combine(_coordinationDir, "report.json")).ShouldBeTrue();
        (await _repo.CountAsync(default)).ShouldBe(0);
    }

    [Fact]
    public async Task Die_Migration_ist_idempotent()
    {
        Write("task_a.md", "# Task: Einmalig\nInhalt.");

        (await _migration.RunAsync(default)).ShouldBe(1);
        (await _migration.RunAsync(default)).ShouldBe(0, "zweiter Lauf findet keine task_*-Datei mehr");

        (await _repo.CountAsync(default)).ShouldBe(1, "keine Dublette");
    }

    [Fact]
    public async Task Ohne_Task_Ueberschrift_kommt_der_Titel_aus_dem_Dateinamen()
    {
        Write("task_video_analysis_progress.md", "## Status: IN PROGRESS\nOhne echte Überschrift.");

        await _migration.RunAsync(default);

        var tasks = await _repo.ListAsync(new TaskQuery(), default);
        tasks[0].Title.ShouldBe("video analysis progress");
    }

    [Fact]
    public async Task Ohne_coordination_Verzeichnis_passiert_nichts()
    {
        Directory.Delete(_coordinationDir, recursive: true);
        (await _migration.RunAsync(default)).ShouldBe(0);
    }
}
