"""
Tests for importing multiple text columns from CSV files.

This module tests the ability to specify multiple text columns when importing
CSV files, supporting both comma-separated values and multiple flag usage.
"""

import os
import tempfile

import pandas as pd
import pytest

from src.crisp_t.read_data import ReadData


def test_multiple_text_columns_comma_separated():
    """Test importing multiple text columns using comma-separated string."""
    with tempfile.TemporaryDirectory() as tmpdir:
        csv_path = os.path.join(tmpdir, "test_multi.csv")
        df = pd.DataFrame(
            {
                "id": [1, 2, 3],
                "note1": ["First note col1", "Second note col1", "Third note col1"],
                "note2": ["Additional col2", "More details col2", "Extra info col2"],
                "note3": ["Data col3", "Info col3", "Text col3"],
                "score": [85, 92, 78],
            }
        )
        df.to_csv(csv_path, index=False)

        reader = ReadData()
        corpus = reader.read_csv_to_corpus(
            csv_path,
            comma_separated_text_columns="note1,note2,note3",
            id_column="id",
        )

        # Verify corpus was created
        assert corpus is not None, "Corpus should not be None"
        assert len(corpus.documents) == 3, "Should create one document per row"

        # Verify texts from all columns are concatenated
        assert (
            "First note col1" in corpus.documents[0].text
        ), "Should contain text from note1"
        assert (
            "Additional col2" in corpus.documents[0].text
        ), "Should contain text from note2"
        assert "Data col3" in corpus.documents[0].text, "Should contain text from note3"

        # Verify second document
        assert (
            "Second note col1" in corpus.documents[1].text
        ), "Should contain text from note1"
        assert (
            "More details col2" in corpus.documents[1].text
        ), "Should contain text from note2"
        assert "Info col3" in corpus.documents[1].text, "Should contain text from note3"

        # Verify DataFrame has only numeric columns
        assert isinstance(reader.df, pd.DataFrame), "DataFrame should be set"
        assert "note1" not in reader.df.columns, "Text columns should be removed from df"
        assert "note2" not in reader.df.columns, "Text columns should be removed from df"
        assert "note3" not in reader.df.columns, "Text columns should be removed from df"
        assert "score" in reader.df.columns, "Numeric columns should remain in df"


def test_multiple_text_columns_with_spaces():
    """Test that spaces in comma-separated column names are handled correctly."""
    with tempfile.TemporaryDirectory() as tmpdir:
        csv_path = os.path.join(tmpdir, "test_multi.csv")
        df = pd.DataFrame(
            {
                "id": [1, 2],
                "note1": ["Text 1", "Text 2"],
                "note2": ["Info 1", "Info 2"],
                "value": [10, 20],
            }
        )
        df.to_csv(csv_path, index=False)

        reader = ReadData()
        # Test with spaces around commas
        corpus = reader.read_csv_to_corpus(
            csv_path,
            comma_separated_text_columns="note1, note2",  # Space after comma
            id_column="id",
        )

        assert corpus is not None, "Corpus should be created"
        assert len(corpus.documents) == 2, "Should create documents"
        # Verify that both columns are included (spaces should be stripped)
        assert "Text 1" in corpus.documents[0].text, "Should contain text from note1"
        assert "Info 1" in corpus.documents[0].text, "Should contain text from note2"
        assert "Text 2" in corpus.documents[1].text, "Should contain text from note1"
        assert "Info 2" in corpus.documents[1].text, "Should contain text from note2"


def test_single_text_column_backward_compatibility():
    """Test that single text column import still works (backward compatibility)."""
    with tempfile.TemporaryDirectory() as tmpdir:
        csv_path = os.path.join(tmpdir, "test_single.csv")
        df = pd.DataFrame(
            {
                "id": [1, 2, 3],
                "comments": [
                    "This is comment one",
                    "This is comment two",
                    "This is comment three",
                ],
                "rating": [4, 5, 3],
            }
        )
        df.to_csv(csv_path, index=False)

        reader = ReadData()
        corpus = reader.read_csv_to_corpus(
            csv_path,
            comma_separated_text_columns="comments",  # Single column
            id_column="id",
        )

        assert corpus is not None, "Corpus should not be None"
        assert len(corpus.documents) == 3, "Should create one document per row"
        assert (
            "This is comment one" in corpus.documents[0].text
        ), "Should contain comment text"
        assert (
            "comments" not in reader.df.columns
        ), "Text column should be removed from df"
        assert "rating" in reader.df.columns, "Numeric column should remain in df"


def test_text_columns_with_none_values():
    """Test handling of None/NaN values in text columns."""
    with tempfile.TemporaryDirectory() as tmpdir:
        csv_path = os.path.join(tmpdir, "test_none.csv")
        df = pd.DataFrame(
            {
                "id": [1, 2, 3],
                "note1": ["Text 1", None, "Text 3"],
                "note2": ["Info 1", "Info 2", None],
                "value": [10, 20, 30],
            }
        )
        df.to_csv(csv_path, index=False)

        reader = ReadData()
        corpus = reader.read_csv_to_corpus(
            csv_path,
            comma_separated_text_columns="note1,note2",
            id_column="id",
        )

        assert corpus is not None, "Corpus should handle None values"
        assert len(corpus.documents) == 3, "Should create documents despite None values"

        # Check that None values don't appear in text
        for doc in corpus.documents:
            assert "None" not in doc.text or doc.text.strip() != "None", (
                "None values should be handled gracefully"
            )


def test_text_columns_with_nan_values():
    """Test handling of NaN values in text columns."""
    with tempfile.TemporaryDirectory() as tmpdir:
        csv_path = os.path.join(tmpdir, "test_nan.csv")
        df = pd.DataFrame(
            {
                "id": [1, 2, 3],
                "note1": ["Text 1", float("nan"), "Text 3"],
                "note2": ["Info 1", "Info 2", float("nan")],
                "value": [10, 20, 30],
            }
        )
        df.to_csv(csv_path, index=False)

        reader = ReadData()
        corpus = reader.read_csv_to_corpus(
            csv_path,
            comma_separated_text_columns="note1,note2",
            id_column="id",
        )

        assert corpus is not None, "Corpus should handle NaN values"
        assert len(corpus.documents) == 3, "Should create documents despite NaN values"


def test_empty_text_columns():
    """Test handling of empty string values in text columns."""
    with tempfile.TemporaryDirectory() as tmpdir:
        csv_path = os.path.join(tmpdir, "test_empty.csv")
        df = pd.DataFrame(
            {
                "id": [1, 2, 3],
                "note1": ["Text 1", "", "Text 3"],
                "note2": ["", "Info 2", ""],
                "value": [10, 20, 30],
            }
        )
        df.to_csv(csv_path, index=False)

        reader = ReadData()
        corpus = reader.read_csv_to_corpus(
            csv_path,
            comma_separated_text_columns="note1,note2",
            id_column="id",
        )

        assert corpus is not None, "Corpus should handle empty strings"
        assert len(corpus.documents) == 3, "Should create documents despite empty values"


def test_nonexistent_text_column():
    """Test that nonexistent column names are handled gracefully."""
    with tempfile.TemporaryDirectory() as tmpdir:
        csv_path = os.path.join(tmpdir, "test_nonexistent.csv")
        df = pd.DataFrame(
            {
                "id": [1, 2],
                "note1": ["Text 1", "Text 2"],
                "value": [10, 20],
            }
        )
        df.to_csv(csv_path, index=False)

        reader = ReadData()
        # Request nonexistent column
        corpus = reader.read_csv_to_corpus(
            csv_path,
            comma_separated_text_columns="note1,nonexistent_column",
            id_column="id",
        )

        # Should still create corpus with available columns
        assert corpus is not None, "Corpus should be created"
        assert len(corpus.documents) == 2, "Should create documents"


def test_text_column_ordering():
    """Test that text from columns is concatenated in the specified order."""
    with tempfile.TemporaryDirectory() as tmpdir:
        csv_path = os.path.join(tmpdir, "test_order.csv")
        df = pd.DataFrame(
            {
                "id": [1],
                "col_a": ["AAA"],
                "col_b": ["BBB"],
                "col_c": ["CCC"],
            }
        )
        df.to_csv(csv_path, index=False)

        reader = ReadData()
        corpus = reader.read_csv_to_corpus(
            csv_path,
            comma_separated_text_columns="col_a,col_b,col_c",
            id_column="id",
        )

        # Check order in the concatenated text
        text = corpus.documents[0].text
        assert text.find("AAA") < text.find("BBB"), "col_a should come before col_b"
        assert text.find("BBB") < text.find("CCC"), "col_b should come before col_c"


def test_multiple_text_columns_with_ignore_words():
    """Test that ignore words are removed from all text columns."""
    with tempfile.TemporaryDirectory() as tmpdir:
        csv_path = os.path.join(tmpdir, "test_ignore.csv")
        df = pd.DataFrame(
            {
                "id": [1],
                "note1": ["This is test text"],
                "note2": ["Another test phrase"],
                "value": [10],
            }
        )
        df.to_csv(csv_path, index=False)

        reader = ReadData()
        corpus = reader.read_csv_to_corpus(
            csv_path,
            comma_separated_ignore_words="test",
            comma_separated_text_columns="note1,note2",
            id_column="id",
        )

        # Check that "test" is removed from the text
        text = corpus.documents[0].text.lower()
        assert "test" not in text, "Ignore words should be removed from all text columns"


def test_max_rows_with_multiple_columns():
    """Test that max_rows parameter works with multiple text columns."""
    with tempfile.TemporaryDirectory() as tmpdir:
        csv_path = os.path.join(tmpdir, "test_maxrows.csv")
        df = pd.DataFrame(
            {
                "id": [1, 2, 3, 4, 5],
                "note1": ["Text 1", "Text 2", "Text 3", "Text 4", "Text 5"],
                "note2": ["Info 1", "Info 2", "Info 3", "Info 4", "Info 5"],
                "value": [10, 20, 30, 40, 50],
            }
        )
        df.to_csv(csv_path, index=False)

        reader = ReadData()
        corpus = reader.read_csv_to_corpus(
            csv_path,
            comma_separated_text_columns="note1,note2",
            id_column="id",
            max_rows=3,  # Limit to 3 rows
        )

        assert len(corpus.documents) == 3, "Should respect max_rows limit"


def test_timestamp_extraction_with_multiple_columns():
    """Test that timestamp extraction works with multiple text columns."""
    with tempfile.TemporaryDirectory() as tmpdir:
        csv_path = os.path.join(tmpdir, "test_timestamp.csv")
        df = pd.DataFrame(
            {
                "id": [1],
                "note1": ["Document created on 2025-01-15"],
                "note2": ["Additional information"],
                "timestamp": ["2025-01-15T10:30:00"],
            }
        )
        df.to_csv(csv_path, index=False)

        reader = ReadData()
        corpus = reader.read_csv_to_corpus(
            csv_path,
            comma_separated_text_columns="note1,note2",
            id_column="id",
            timestamp_column="timestamp",
        )

        assert corpus.documents[0].timestamp is not None, (
            "Timestamp should be extracted"
        )
        assert "2025-01-15" in corpus.documents[0].timestamp, (
            "Timestamp should be from timestamp column"
        )
