"""Tests for headerfile class functionality."""

import os
from unittest.mock import patch

from secbulkdownload.secmeta import headerfile


class TestHeaderPathComputation:
    """Test header path computation logic."""

    def test_header_path_structure(self, datadir: str) -> None:
        """Test that header paths follow the expected structure."""
        sec_filename = "edgar/data/0000320193/0000320193-23-000077.txt"
        hdr = headerfile(sec_filename, datadir=datadir, user_agent="Test Co test@test.com")

        # Expected local path: <datadir>/headerfiles/<CIK>/<accession>.hdr.sgml
        expected_local = os.path.join(
            datadir, "headerfiles", "0000320193", "0000320193-23-000077.hdr.sgml"
        )
        assert hdr.localpath == expected_local

    def test_header_url_structure(self, datadir: str) -> None:
        """Test that header URLs are correctly constructed."""
        sec_filename = "edgar/data/0000320193/0000320193-23-000077.txt"
        hdr = headerfile(sec_filename, datadir=datadir, user_agent="Test Co test@test.com")

        # Expected URL: http://www.sec.gov/Archives/edgar/data/<CIK>/<accession_no_hyphens>/<accession>.hdr.sgml
        expected_url = (
            "http://www.sec.gov/Archives/edgar/data/0000320193/"
            "000032019323000077/0000320193-23-000077.hdr.sgml"
        )
        assert hdr.url == expected_url

    def test_accession_without_hyphens_in_url(self, datadir: str) -> None:
        """Test that accession numbers in URLs have hyphens removed."""
        sec_filename = "edgar/data/0000320193/0000320193-23-000077.txt"
        hdr = headerfile(sec_filename, datadir=datadir, user_agent="Test Co test@test.com")

        # Verify the URL has hyphens removed from accession in the middle path segment
        assert "/000032019323000077/" in hdr.url

    def test_islocal_false_when_not_cached(self, datadir: str) -> None:
        """Test that islocal is False when file doesn't exist."""
        sec_filename = "edgar/data/0000320193/0000320193-23-000077.txt"
        hdr = headerfile(sec_filename, datadir=datadir, user_agent="Test Co test@test.com")
        
        assert hdr.islocal is False

    def test_islocal_true_when_cached(self, datadir: str) -> None:
        """Test that islocal is True when file exists."""
        sec_filename = "edgar/data/0000320193/0000320193-23-000077.txt"
        
        # Create the cached file
        header_dir = os.path.join(datadir, "headerfiles", "0000320193")
        os.makedirs(header_dir, exist_ok=True)
        cached_path = os.path.join(header_dir, "0000320193-23-000077.hdr.sgml")
        with open(cached_path, "w", encoding="latin-1") as f:
            f.write("<SEC-HEADER>test</SEC-HEADER>")
        
        hdr = headerfile(sec_filename, datadir=datadir, user_agent="Test Co test@test.com")
        
        assert hdr.islocal is True


class TestSGMLParsing:
    """Test SGML parsing to dictionary."""

    def test_sgml_parsing_to_dict(self, datadir: str) -> None:
        """Test that SGML header is correctly parsed to dict."""
        sec_filename = "edgar/data/0000320193/0000320193-23-000077.txt"
        
        # Create a mock SGML header file
        header_dir = os.path.join(datadir, "headerfiles", "0000320193")
        os.makedirs(header_dir, exist_ok=True)
        cached_path = os.path.join(header_dir, "0000320193-23-000077.hdr.sgml")
        
        sgml_content = """<SEC-HEADER>
<ACCEPTANCE-DATETIME>20230101
<ACCESSION-NUMBER>0000320193-23-000077
<TYPE>10-K
<ITEMS>
<ITEM>4
</ITEMS>
<COMPANY-DATA>
<CIK>0000320193
<CONFORMED-NAME>Apple Inc.
</COMPANY-DATA>
</SEC-HEADER>"""
        
        with open(cached_path, "w", encoding="latin-1") as f:
            f.write(sgml_content)
        
        hdr = headerfile(sec_filename, datadir=datadir, user_agent="Test Co test@test.com")
        result = hdr._SGMLfiletoDict()
        
        # Verify parsed structure
        assert "SEC-HEADER" in result or result.get("TYPE") == "10-K"
        assert isinstance(result, dict)

    def test_sgml_with_nested_containers(self, datadir: str) -> None:
        """Test SGML parsing with nested container elements."""
        sec_filename = "edgar/data/0000320193/0000320193-23-000077.txt"
        
        header_dir = os.path.join(datadir, "headerfiles", "0000320193")
        os.makedirs(header_dir, exist_ok=True)
        cached_path = os.path.join(header_dir, "0000320193-23-000077.hdr.sgml")
        
        sgml_content = """<SEC-HEADER>
<COMPANY-DATA>
<CIK>0000320193
<CONFORMED-NAME>Apple Inc.
<ASSIGNED-SIC>3571
</COMPANY-DATA>
<FILING-VALUES>
<FORM-TYPE>10-K
<ACCESSION-NUMBER>0000320193-23-000077
</FILING-VALUES>
</SEC-HEADER>"""
        
        with open(cached_path, "w", encoding="latin-1") as f:
            f.write(sgml_content)
        
        hdr = headerfile(sec_filename, datadir=datadir, user_agent="Test Co test@test.com")
        result = hdr._SGMLfiletoDict()
        
        assert isinstance(result, dict)

    def test_sgml_ampersand_handling(self, datadir: str) -> None:
        """Test that ampersands are replaced for XML parsing."""
        sec_filename = "edgar/data/0000320193/0000320193-23-000077.txt"
        
        header_dir = os.path.join(datadir, "headerfiles", "0000320193")
        os.makedirs(header_dir, exist_ok=True)
        cached_path = os.path.join(header_dir, "0000320193-23-000077.hdr.sgml")
        
        # SGML with ampersand that needs handling
        sgml_content = """<SEC-HEADER>
<COMPANY-NAME>Johnson & Johnson
<ACCESSION-NUMBER>0000320193-23-000077
</SEC-HEADER>"""
        
        with open(cached_path, "w", encoding="latin-1") as f:
            f.write(sgml_content)
        
        hdr = headerfile(sec_filename, datadir=datadir, user_agent="Test Co test@test.com")
        result = hdr._SGMLfiletoDict()
        
        # Should not raise XML parsing error
        assert isinstance(result, dict)


class TestHeaderFetch:
    """Test header file fetching."""

    def test_get_header_dict_fetches_if_missing(self, datadir: str) -> None:
        """Test that get_headerDict fetches file if not local."""
        sec_filename = "edgar/data/0000320193/0000320193-23-000077.txt"

        with (
            patch.object(headerfile, "fetch_file") as mock_fetch,
            patch.object(headerfile, "_SGMLfiletoDict") as mock_parse,
        ):
            mock_parse.return_value = {"TYPE": "10-K"}

            hdr = headerfile(sec_filename, datadir=datadir, user_agent="Test Co test@test.com")
            # File doesn't exist locally
            assert hdr.islocal is False

            # get_headerDict should call fetch_file
            result = hdr.get_headerDict()

            mock_fetch.assert_called_once()
            assert result == {"TYPE": "10-K"}

    def test_fetch_file_calls_fetch_sec_file(self, datadir: str) -> None:
        """Test that fetch_file calls fetch_sec_file with correct args."""
        sec_filename = "edgar/data/0000320193/0000320193-23-000077.txt"
        
        with patch("secbulkdownload.secmeta.fetch_sec_file") as mock_fetch:
            hdr = headerfile(sec_filename, datadir=datadir, user_agent="Test Co test@test.com")
            hdr.fetch_file()
            
            mock_fetch.assert_called_once_with(
                hdr.url,
                hdr.localpath,
                content=False,
                limiter=hdr.limiter,
                user_agent=hdr.user_agent,
                verbose=False,
            )


class TestLocalCacheReuse:
    """Test local cache reuse functionality."""

    def test_cached_file_reused(self, datadir: str) -> None:
        """Test that cached header file is reused without network call."""
        sec_filename = "edgar/data/0000320193/0000320193-23-000077.txt"
        
        # Create cached file
        header_dir = os.path.join(datadir, "headerfiles", "0000320193")
        os.makedirs(header_dir, exist_ok=True)
        cached_path = os.path.join(header_dir, "0000320193-23-000077.hdr.sgml")
        
        sgml_content = """<SEC-HEADER>
<TYPE>10-K
<ACCESSION-NUMBER>0000320193-23-000077
</SEC-HEADER>"""
        
        with open(cached_path, "w", encoding="latin-1") as f:
            f.write(sgml_content)
        
        hdr = headerfile(sec_filename, datadir=datadir, user_agent="Test Co test@test.com")
        
        # File should be local
        assert hdr.islocal is True
        
        # get_headerDict should not call fetch_file
        with patch.object(hdr, "fetch_file") as mock_fetch:
            result = hdr.get_headerDict()
            mock_fetch.assert_not_called()
            assert isinstance(result, dict)

    def test_cache_invalidation_on_clear(self, datadir: str) -> None:
        """Test that cache state is properly tracked."""
        sec_filename = "edgar/data/0000320193/0000320193-23-000077.txt"
        
        # First, no cache
        hdr = headerfile(sec_filename, datadir=datadir, user_agent="Test Co test@test.com")
        assert hdr.islocal is False
        
        # Create cache file
        header_dir = os.path.join(datadir, "headerfiles", "0000320193")
        os.makedirs(header_dir, exist_ok=True)
        cached_path = os.path.join(header_dir, "0000320193-23-000077.hdr.sgml")
        with open(cached_path, "w", encoding="latin-1") as f:
            f.write("<SEC-HEADER>test</SEC-HEADER>")
        
        # New instance should see cache
        hdr2 = headerfile(sec_filename, datadir=datadir, user_agent="Test Co test@test.com")
        assert hdr2.islocal is True
