"""Tests for driedfigs core functionality"""

import pytest
import matplotlib.pyplot as plt
import numpy as np
from pathlib import Path
import pickle
import tempfile
import shutil

import driedfigs as df
from driedfigs._hooks import set_active_figuredata


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


@pytest.fixture(autouse=True)
def clean_active_figure():
    """Reset active figure data before each test"""
    set_active_figuredata(None)
    yield
    set_active_figuredata(None)


class TestBasicFunctionality:
    """Test basic driedfigs functionality"""

    def test_start_figure(self):
        """Test starting a figure capture"""
        fig_data = df.start_figure("test_figure")
        assert isinstance(fig_data, df.FigureData)
        assert fig_data.figure_name == "test_figure"
        assert fig_data.is_active

    def test_capture_plot_data(self, temp_dir):
        """Test capturing data from plt.plot"""
        df.start_figure("test_plot")

        x = np.array([1, 2, 3, 4, 5])
        y = np.array([2, 4, 6, 8, 10])

        plt.figure()
        plt.plot(x, y, name="my_plot")

        # Save the data
        output_file = temp_dir / "test.pkl"
        df.save_figuredata(output_file)

        # Verify file was created and contains correct data
        assert output_file.exists()

        with open(output_file, "rb") as f:
            data = pickle.load(f)

        assert "my_plot" in data
        captured_x, captured_y = data["my_plot"]
        np.testing.assert_array_equal(captured_x, x)
        np.testing.assert_array_equal(captured_y, y)

        plt.close()

    def test_capture_multiple_plots(self, temp_dir):
        """Test capturing data from multiple plot calls"""
        df.start_figure("multi_plot")

        x1 = np.array([1, 2, 3])
        y1 = np.array([4, 5, 6])
        x2 = np.array([1, 2])
        y2 = np.array([7, 8])

        plt.figure()
        plt.plot(x1, y1, name="plot1")
        plt.plot(x2, y2, name="plot2")

        output_file = temp_dir / "test.pkl"
        df.save_figuredata(output_file)

        with open(output_file, "rb") as f:
            data = pickle.load(f)

        assert "plot1" in data
        assert "plot2" in data
        assert len(data) == 2

        plt.close()

    def test_scatter_capture(self, temp_dir):
        """Test capturing scatter plot data"""
        df.start_figure("scatter_test")

        x = np.array([1, 2, 3])
        y = np.array([4, 5, 6])

        plt.figure()
        plt.scatter(x, y, name="scatter_data")

        output_file = temp_dir / "scatter.pkl"
        df.save_figuredata(output_file)

        with open(output_file, "rb") as f:
            data = pickle.load(f)

        assert "scatter_data" in data
        captured_x, captured_y = data["scatter_data"]
        np.testing.assert_array_equal(captured_x, x)
        np.testing.assert_array_equal(captured_y, y)

        plt.close()

    def test_figuredata_save_method(self, temp_dir):
        """Test using the FigureData.save() method directly"""
        fig_data = df.start_figure("direct_save")

        x = np.array([1, 2, 3])
        y = np.array([4, 5, 6])

        plt.figure()
        plt.plot(x, y, name="plot")

        output_file = temp_dir / "direct.pkl"
        fig_data.save(output_file)

        assert output_file.exists()

        with open(output_file, "rb") as f:
            data = pickle.load(f)

        assert "plot" in data

        plt.close()


class TestErrorHandling:
    """Test error handling"""

    def test_duplicate_name_error(self):
        """Test that using the same name twice raises an error"""
        df.start_figure("test")

        plt.figure()
        plt.plot([1, 2], [3, 4], name="duplicate")

        with pytest.raises(ValueError, match="already present"):
            plt.plot([5, 6], [7, 8], name="duplicate")

        plt.close()

    def test_plot_without_name_not_captured(self, temp_dir):
        """Test that plots without 'name' parameter are not captured"""
        df.start_figure("optional_capture")

        plt.figure()
        plt.plot([1, 2], [3, 4], name="named_plot")
        plt.plot([5, 6], [7, 8])  # No name - should not be captured

        output_file = temp_dir / "test.pkl"
        df.save_figuredata(output_file)

        with open(output_file, "rb") as f:
            data = pickle.load(f)

        assert "named_plot" in data
        assert len(data) == 1  # Only the named plot

        plt.close()

    def test_save_without_active_figure(self, temp_dir):
        """Test that saving without an active figure raises an error"""
        with pytest.raises(ValueError, match="No active FigureData"):
            df.save_figuredata(temp_dir / "test.pkl")


class TestVerboseMode:
    """Test verbose mode functionality"""

    def test_verbose_prints_messages(self, capsys):
        """Test that verbose mode prints informational messages"""
        fig_data = df.start_figure("verbose_test", verbose=True)

        plt.figure()
        plt.plot([1, 2], [3, 4], name="test_plot")

        captured = capsys.readouterr()
        assert "Stored data for artist test_plot" in captured.out

        plt.close()

    def test_non_verbose_no_messages(self, capsys):
        """Test that non-verbose mode doesn't print messages"""
        fig_data = df.start_figure("silent_test", verbose=False)

        plt.figure()
        plt.plot([1, 2], [3, 4], name="test_plot")

        captured = capsys.readouterr()
        assert captured.out == ""

        plt.close()


class TestMultipleFigures:
    """Test handling multiple figures"""

    def test_multiple_figures_sequential(self, temp_dir):
        """Test creating multiple figures sequentially"""
        # First figure
        fig1 = df.start_figure("figure1")
        plt.plot([1, 2], [3, 4], name="data1")
        fig1.save(temp_dir / "fig1.pkl")

        # Second figure
        fig2 = df.start_figure("figure2")
        plt.plot([5, 6], [7, 8], name="data2")
        fig2.save(temp_dir / "fig2.pkl")

        # Verify both files
        with open(temp_dir / "fig1.pkl", "rb") as f:
            data1 = pickle.load(f)
        with open(temp_dir / "fig2.pkl", "rb") as f:
            data2 = pickle.load(f)

        assert "data1" in data1
        assert "data2" in data2
        assert "data2" not in data1  # Make sure they're separate

        plt.close('all')


class TestRepr:
    """Test string representations"""

    def test_figuredata_repr(self):
        """Test FigureData __repr__ method"""
        fig_data = df.start_figure("test")
        plt.plot([1, 2], [3, 4], name="plot1")
        plt.plot([5, 6], [7, 8], name="plot2")

        repr_str = repr(fig_data)
        assert "FigureData" in repr_str
        assert "test" in repr_str
        assert "plot1" in repr_str
        assert "plot2" in repr_str

        plt.close()
