from __future__ import annotations

import json
from typing import Any, Optional
from django import forms
from django.utils.safestring import mark_safe, SafeString
from .conf import get_setting


class RichTextWidget(forms.Textarea):
    """
    Textarea replacement that mounts the 101editor React app.
    The editor syncs HTML back to the hidden textarea on every change so
    standard Django form submission and validation work unchanged.
    """

    def __init__(
        self,
        attrs: Optional[dict[str, Any]] = None,
        toolbar: Optional[str] = None,
    ) -> None:
        super().__init__(attrs)
        self._toolbar: str = toolbar or get_setting("toolbar")

    class Media:
        css: dict[str, tuple[str, ...]] = {"all": ("editor101/editor.css",)}
        js: tuple[str, ...] = ("editor101/editor.bundle.js",)

    def build_attrs(
        self,
        base_attrs: dict[str, Any],
        extra_attrs: Optional[dict[str, Any]] = None,
    ) -> dict[str, Any]:
        attrs = super().build_attrs(base_attrs, extra_attrs)
        attrs["class"] = (attrs.get("class", "") + " editor101-textarea").strip()
        attrs["style"] = "display:none;"
        return attrs

    def render(
        self,
        name: str,
        value: Any,
        attrs: Optional[dict[str, Any]] = None,
        renderer: Any = None,
    ) -> SafeString:
        textarea_html: str = super().render(name, value, attrs, renderer)
        config: str = json.dumps(
            {
                "toolbar": self._toolbar,
                "uploadUrl": "/editor101/upload/",
                "csrfCookieName": "csrftoken",
                "language": get_setting("language"),
            }
        )
        mount_div = (
            f'<div class="editor101-mount" data-config=\'{config}\'></div>'
        )
        return mark_safe(textarea_html + mount_div)
