<?php
// phpcs:disable
declare(strict_types=1);

namespace IronKanban\Tests;

use IronKanban\Markdown\FrontMatterParser;
use IronKanban\Repository\TaskRepository;
use IronKanban\Support\IdGenerator;
use IronKanban\Support\Paths;
use IronKanban\Support\TaskMapper;
use PHPUnit\Framework\TestCase;

class TaskRepositoryTest extends TestCase {
    private string $tempRoot;

    protected function setUp(): void {
        parent::setUp();

        $this->tempRoot = sys_get_temp_dir() . '/ironkanban-test-' . bin2hex(random_bytes(4));
        mkdir($this->tempRoot, 0775, true);
        mkdir($this->tempRoot . '/sample-project', 0775, true);
        mkdir($this->tempRoot . '/sample-project/tasks', 0775, true);
    }

    protected function tearDown(): void {
        $this->deleteDirectory($this->tempRoot);
        parent::tearDown();
    }

    public function testCreateWritesTaskFileAndCanReadItBack(): void {
        $repo = $this->makeRepository();

        $task = $repo->create([
            'projectId' => 'sample-project',
            'title' => 'Build parser',
            'body' => "Task body",
            'column' => 'doing',
            'priority' => 'high',
        ]);

        $this->assertSame('Build parser', $task->title);
        $this->assertSame('doing', $task->column);
        $this->assertSame('high', $task->priority);
        $this->assertFileExists($this->tempRoot . '/sample-project/tasks/' . $task->fileName);

        $loaded = $repo->get('sample-project', $task->id);

        $this->assertSame($task->id, $loaded->id);
        $this->assertSame('Build parser', $loaded->title);
        $this->assertSame('Task body', $loaded->body);
        $this->assertSame($task->fileName, $loaded->fileName);
    }

    public function testPreservesLegacyFilenameWhenReadingAndSaving(): void {
        $contents = <<<MD
        ---
        id: custom-task-id
        type: task
        title: Legacy Task
        project_id: sample-project
        section: Back Burner
        priority: normal
        completed: false
        is_active: true
        created: 2026-03-01T00:00:00+00:00
        updated: 2026-03-01T00:00:00+00:00
        legacy_key: keep-me
        ---

        Legacy body
        MD;

        $legacyPath = $this->tempRoot . '/sample-project/tasks/task-legacy-import.md';
        file_put_contents($legacyPath, $contents);

        $repo = $this->makeRepository();
        $task = $repo->get('sample-project', 'custom-task-id');

        $this->assertSame('task-legacy-import.md', $task->fileName);
        $this->assertSame('back-burner', $task->column);
        $this->assertSame('keep-me', $task->meta['legacy_key']);

        $task->title = 'Legacy Task Updated';
        $repo->save($task);

        $this->assertFileExists($legacyPath);
        $this->assertStringContainsString('Legacy Task Updated', (string) file_get_contents($legacyPath));
        $this->assertStringContainsString('legacy_key: keep-me', (string) file_get_contents($legacyPath));
    }

    public function testDeleteRemovesUnderlyingFile(): void {
        $repo = $this->makeRepository();

        $task = $repo->create([
            'projectId' => 'sample-project',
            'title' => 'Delete me',
        ]);

        $filePath = $this->tempRoot . '/sample-project/tasks/' . $task->fileName;

        $this->assertFileExists($filePath);

        $repo->delete('sample-project', $task->id);

        $this->assertFileDoesNotExist($filePath);
    }

    private function makeRepository(): TaskRepository {
        return new TaskRepository(
            new Paths($this->tempRoot),
            new FrontMatterParser(),
            new TaskMapper(),
            new IdGenerator()
        );
    }

    private function deleteDirectory(string $path): void {
        if (!is_dir($path)) {
            return;
        }

        $items = scandir($path);

        if ($items === false) {
            return;
        }

        foreach ($items as $item) {
            if ($item === '.' || $item === '..') {
                continue;
            }

            $itemPath = $path . DIRECTORY_SEPARATOR . $item;

            if (is_dir($itemPath) && !is_link($itemPath)) {
                $this->deleteDirectory($itemPath);
                continue;
            }

            @unlink($itemPath);
        }

        @rmdir($path);
    }
}
// phpcs:enable
