from __future__ import annotations

import base64
import re

from ..config import mcp_config

_BASE64_RE = re.compile(r"^[A-Za-z0-9+/]*={0,2}$")
_BASE64URL_RE = re.compile(r"^[A-Za-z0-9_-]*={0,2}$")
_OVERHEAD_RATIO = 4 / 3


def validate_and_decode_base64(raw: str) -> tuple[bool, bytes | None, str]:
    """
    Validate and decode base64 input.
    Returns (ok, decoded_bytes, error_message).
    """
    if not raw:
        return False, None, "Content must be a non-empty base64 string."

    stripped = re.sub(r"[\r\n\s]", "", raw)

    estimated_bytes = int(len(stripped) / _OVERHEAD_RATIO) + 1
    if estimated_bytes > mcp_config.max_file_size_bytes:
        limit_mb = mcp_config.max_file_size_bytes / (1024 * 1024)
        est_kb = round(estimated_bytes / 1024)
        return False, None, f"File exceeds {limit_mb:.0f} MB limit (estimated {est_kb} KB)."

    if not _BASE64_RE.match(stripped) and not _BASE64URL_RE.match(stripped):
        return False, None, "Content is not valid base64."

    try:
        decoded = base64.b64decode(stripped, validate=True)
    except Exception:
        try:
            safe = stripped.replace("-", "+").replace("_", "/")
            pad = 4 - len(safe) % 4
            if pad != 4:
                safe += "=" * pad
            decoded = base64.b64decode(safe, validate=True)
        except Exception:
            return False, None, "Failed to decode base64 content."

    if len(decoded) == 0:
        return False, None, "File cannot be empty."

    if len(decoded) > mcp_config.max_file_size_bytes:
        limit_mb = mcp_config.max_file_size_bytes / (1024 * 1024)
        size_kb = round(len(decoded) / 1024)
        return False, None, f"File exceeds {limit_mb:.0f} MB limit ({size_kb} KB)."

    return True, decoded, ""
