"""Sheet parsing - converts files to Sheet objects."""

import logging
from pathlib import Path

import yaml

from .models import Sheet, PanelSpec, CodeSection, SheetStyle

logger = logging.getLogger(__name__)


class SheetParser:
    """Parses sheet files into Sheet objects."""

    def parse(self, path: Path, sheet_type: str = "reference") -> Sheet | None:
        """Parse a sheet file based on explicit type.

        Args:
            path: Path to sheet file
            sheet_type: Type of sheet ("reference" or "code")

        Returns:
            Sheet or None if parsing fails
        """
        if not path.exists():
            logger.warning(f"Sheet file not found: {path}")
            return None

        if sheet_type == "reference":
            return self._parse_yaml(path)
        elif sheet_type == "code":
            return self._parse_code(path)
        else:
            logger.error(f"Unknown sheet type: {sheet_type}")
            return None

    def _parse_yaml(self, path: Path) -> Sheet | None:
        """Parse a YAML reference sheet.

        Args:
            path: Path to YAML file

        Returns:
            Sheet or None if parsing fails
        """
        try:
            with open(path) as f:
                data = yaml.safe_load(f)

            name = data.get("name", path.stem)
            mode = data.get("mode", "reference")

            # Parse style section if present
            style_data = data.get("style", {})
            style = SheetStyle(
                border_color=style_data.get("border_color", "cyan"),
                title_color=style_data.get("title_color", "bright_white"),
                key_color=style_data.get("key_color", "bright_cyan"),
                desc_color=style_data.get("desc_color", "white"),
            )

            sections = []
            for section_data in data.get("sections", []):
                spec = PanelSpec(
                    title=section_data.get("title", section_data.get("name", "")),
                    size=section_data.get("size", "full"),
                    base=section_data.get("base"),
                    items=section_data.get("items", []),
                )

                if len(spec.items) > spec.max_items:
                    logger.warning(
                        f"Section '{spec.title}' has {len(spec.items)} items, "
                        f"truncating to {spec.max_items}"
                    )
                    spec.items = spec.items[: spec.max_items]

                sections.append(spec)

            return Sheet(name=name, mode=mode, sections=sections, style=style)

        except yaml.YAMLError as e:
            logger.error(f"Failed to parse YAML {path}: {e}")
            return None
        except Exception as e:
            logger.error(f"Unexpected error parsing {path}: {e}")
            return None

    def _parse_code(self, path: Path) -> Sheet | None:
        """Parse a code file with @section: markers.

        Args:
            path: Path to code file

        Returns:
            Sheet with code sections or None if parsing fails
        """
        try:
            content = path.read_text()
            lines = content.splitlines()

            mode = "code"
            sections = []
            current_section = None
            current_code = []

            for line in lines:
                if "@mode:" in line:
                    mode_value = line.split("@mode:")[1].strip()
                    if mode_value:
                        mode = mode_value

                elif "@section:" in line:
                    if current_section:
                        current_section["code"] = "\n".join(current_code).strip()
                        sections.append(
                            CodeSection(
                                name=current_section["name"],
                                title=current_section.get(
                                    "title", current_section["name"]
                                ),
                                code=current_section["code"],
                                size=current_section.get("size", "medium"),  # type: ignore[arg-type]
                                language=path.suffix[1:],
                            )
                        )

                    section_name = line.split("@section:")[1].strip()
                    current_section = {"name": section_name}
                    current_code = []

                elif "@title:" in line and current_section:
                    current_section["title"] = line.split("@title:")[1].strip()

                elif "@size:" in line and current_section:
                    size_value = line.split("@size:")[1].strip()
                    if size_value in ("small", "medium", "large"):
                        current_section["size"] = size_value

                elif current_section:
                    current_code.append(line)

            if current_section:
                current_section["code"] = "\n".join(current_code).strip()
                sections.append(
                    CodeSection(
                        name=current_section["name"],
                        title=current_section.get("title", current_section["name"]),
                        code=current_section["code"],
                        size=current_section.get("size", "medium"),  # type: ignore[arg-type]
                        language=path.suffix[1:],
                    )
                )

            if not sections:
                logger.warning(f"No sections found in code file: {path}")
                return None

            return Sheet(
                name=path.stem,
                mode=mode,  # type: ignore[arg-type]
                sections=sections,
                language=path.suffix[1:],
            )

        except FileNotFoundError:
            logger.error(f"Code file not found: {path}")
            return None
        except Exception as e:
            logger.error(f"Unexpected error parsing code file {path}: {e}")
            return None
