"""
Tests for the I/O utility functions.
"""
import os
import json
import tempfile
import shutil
from pathlib import Path

import pytest

from utils.io import save_output, load_latest_output, ensure_dir, save_markdown_lesson

@pytest.fixture
def temp_dir():
    """Create a temporary directory for testing."""
    temp_dir = tempfile.mkdtemp()
    yield temp_dir
    shutil.rmtree(temp_dir)

def test_ensure_dir(temp_dir):
    """Test the ensure_dir function."""
    test_path = os.path.join(temp_dir, "test_dir", "nested_dir")

    # Ensure the directory exists
    ensure_dir(test_path)

    # Check that the directory was created
    assert os.path.exists(test_path)
    assert os.path.isdir(test_path)

def test_save_and_load_output_json(temp_dir, monkeypatch):
    """Test saving and loading output as JSON."""
    # Set up a mock output directory
    monkeypatch.setattr("utils.io.ensure_dir", lambda x: None)

    # Mock data
    test_data = {"key": "value", "nested": {"key2": "value2"}}
    pipeline = "test_pipeline"
    step = "test_step"
    run_id = "test_run"

    # Create a temporary output path
    output_dir = os.path.join(temp_dir, "output", pipeline, run_id)
    os.makedirs(output_dir, exist_ok=True)

    # Mock the output filepath to use our temporary directory
    expected_filepath = os.path.join(output_dir, f"{step}_*.json")

    def mock_save(data, pipeline, step, run_id, as_text=False, subfolder=None):
        """Mock function to save output to our temporary directory."""
        filename = f"{step}_20250101_120000.json"
        filepath = os.path.join(output_dir, filename)

        # Save the raw version too
        raw_filename = f"{step}_raw_20250101_120000.txt"
        raw_filepath = os.path.join(output_dir, raw_filename)
        with open(raw_filepath, "w", encoding="utf-8") as f:
            f.write(str(data))

        # Save the actual data
        with open(filepath, "w", encoding="utf-8") as f:
            json.dump(data, f)

        return filepath

    # Patch the save_output function
    monkeypatch.setattr("utils.io.save_output", mock_save)

    # Save the test data
    saved_path = mock_save(test_data, pipeline, step, run_id)

    # Mock glob to return our saved file
    def mock_glob(pattern):
        return [saved_path]

    monkeypatch.setattr("glob.glob", mock_glob)

    # Mock os.path.getmtime to always return the same value
    monkeypatch.setattr("os.path.getmtime", lambda x: 1)

    # Test loading the output
    loaded_data = load_latest_output(pipeline, step, run_id)

    # Check that the loaded data matches the original data
    assert loaded_data == test_data

def test_save_markdown_lesson(temp_dir, monkeypatch):
    """Test saving a markdown lesson."""
    # Set up a mock output directory
    monkeypatch.setattr("utils.io.ensure_dir", lambda x: None)

    # Mock data
    content = "# Test Lesson\n\nThis is a test lesson."
    topic = "Test Topic"
    run_id = "test_run"
    index = 1

    # Create a temporary output path
    output_dir = os.path.join(temp_dir, "output", "lessons", run_id, "lessons-markdown")
    os.makedirs(output_dir, exist_ok=True)

    # Mock the slugify function
    monkeypatch.setattr("utils.io.slugify", lambda x: x.lower().replace(" ", "-"))

    # Patch the ensure_dir function
    monkeypatch.setattr("utils.io.ensure_dir", lambda x: None)

    # Mock the save_markdown_lesson function
    def mock_save_markdown(content, topic, run_id, index):
        """Mock function to save markdown to our temporary directory."""
        slug = topic.lower().replace(" ", "-")
        filename = f"{index:02d}-{slug}.md"
        filepath = os.path.join(output_dir, filename)

        with open(filepath, "w", encoding="utf-8") as f:
            f.write(content)

        return filepath

    # Save the markdown lesson
    filepath = mock_save_markdown(content, topic, run_id, index)

    # Check that the file was created with the expected name
    expected_filename = "01-test-topic.md"
    assert os.path.basename(filepath) == expected_filename