"""
Unit tests for DocumentToHtmlConverter.

Tests Word document conversion including format normalization and LibreOffice integration.
"""

import pytest
from pathlib import Path
from unittest.mock import patch, MagicMock
from src.extraction_v2.document_converter import DocumentToHtmlConverter


class TestDocumentToHtmlConverter:
    """Test suite for DocumentToHtmlConverter class."""

    def test_init(self):
        """Test converter initialization."""
        converter = DocumentToHtmlConverter()
        assert converter.converter is not None
        assert converter._last_doc is None
        assert converter._last_sheet_names == []

    def test_convert_to_html_routes_excel(self):
        """Test that Excel files are routed to Excel converter."""
        converter = DocumentToHtmlConverter()

        with patch.object(converter, '_convert_excel_to_html', return_value="<html>test</html>") as mock_excel:
            result = converter.convert_to_html("test.xlsx")
            mock_excel.assert_called_once_with("test.xlsx")
            assert result == "<html>test</html>"

    def test_convert_to_html_routes_word(self):
        """Test that Word files are routed to Word converter."""
        converter = DocumentToHtmlConverter()

        with patch.object(converter, '_convert_word_to_markdown', return_value="# Test") as mock_word:
            result = converter.convert_to_html("test.docx")
            mock_word.assert_called_once_with("test.docx")
            assert result == "# Test"

    def test_convert_to_html_unsupported_format(self):
        """Test that unsupported file formats return None."""
        converter = DocumentToHtmlConverter()
        result = converter.convert_to_html("test.pdf")
        assert result is None

    def test_validate_word_file_success(self):
        """Test Word file validation with valid .docx file."""
        converter = DocumentToHtmlConverter()

        # Create a mock Path object
        mock_path = MagicMock(spec=Path)
        mock_path.exists.return_value = True
        mock_path.suffix = ".docx"
        mock_path.stat.return_value = MagicMock(st_size=1024 * 1024)  # 1MB

        # Mock zipfile for .docx validation
        with patch('zipfile.ZipFile') as mock_zipfile:
            mock_zip = MagicMock()
            mock_zip.namelist.return_value = ['word/document.xml', 'word/styles.xml']
            mock_zipfile.return_value.__enter__.return_value = mock_zip

            is_valid, error_msg = converter._validate_word_file(mock_path)

        assert is_valid is True
        assert error_msg is None

    def test_validate_word_file_not_found(self):
        """Test Word file validation with non-existent file."""
        converter = DocumentToHtmlConverter()

        mock_path = MagicMock(spec=Path)
        mock_path.exists.return_value = False

        is_valid, error_msg = converter._validate_word_file(mock_path)

        assert is_valid is False
        assert error_msg == "File not found"

    def test_validate_word_file_too_large(self):
        """Test Word file validation with file over 100MB."""
        converter = DocumentToHtmlConverter()

        mock_path = MagicMock(spec=Path)
        mock_path.exists.return_value = True
        mock_path.suffix = ".docx"
        mock_path.stat.return_value = MagicMock(st_size=150 * 1024 * 1024)  # 150MB

        is_valid, error_msg = converter._validate_word_file(mock_path)

        assert is_valid is False
        assert "too large" in error_msg

    def test_validate_word_file_unsupported_extension(self):
        """Test Word file validation with unsupported extension."""
        converter = DocumentToHtmlConverter()

        mock_path = MagicMock(spec=Path)
        mock_path.exists.return_value = True
        mock_path.suffix = ".pdf"
        mock_path.stat.return_value = MagicMock(st_size=1024 * 1024)  # 1MB

        is_valid, error_msg = converter._validate_word_file(mock_path)

        assert is_valid is False
        assert "Unsupported format" in error_msg

    def test_validate_word_file_corrupted_docx(self):
        """Test Word file validation with corrupted .docx file."""
        converter = DocumentToHtmlConverter()

        mock_path = MagicMock(spec=Path)
        mock_path.exists.return_value = True
        mock_path.suffix = ".docx"
        mock_path.stat.return_value = MagicMock(st_size=1024 * 1024)  # 1MB

        # Mock zipfile to raise BadZipFile exception
        with patch('zipfile.ZipFile', side_effect=Exception("Bad ZIP")):
            is_valid, error_msg = converter._validate_word_file(mock_path)

        assert is_valid is False
        assert "File validation error" in error_msg

    def test_convert_doc_to_docx_libreoffice_not_found(self):
        """Test .doc conversion when LibreOffice is not installed."""
        converter = DocumentToHtmlConverter()

        with patch.object(converter, '_find_libreoffice_command', return_value=None):
            result = converter._convert_doc_to_docx(Path("test.doc"))

        assert result is None

    def test_convert_doc_to_docx_timeout(self):
        """Test .doc conversion timeout handling."""
        converter = DocumentToHtmlConverter()

        with patch.object(converter, '_find_libreoffice_command', return_value='libreoffice'):
            with patch('subprocess.run', side_effect=Exception("Timeout")):
                result = converter._convert_doc_to_docx(Path("test.doc"))

        assert result is None

    @pytest.mark.parametrize("extension", ['.xlsx', '.xls', '.xlsm'])
    def test_excel_extensions_routed_correctly(self, extension):
        """Test that all Excel extensions are routed to Excel converter."""
        converter = DocumentToHtmlConverter()

        with patch.object(converter, '_convert_excel_to_html', return_value="<html>test</html>") as mock_excel:
            converter.convert_to_html(f"test{extension}")
            assert mock_excel.called

    @pytest.mark.parametrize("extension", ['.docx', '.doc', '.docm'])
    def test_word_extensions_routed_correctly(self, extension):
        """Test that all Word extensions are routed to Word converter."""
        converter = DocumentToHtmlConverter()

        with patch.object(converter, '_convert_word_to_markdown', return_value="# Test") as mock_word:
            converter.convert_to_html(f"test{extension}")
            assert mock_word.called


class TestConvenienceFunctions:
    """Test suite for convenience functions."""

    def test_convert_excel_to_html(self):
        """Test convert_excel_to_html convenience function."""
        from src.extraction_v2.document_converter import convert_excel_to_html

        with patch.object(DocumentToHtmlConverter, 'convert_to_html', return_value="<html>test</html>"):
            result = convert_excel_to_html("test.xlsx")
            assert result == "<html>test</html>"

    def test_convert_word_to_markdown(self):
        """Test convert_word_to_markdown convenience function."""
        from src.extraction_v2.document_converter import convert_word_to_markdown

        with patch.object(DocumentToHtmlConverter, 'convert_to_html', return_value="# Test"):
            result = convert_word_to_markdown("test.docx")
            assert result == "# Test"
