"""
XLSX parser — uses openpyxl in read_only mode for memory-efficient streaming.

Each worksheet becomes a section. Each worksheet is emitted as a table:simple element.
Merged cells are expanded with the first cell's value.
"""

from __future__ import annotations

from collections.abc import Iterator

from .base import BaseParser, FileRecord, RawElement


def _build_markdown(headers: list[str], rows: list[list[str]]) -> str:
    if not headers and not rows:
        return ""
    all_rows = ([headers] if headers else []) + rows
    col_count = max(len(r) for r in all_rows) if all_rows else 0
    lines: list[str] = []
    if headers:
        lines.append("| " + " | ".join(str(c) for c in headers) + " |")
        lines.append("|" + "|".join("---" for _ in range(col_count)) + "|")
    for row in rows:
        padded = list(row) + [""] * max(0, col_count - len(row))
        lines.append("| " + " | ".join(str(c) if c is not None else "" for c in padded) + " |")
    return "\n".join(lines)


class XLSXParser(BaseParser):
    handles = [
        ("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", None),
        ("application/vnd.ms-excel", None),
    ]

    def parse(self, file_record: FileRecord) -> Iterator[RawElement]:
        try:
            import openpyxl  # type: ignore[import-untyped]
        except ImportError as e:
            raise ImportError("openpyxl required: pip install openpyxl") from e

        wb = openpyxl.load_workbook(str(file_record.path), read_only=True, data_only=True)
        try:
            for sheet_name in wb.sheetnames:
                ws = wb[sheet_name]

                # Emit sheet name as section heading
                yield RawElement(
                    element_type="structural:section_header",
                    text=sheet_name,
                    heading_level=1,
                    detection_tier=1,
                    extra={
                        "extraction_method": "openpyxl:sheet",
                        "confidence": 1.0,
                    },
                )

                # Collect all rows
                all_rows: list[list[str]] = []
                for row in ws.iter_rows(values_only=True):
                    all_rows.append([str(cell) if cell is not None else "" for cell in row])

                if not all_rows:
                    # Empty sheet — emit warning element
                    yield RawElement(
                        element_type="meta:extraction_error",
                        text=f"Sheet '{sheet_name}' is empty",
                        extra={
                            "extraction_method": "openpyxl:sheet",
                            "confidence": 1.0,
                        },
                    )
                    continue

                # First row as headers
                headers = all_rows[0]
                data_rows = all_rows[1:]

                markdown = _build_markdown(headers, data_rows)

                yield RawElement(
                    element_type="table:simple",
                    text=markdown,
                    table_data={
                        "markdown": markdown,
                        "structured": {"headers": headers, "rows": data_rows},
                        "has_header_row": True,
                        "row_count": len(data_rows),
                        "header_row_count": 1,
                        "col_count": len(headers),
                    },
                    extra={
                        "extraction_method": "openpyxl:worksheet",
                        "confidence": 0.95,
                        "style_name": sheet_name,
                    },
                )
        finally:
            wb.close()
