"""Activation page rendering + license gate inline-renderer.

Two public callables:

- :func:`render_activation_form` — the activation page body. Used by
  ``pages/_Activate.py`` for the explicit nav entry and by
  :func:`require_license_or_render_activation` for the gate-injected
  inline form.

- :func:`require_license_or_render_activation` — call after
  ``hide_streamlit_chrome`` from every page that needs a valid
  license. When the license is missing, expired, or invalid it
  renders the activation form in place of the page body and calls
  ``st.stop()`` so the rest of the page doesn't execute.

- :func:`render_license_status_sidebar` — small chrome widget the
  sidebar uses to show "Core · 327 days left" or "🛑 Expired".

The component is kept dependency-free of the page modules so any
page can import these helpers without circular imports through
``components.__init__``.
"""

from __future__ import annotations

from typing import Optional

import streamlit as st

from src.i18n import t as _t
from src.license import (
    ExpiredLicenseError,
    InvalidLicenseError,
    LicenseError,
    NotActivatedError,
    get_manager,
)


# ---------------------------------------------------------------------------
# Sidebar status widget
# ---------------------------------------------------------------------------

def render_license_status_sidebar() -> None:
    """Render the per-page sidebar license badge.

    Cheap to call — the manager caches the parsed license, so multiple
    pages mounting the same chrome don't pay multiple disk reads.
    """
    state = get_manager().current_state()
    target = st.sidebar
    if not state.activated:
        target.caption(f"🔒 {_t('license.status_not_activated')}")
        return
    if state.error_kind == "invalid":
        target.caption(f"⚠️ {_t('license.status_invalid')}")
        return
    if not state.valid:
        # Activated but expired.
        target.caption(f"🛑 {_t('license.status_expired')}")
        return

    tier_label = _t(f"license.tier_{state.tier}") or state.tier.title()
    if state.tier == "trial":
        label = _t("license.status_trial", days=state.days_remaining)
    else:
        label = _t(
            "license.status_active",
            tier=tier_label,
            days=state.days_remaining,
        )
    target.caption(label)
    if 0 < state.days_remaining <= 30:
        target.warning(
            _t("license.renewal_warning_30", days=state.days_remaining)
        )


# ---------------------------------------------------------------------------
# Activation page body
# ---------------------------------------------------------------------------

def render_activation_form(*, key_prefix: str = "act") -> None:
    """Render the full activation page body.

    *key_prefix* is appended to every Streamlit widget key so the
    form can be embedded inline by ``require_license_or_render_activation``
    without colliding with an instance that's mounted by the
    explicit ``_Activate.py`` page.
    """
    st.title(_t("activation.title"))
    st.caption(_t("activation.intro"))

    mgr = get_manager()
    state = mgr.current_state()

    # Surface the current state explicitly so a user with an expired /
    # invalid license sees what's wrong before they paste anything.
    if state.activated and state.error_kind == "expired":
        st.warning(
            _t("license.renewal_warning_expired", date=state.expires_at[:10])
        )
    elif state.activated and state.error_kind == "invalid":
        st.error(f"⚠️ {state.error_message}")

    st.divider()

    with st.form(key=f"{key_prefix}_form"):
        name = st.text_input(
            _t("activation.name_label"),
            value=state.name,
            help=_t("activation.name_help"),
            key=f"{key_prefix}_name",
        )
        email = st.text_input(
            _t("activation.email_label"),
            value=state.email,
            help=_t("activation.email_help"),
            key=f"{key_prefix}_email",
        )
        blob = st.text_area(
            _t("activation.blob_label"),
            help=_t("activation.blob_help"),
            key=f"{key_prefix}_blob",
            height=120,
        )

        is_renewal = state.activated
        label = (
            _t("activation.renew_button") if is_renewal
            else _t("activation.activate_button")
        )
        submit = st.form_submit_button(label, type="primary")

    # Process the submission.
    if submit:
        if not blob.strip():
            st.error(_t("activation.errors_heading") + ": license blob is empty.")
            return
        try:
            if is_renewal:
                lic = mgr.renew(blob)
                st.success(_t("activation.renewed", expires=lic.expires_at[:10]))
            else:
                lic = mgr.activate_from_blob(blob, name=name, email=email)
                st.success(_t(
                    "activation.success",
                    name=lic.name, expires=lic.expires_at[:10],
                ))
            # Force a clean re-render so the gate sees the new state.
            st.rerun()
        except LicenseError as e:
            st.error(f"{_t('activation.errors_heading')}: {e}")

    # Deactivate (only useful when already activated).
    if state.activated:
        st.divider()
        with st.expander(_t("activation.deactivate_button")):
            st.caption(_t("activation.deactivate_help"))
            if st.button(
                _t("activation.deactivate_button"),
                key=f"{key_prefix}_deactivate",
                type="secondary",
            ):
                mgr.deactivate()
                st.rerun()


# ---------------------------------------------------------------------------
# Gate
# ---------------------------------------------------------------------------

def require_license_or_render_activation(*, feature: Optional[str] = None) -> None:
    """Page-level guard. Call after ``hide_streamlit_chrome``.

    If a valid license exists (and *feature*, when supplied, is
    unlocked), this is a no-op. Otherwise it renders the activation
    form in place of the page body and calls ``st.stop()``.

    Tool pages that need per-tool gating call
    :func:`require_feature_or_render_upgrade` *after* this — that
    keeps the global gate (activate / renew flow) separate from the
    per-tier feature gate (upgrade flow).
    """
    mgr = get_manager()
    if mgr.dev_mode:
        return
    if mgr.is_valid():
        return

    # Otherwise: render the activation form inline and stop the page.
    render_activation_form(key_prefix="gate")
    st.stop()


def require_feature_or_render_upgrade(feature: str) -> None:
    """Per-tool feature gate. Renders an upgrade prompt + stops the
    page when the active license's tier doesn't unlock *feature*.

    Call from tool pages after ``hide_streamlit_chrome``. The page
    body should be wrapped after this call so the upgrade prompt
    cleanly replaces the body when the user's tier is too low.

    Distinguished from :func:`require_license_or_render_activation`
    by what it offers the user: that one drops them into the
    activation form (paste a paid blob to activate at all); this one
    surfaces an upgrade prompt with a button to the Activate page
    (paste a higher-tier blob to upgrade).
    """
    from src.license import UnsupportedFeatureError

    mgr = get_manager()
    if mgr.dev_mode:
        return
    try:
        mgr.require_feature(feature)
        return
    except UnsupportedFeatureError:
        pass  # render the upgrade prompt below
    except LicenseError as e:
        # Not-activated / expired / invalid — fall through to the
        # global gate (which would already have run; this is belt
        # and braces for callers that bypass it).
        st.error(f"⚠️ {e}")
        st.stop()

    state = mgr.current_state()
    tier_label = _t(f"license.tier_{state.tier}") or state.tier.title()
    feature_names = ", ".join(
        _t(f"tools.{f}.name") if f.startswith("0") and "_" in f else f
        for f in state.features
    )
    st.warning(_t("license.feature_locked_title", tier=tier_label))
    st.caption(_t("license.feature_locked_body", features=feature_names))
    if st.button(_t("license.upgrade_link"), key="upgrade_to_activate"):
        st.switch_page("pages/_Activate.py")
    st.stop()
