"""
Activation Functions — comprehensive topic content with interactive graphs.
"""

import json
import numpy as np


def _all_activations():
    """Plot all major activation functions."""
    x = np.linspace(-5, 5, 300)
    sigmoid = 1 / (1 + np.exp(-x))
    tanh = np.tanh(x)
    relu = np.maximum(0, x)
    leaky = np.where(x > 0, x, 0.01 * x)
    elu = np.where(x > 0, x, 1.0 * (np.exp(x) - 1))
    swish = x * sigmoid

    data = [
        {"x": x.tolist(), "y": relu.tolist(), "mode": "lines", "type": "scatter", "name": "ReLU",
         "line": {"color": "#6C63FF", "width": 3}},
        {"x": x.tolist(), "y": sigmoid.tolist(), "mode": "lines", "type": "scatter", "name": "Sigmoid",
         "line": {"color": "#FF6584", "width": 2.5}},
        {"x": x.tolist(), "y": tanh.tolist(), "mode": "lines", "type": "scatter", "name": "Tanh",
         "line": {"color": "#34d399", "width": 2.5}},
        {"x": x.tolist(), "y": leaky.tolist(), "mode": "lines", "type": "scatter", "name": "Leaky ReLU",
         "line": {"color": "#fbbf24", "width": 2.5}},
        {"x": x.tolist(), "y": swish.tolist(), "mode": "lines", "type": "scatter", "name": "Swish (SiLU)",
         "line": {"color": "#a78bfa", "width": 2.5}},
    ]
    layout = {
        "template": "plotly_dark", "paper_bgcolor": "rgba(0,0,0,0)", "plot_bgcolor": "rgba(0,0,0,0)",
        "title": {"text": "Common Activation Functions", "font": {"size": 18}},
        "xaxis": {"title": "Input (z)", "gridcolor": "rgba(255,255,255,0.08)", "zeroline": True, "zerolinecolor": "rgba(255,255,255,0.2)"},
        "yaxis": {"title": "Output f(z)", "gridcolor": "rgba(255,255,255,0.08)", "range": [-2, 5], "zeroline": True, "zerolinecolor": "rgba(255,255,255,0.2)"},
        "margin": {"l": 60, "r": 30, "t": 50, "b": 50},
    }
    return json.dumps({"data": data, "layout": layout})


def _derivatives():
    """Plot derivatives of activation functions."""
    x = np.linspace(-5, 5, 300)
    sigmoid = 1 / (1 + np.exp(-x))
    d_sigmoid = sigmoid * (1 - sigmoid)
    d_tanh = 1 - np.tanh(x) ** 2
    d_relu = (x > 0).astype(float)

    data = [
        {"x": x.tolist(), "y": d_relu.tolist(), "mode": "lines", "type": "scatter", "name": "ReLU derivative",
         "line": {"color": "#6C63FF", "width": 3}},
        {"x": x.tolist(), "y": d_sigmoid.tolist(), "mode": "lines", "type": "scatter", "name": "Sigmoid derivative",
         "line": {"color": "#FF6584", "width": 2.5}},
        {"x": x.tolist(), "y": d_tanh.tolist(), "mode": "lines", "type": "scatter", "name": "Tanh derivative",
         "line": {"color": "#34d399", "width": 2.5}},
    ]
    layout = {
        "template": "plotly_dark", "paper_bgcolor": "rgba(0,0,0,0)", "plot_bgcolor": "rgba(0,0,0,0)",
        "title": {"text": "Activation Derivatives (Gradient Flow)", "font": {"size": 18}},
        "xaxis": {"title": "Input (z)", "gridcolor": "rgba(255,255,255,0.08)"},
        "yaxis": {"title": "Derivative f'(z)", "gridcolor": "rgba(255,255,255,0.08)", "range": [-0.1, 1.2]},
        "annotations": [{"x": 0, "y": 0.25, "text": "Sigmoid max gradient = 0.25<br>→ vanishing gradients!", "showarrow": True,
                         "arrowhead": 2, "font": {"size": 11, "color": "#FF6584"}, "ax": 80, "ay": -40}],
        "margin": {"l": 60, "r": 30, "t": 50, "b": 50},
    }
    return json.dumps({"data": data, "layout": layout})


def get_content() -> dict:
    return {
        "title": "Activation Functions",
        "icon": "⚡",
        "subtitle": "Non-linearities that give neural networks their power",
        "sections": [
            {"id": "introduction", "heading": "Why Activation Functions?", "type": "text",
             "content": ("Without activation functions, a neural network is just a <strong>linear transformation</strong> — "
                         "no matter how many layers, it can only model linear relationships.\n\n"
                         "Activation functions introduce <strong>non-linearity</strong>, enabling networks to learn complex "
                         "patterns like curves, edges, and abstract features.")},
            {"id": "comparison", "heading": "Common Activation Functions", "type": "graph",
             "description": "ReLU is the default for hidden layers. Sigmoid squashes to [0,1] (used in output for binary classification). Tanh squashes to [-1,1]. Swish is a smooth alternative to ReLU.",
             "graph_json": _all_activations()},
            {"id": "math", "heading": "The Mathematics", "type": "math",
             "content": [
                 {"label": "ReLU", "formula": "f(z) = \\max(0, z)",
                  "explanation": "Simple and effective. Zero for negative, identity for positive. Derivative = 1 or 0."},
                 {"label": "Sigmoid", "formula": "\\sigma(z) = \\frac{1}{1 + e^{-z}}",
                  "explanation": "Outputs in [0,1]. Used in output layer for binary classification. Max gradient = 0.25 → vanishing gradients."},
                 {"label": "Tanh", "formula": "\\tanh(z) = \\frac{e^z - e^{-z}}{e^z + e^{-z}}",
                  "explanation": "Outputs in [-1,1]. Zero-centered (better than sigmoid for hidden layers). Still saturates."},
                 {"label": "Leaky ReLU", "formula": "f(z) = \\begin{cases} z & z > 0 \\\\ \\alpha z & z \\leq 0 \\end{cases}",
                  "explanation": "Small slope (α=0.01) for negative inputs prevents 'dying ReLU' problem where neurons permanently output zero."},
                 {"label": "Swish (SiLU)", "formula": "f(z) = z \\cdot \\sigma(z)",
                  "explanation": "Smooth, non-monotonic. Consistently outperforms ReLU in deep networks. Used in EfficientNet and modern architectures."},
             ]},
            {"id": "derivatives", "heading": "Gradient Flow", "type": "graph",
             "description": "The derivative matters for backpropagation. Sigmoid's max gradient is only 0.25 — multiplied across layers, gradients vanish. ReLU's derivative is 1 (perfect gradient flow for positive inputs).",
             "graph_json": _derivatives()},
            {"id": "guide", "heading": "When to Use What", "type": "list",
             "entries": [
                 {"title": "Hidden Layers → ReLU", "detail": "Default choice. Fast, simple, good gradient flow. Use Leaky ReLU if dying neurons are an issue."},
                 {"title": "Binary Output → Sigmoid", "detail": "Squashes output to [0,1] for binary classification probability."},
                 {"title": "Multi-class Output → Softmax", "detail": "Produces probability distribution over K classes. All outputs sum to 1."},
                 {"title": "RNN Hidden → Tanh", "detail": "Zero-centered output helps with vanishing gradients in recurrent networks."},
                 {"title": "Modern Deep Nets → Swish/GELU", "detail": "Swish (SiLU) and GELU are now standard in transformers and modern architectures. Smoother gradients."},
             ]},
        ],
    }
