"""Shared validation helpers for dashboard handlers."""
import json
import re
from http.server import BaseHTTPRequestHandler

_SLUG_RE = re.compile(r'^[a-z0-9][a-z0-9\-_]{1,38}[a-z0-9]$')


def validate_slug(slug: str) -> str | None:
    """Returns error message or None if valid."""
    if not slug:
        return "slug required"
    if not _SLUG_RE.match(slug):
        return "slug must be 3-40 chars, lowercase alphanumeric + hyphens/underscores"
    return None


def validate_description(desc: str) -> str | None:
    """Returns error message or None if valid. Min 10 chars, max 500."""
    if not desc or len(desc.strip()) < 10:
        return "description must be at least 10 characters"
    if len(desc) > 500:
        return "description must be at most 500 characters"
    return None


def parse_json_body(handler: BaseHTTPRequestHandler) -> dict | None:
    """Parse JSON body from request. Returns None on failure (sends 400)."""
    try:
        length = int(handler.headers.get('Content-Length', '0') or '0')
    except (TypeError, ValueError):
        length = 0

    def _send_error(msg: str) -> None:
        sender = getattr(handler, 'send_json', None)
        if callable(sender):
            sender({'error': msg}, 400)
            return
        body = json.dumps({'error': msg}).encode()
        handler.send_response(400)
        handler.send_header('Content-Type', 'application/json')
        handler.send_header('Content-Length', str(len(body)))
        handler.end_headers()
        handler.wfile.write(body)

    if length <= 0:
        _send_error('empty body')
        return None
    try:
        raw = handler.rfile.read(length)
        return json.loads(raw.decode('utf-8'))
    except (ValueError, json.JSONDecodeError, UnicodeDecodeError):
        _send_error('invalid JSON body')
        return None
