from __future__ import annotations

import re
from collections import Counter
from typing import Any

from .rendering import PLACEHOLDER_PATTERN


EXCEL_FORBIDDEN_CHARS = re.compile(r"[\[\]:*?/\\]")
MAX_SHEET_NAME_LEN = 31


def _duplicates(values: list[str]) -> list[str]:
    return sorted(value for value, count in Counter(values).items() if count > 1)


def validate_template_data(data: dict[str, Any]) -> list[str]:
    errors: list[str] = []
    forms = data.get("forms", [])

    form_ids = [form.get("form_id", "") for form in forms]
    for form_id in _duplicates(form_ids):
        errors.append(f"Duplicate form_id: {form_id}")

    sheet_names = [form.get("sheet_name") or form.get("template_sheet", "") for form in forms]
    for sheet_name in _duplicates(sheet_names):
        errors.append(f"Duplicate sheet_name: {sheet_name}")
    for sheet_name in sheet_names:
        if not sheet_name:
            errors.append("Missing sheet_name/template_sheet")
        if len(sheet_name) > MAX_SHEET_NAME_LEN:
            errors.append(f"Sheet name too long: {sheet_name}")
        if EXCEL_FORBIDDEN_CHARS.search(sheet_name):
            errors.append(f"Sheet name has forbidden Excel characters: {sheet_name}")

    global_defaults = data.get("global_defaults", {})
    for form in forms:
        form_id = form.get("form_id", "<unknown>")
        form_defaults = form.get("defaults") or form.get("procedure_defaults") or {}
        field_keys = {field.get("key") for field in form.get("fields", [])}
        available_keys = field_keys | set(form_defaults) | set(global_defaults)

        for field in form.get("fields", []):
            missing = [
                required_key
                for required_key in ("section", "key", "label", "input_type", "default_layer")
                if not field.get(required_key)
            ]
            if missing:
                errors.append(f"{form_id}: field missing {', '.join(missing)}")

            if field.get("default_layer") == "No Default":
                key = field.get("key")
                if key in form_defaults and str(form_defaults.get(key, "")).strip():
                    errors.append(f"{form_id}: No Default field has form default: {key}")
                if key in global_defaults and str(global_defaults.get(key, "")).strip():
                    errors.append(f"{form_id}: No Default field has global default: {key}")

        template = form.get("narrative_template") or form.get("template", "")
        for placeholder in PLACEHOLDER_PATTERN.findall(template):
            key = placeholder.strip()
            if key not in available_keys:
                errors.append(f"{form_id}: narrative placeholder has no field/default: {key}")

    return errors
