#!/usr/bin/env python3
"""Validate StarPost terminal-friendly Markdown tables."""

from __future__ import annotations

import argparse
import re
from pathlib import Path


PIPE_TABLE_ROW = re.compile(r"^\s*\|.*\|\s*$")
MAX_TABLE_WIDTH = 72


def markdown_files(paths: list[str]) -> list[Path]:
    if paths:
        return [Path(value) for value in paths]
    return sorted(
        path
        for path in Path.cwd().rglob("*.md")
        if not any(part.startswith(".") for part in path.parts)
    )


def validate_table(path: Path, number: int, lines: list[str]) -> list[str]:
    errors: list[str] = []
    widths = {len(line) for line in lines}

    if len(widths) != 1:
        errors.append(f"table {number} has inconsistent widths: {sorted(widths)}")
        return errors

    width = widths.pop()
    if width > MAX_TABLE_WIDTH:
        errors.append(
            f"table {number} is {width} characters wide; maximum is {MAX_TABLE_WIDTH}"
        )

    if not lines[0].startswith("┌") or not lines[0].endswith("┐"):
        errors.append(f"table {number} has an incomplete top border")
        return errors

    if not lines[-1].startswith("└") or not lines[-1].endswith("┘"):
        errors.append(f"table {number} has an incomplete bottom border")

    column_count = lines[0].count("┬") + 1
    rows = [line for line in lines if line.startswith("│")]
    separators = [line for line in lines if line.startswith("├")]

    for row_index, row in enumerate(rows, start=1):
        if row.count("│") != column_count + 1:
            errors.append(
                f"table {number} row {row_index} is missing a vertical inner border"
            )

    expected_separators = max(0, len(rows) - 1)
    if len(separators) != expected_separators:
        errors.append(
            f"table {number} requires {expected_separators} horizontal inner borders; "
            f"found {len(separators)}"
        )

    if any("\t" in line for line in lines):
        errors.append(f"table {number} contains a tab character")

    return errors


def validate_file(path: Path) -> tuple[int, list[str]]:
    text = path.read_text(encoding="utf-8")
    errors: list[str] = []

    for line_number, line in enumerate(text.splitlines(), start=1):
        if PIPE_TABLE_ROW.match(line):
            errors.append(
                f"line {line_number} uses a Markdown pipe table; use a fenced Unicode table"
            )

    in_text_fence = False
    block: list[str] = []
    table_count = 0

    for line in [*text.splitlines(), "```END"]:
        if line == "```text":
            in_text_fence = True
            block = []
            continue

        if in_text_fence and line.startswith("```"):
            if block and block[0].startswith("┌"):
                table_count += 1
                errors.extend(validate_table(path, table_count, block))
            in_text_fence = False
            block = []
            continue

        if in_text_fence:
            block.append(line)

    lines = text.splitlines()
    index = 0
    while index < len(lines):
        if not lines[index].startswith("    ┌"):
            index += 1
            continue

        indented_table: list[str] = []
        while index < len(lines) and lines[index].startswith("    "):
            candidate = lines[index][4:]
            if not candidate or candidate[0] not in "┌├└│":
                break
            indented_table.append(candidate)
            index += 1

        if indented_table:
            table_count += 1
            errors.extend(validate_table(path, table_count, indented_table))
        else:
            index += 1

    return table_count, errors


def main() -> int:
    parser = argparse.ArgumentParser(
        description="Validate StarPost fixed-width Markdown tables."
    )
    parser.add_argument("paths", nargs="*", help="Markdown files; defaults to all")
    arguments = parser.parse_args()

    files = markdown_files(arguments.paths)
    failed = False

    for path in files:
        table_count, errors = validate_file(path)
        if errors:
            failed = True
            for error in errors:
                print(f"ERROR: {path}: {error}")
        elif table_count:
            print(f"OK: {path}: {table_count} intact table(s)")

    if failed:
        return 1

    print("FINAL RESULT: MARKDOWN TABLES ARE INTACT")
    return 0


if __name__ == "__main__":
    raise SystemExit(main())
