"""
Test content type detection functionality.

This test suite validates the ability of the ContentTypeInterpreter
to correctly identify various file formats and content types.
"""

import logging
import os
import tempfile

import pytest

from mcard.model.interpreter import ContentTypeInterpreter

# Setup logging
logging.basicConfig(level=logging.DEBUG)
logger = logging.getLogger(__name__)

# Sample content for different file types
SAMPLE_DATA = {
    # Plain text
    "plain_text": {
        "content": "This is a sample text file.\nIt contains multiple lines\nof plain text data\nfor testing purposes.",
        "expected_mime": "text/plain",
        "expected_ext": "txt",
    },
    # Python
    "python": {
        "content": """#!/usr/bin/env python3
import os
import sys

def hello_world():
    print("Hello, world!")

if __name__ == "__main__":
    hello_world()
""",
        "expected_mime": "text/x-python",
        "expected_ext": "py",
    },
    # CSV
    "csv": {
        "content": """Name,Age,Email
John Doe,30,john@example.com
Jane Smith,25,jane@example.com
Bob Johnson,40,bob@example.com""",
        "expected_mime": "text/csv",
        "expected_ext": "csv",
    },
    # JSON
    "json": {
        "content": """{
  "users": [
    {
      "name": "John Doe",
      "age": 30,
      "email": "john@example.com"
    },
    {
      "name": "Jane Smith",
      "age": 25,
      "email": "jane@example.com"
    }
  ]
}""",
        "expected_mime": "application/json",
        "expected_ext": "json",
    },
    # XML
    "xml": {
        "content": """<?xml version="1.0" encoding="UTF-8"?>
<users>
  <user>
    <name>John Doe</name>
    <age>30</age>
    <email>john@example.com</email>
  </user>
  <user>
    <name>Jane Smith</name>
    <age>25</age>
    <email>jane@example.com</email>
  </user>
</users>""",
        "expected_mime": "application/xml",
        "expected_ext": "xml",
    },
    # HTML
    "html": {
        "content": """<!DOCTYPE html>
<html>
<head>
    <title>Sample HTML Page</title>
</head>
<body>
    <h1>Hello, World!</h1>
    <p>This is a sample HTML page.</p>
</body>
</html>""",
        "expected_mime": "text/html",
        "expected_ext": "html",
    },
    # Markdown
    "markdown": {
        "content": """# Sample Markdown

## Introduction
This is a sample Markdown file.

## Features
- Easy to read
- Easy to write
- Supports formatting

## Code Example
```python
def hello_world():
    print("Hello, world!")
```""",
        "expected_mime": "text/markdown",
        "expected_ext": "md",
    },
    # YAML
    "yaml": {
        "content": """---
users:
  - name: John Doe
    age: 30
    email: john@example.com
  - name: Jane Smith
    age: 25
    email: jane@example.com
settings:
  theme: dark
  notifications: true
""",
        "expected_mime": "application/x-yaml",
        "expected_ext": "yaml",
    },
    # JavaScript
    "javascript": {
        "content": """// Sample JavaScript file
function helloWorld() {
  console.log("Hello, world!");
}

const user = {
  name: "John",
  age: 30,
  sayHello: function() {
    console.log(`Hello, my name is ${this.name}`);
  }
};

helloWorld();
user.sayHello();""",
        "expected_mime": "text/javascript",
        "expected_ext": "js",
    },
    # OBJ (3D model)
    "obj": {
        "content": """# Sample OBJ file
v 0.000000 1.000000 0.000000
v 1.000000 0.000000 0.000000
v 0.000000 0.000000 1.000000
v 0.000000 0.000000 0.000000
vn 0.3333 0.6667 0.6667
vn 0.6667 0.3333 0.6667
vn 0.6667 0.6667 0.3333
s off
f 1//1 2//1 3//1
f 1//2 3//2 4//2
f 1//3 4//3 2//3
f 2//4 4//4 3//4""",
        "expected_mime": "application/3d-obj",
        "expected_ext": "obj",
    },
    # SQL
    "sql": {
        "content": """-- Sample SQL file
CREATE TABLE users (
    id INT PRIMARY KEY,
    name VARCHAR(100),
    email VARCHAR(100),
    age INT
);

INSERT INTO users (id, name, email, age)
VALUES (1, 'John Doe', 'john@example.com', 30);

SELECT * FROM users WHERE age > 25;""",
        "expected_mime": "text/x-sql",
        "expected_ext": "sql",
    },
}


class TestContentTypeDetection:
    """Test suite for content type detection functionality."""

    @pytest.fixture
    def interpreter(self):
        """Create a ContentTypeInterpreter instance."""
        return ContentTypeInterpreter()

    @pytest.mark.parametrize("content_type", SAMPLE_DATA.keys())
    def test_content_detection_from_string(self, interpreter, content_type):
        """Test detection from string content."""
        data = SAMPLE_DATA[content_type]
        content = data["content"]
        expected_mime = data["expected_mime"]
        expected_ext = data["expected_ext"]

        logger.info(f"Testing content type detection for: {content_type}")

        # Detect content type and extension
        file_extension = (
            expected_ext if expected_ext.startswith(".") else f".{expected_ext}"
        )
        mime_type, ext = interpreter.detect_content_type(
            content, file_extension=file_extension
        )

        logger.info(f"Detected MIME type: {mime_type}, extension: {ext}")
        logger.info(f"Expected MIME type: {expected_mime}, extension: {expected_ext}")

        # Assert that the detected MIME type and extension match expected values
        assert (
            mime_type == expected_mime
        ), f"Expected {expected_mime} but got {mime_type} for {content_type}"
        assert (
            ext == expected_ext
        ), f"Expected {expected_ext} but got {ext} for {content_type}"

    @pytest.mark.parametrize("content_type", SAMPLE_DATA.keys())
    def test_content_detection_from_bytes(self, interpreter, content_type):
        """Test detection from bytes content."""
        data = SAMPLE_DATA[content_type]
        content = data["content"].encode("utf-8")  # Convert to bytes
        expected_mime = data["expected_mime"]
        expected_ext = data["expected_ext"]

        logger.info(f"Testing binary content type detection for: {content_type}")

        # Detect content type and extension
        file_extension = (
            expected_ext if expected_ext.startswith(".") else f".{expected_ext}"
        )
        mime_type, ext = interpreter.detect_content_type(
            content, file_extension=file_extension
        )

        logger.info(f"Detected MIME type: {mime_type}, extension: {ext}")

        # Assert that the detected MIME type and extension match expected values
        assert (
            mime_type == expected_mime
        ), f"Expected {expected_mime} but got {mime_type} for {content_type} (binary)"
        assert (
            ext == expected_ext
        ), f"Expected {expected_ext} but got {ext} for {content_type} (binary)"

    @pytest.mark.parametrize("content_type", SAMPLE_DATA.keys())
    def test_content_detection_with_file_extension(self, interpreter, content_type):
        """Test detection with file extension hints."""
        data = SAMPLE_DATA[content_type]
        content = data["content"]
        expected_mime = data["expected_mime"]
        expected_ext = data["expected_ext"]

        # Create a temporary file with the expected extension
        with tempfile.NamedTemporaryFile(suffix=expected_ext) as temp_file:
            # Write the content to the file
            temp_file.write(content.encode("utf-8"))
            temp_file.flush()

            # Read the file content
            # Note: We don't need to read the content here since detect_content_type is called with file_extension
            # Keeping this part of the test structure for potential future use

            logger.info(
                f"Testing file-based detection for: {content_type} with extension {expected_ext}"
            )

            # Get file extension
            file_extension = os.path.splitext(temp_file.name)[1]
            logger.info(f"File extension: {file_extension}")

            # For testing purposes, directly call the registry with the file extension
            from mcard.model.detectors.registry import registry

            mime_type = registry.detect(
                content_sample=content,
                lines=content.split("\n"),
                first_line=content.split("\n")[0] if content else "",
                file_extension=file_extension,
            )
            ext = interpreter.get_extension(mime_type)

            logger.info(f"Detected MIME type: {mime_type}, extension: {ext}")

            # Assert that the detected MIME type and extension match expected values
            assert (
                mime_type == expected_mime
            ), f"Expected {expected_mime} but got {mime_type} for {content_type} (with extension)"
            assert (
                ext == expected_ext
            ), f"Expected {expected_ext} but got {ext} for {content_type} (with extension)"

    def test_ambiguous_content_detection(self, interpreter):
        """Test detection of ambiguous content that could be interpreted multiple ways."""
        # CSV-like content that's actually just plain text
        ambiguous_csv = "This is a line with, some, commas\nAnd another, similar, line"
        mime_type, ext = interpreter.detect_content_type(ambiguous_csv)
        logger.info(f"Ambiguous CSV-like content detected as: {mime_type}")
        assert (
            mime_type == "text/plain"
        ), f"Ambiguous CSV should be detected as text/plain, got {mime_type}"

        # Python-like content that should not be interpreted as OBJ
        python_code = "v = 1.0\nfor i in range(10):\n    print(f'Value: {v*i}')"
        mime_type, ext = interpreter.detect_content_type(python_code)
        logger.info(f"Python-like content detected as: {mime_type}")
        assert (
            mime_type == "text/x-python"
        ), f"Python code should be detected as text/x-python, got {mime_type}"

        # JSON-like content that's actually Python dictionary
        python_dict = "{\n    'name': 'John',\n    'age': 30,\n    'languages': ['Python', 'JavaScript']\n}"
        mime_type, ext = interpreter.detect_content_type(python_dict)
        logger.info(f"Python dict content detected as: {mime_type}")
        assert mime_type in [
            "text/x-python",
            "text/plain",
        ], f"Python dict should be detected as Python or plain text, got {mime_type}"


if __name__ == "__main__":
    pytest.main(["-xvs", __file__])
