"""Five aura motifs (A-D), drawn around a centre on any canvas.

s is the scale: 1.0 matches the first-screen version (first ring 110 px, step 50).
"""
import math

LINE = "#84adff"
LB = "#5aa7ff"


def circles(cx, cy, s):
    return "".join(
        f'<circle cx="{cx}" cy="{cy}" r="{(110 + 50 * i) * s:.1f}" fill="none" stroke="{LINE}" stroke-opacity=".16"/>'
        for i in range(7))


def hexes(cx, cy, s):
    out = []
    for i in range(7):
        r = (115 + 50 * i) * s
        pts = " ".join(f"{cx + r * math.cos(math.radians(a)):.1f},{cy + r * math.sin(math.radians(a)):.1f}"
                       for a in range(-90, 270, 60))
        op = max(0.20 - 0.03 * i, 0.04)
        out.append(f'<polygon points="{pts}" fill="none" stroke="{LINE}" stroke-opacity="{op:.2f}" stroke-linejoin="round"/>')
    return "".join(out)


def hexes_round(cx, cy, s, k=0.14):
    """Same rings as hexes, corners rounded with radius k * circumradius."""
    out = []
    for i in range(7):
        r = (115 + 50 * i) * s
        c = k * r
        t = c / math.sqrt(3)  # tangent distance from a 120-degree corner
        v = [(cx + r * math.cos(math.radians(a)), cy + r * math.sin(math.radians(a))) for a in range(-90, 270, 60)]
        d = ""
        for j in range(6):
            (x0, y0), (x1, y1), (x2, y2) = v[j - 1], v[j], v[(j + 1) % 6]
            ux, uy = (x0 - x1) / r, (y0 - y1) / r
            wx, wy = (x2 - x1) / r, (y2 - y1) / r
            a = (x1 + ux * t, y1 + uy * t)
            b = (x1 + wx * t, y1 + wy * t)
            d += f'{"M" if j == 0 else "L"}{a[0]:.1f},{a[1]:.1f} A{c:.1f},{c:.1f} 0 0 1 {b[0]:.1f},{b[1]:.1f} '
        op = max(0.20 - 0.03 * i, 0.04)
        out.append(f'<path d="{d}Z" fill="none" stroke="{LINE}" stroke-opacity="{op:.2f}"/>')
    return "".join(out)


def arrows(cx, cy, s):
    out = []
    for i, op in enumerate([0.35, 0.22, 0.14, 0.08, 0.05]):
        r = (130 + 60 * i) * s
        arm, depth = (5.6 + 1.2 * i) * s, (7 + 1.5 * i) * s
        for a in range(-90, 270, 60):
            t = math.radians(a)
            tx, ty = cx + r * math.cos(t), cy + r * math.sin(t)
            bx, by = cx + (r - depth) * math.cos(t), cy + (r - depth) * math.sin(t)
            px, py = -math.sin(t) * arm, math.cos(t) * arm
            out.append(f'<path d="M{bx + px:.1f},{by + py:.1f} L{tx:.1f},{ty:.1f} L{bx - px:.1f},{by - py:.1f}" fill="none" '
                       f'stroke="{LB}" stroke-opacity="{op}" stroke-width="{3 * max(s, .6):.1f}" stroke-linecap="round" stroke-linejoin="round"/>')
    return "".join(out)


def iso(cx, cy, s, w, h, uid):
    step = 26 * s
    span = int(max(w, h) * 2 / step) + 2
    lines = []
    for k in range(-span, span + 1):
        x = cx + k * step
        lines.append(f'<line x1="{x:.1f}" y1="-10" x2="{x:.1f}" y2="{h + 10}"/>')
        for sl in (math.tan(math.radians(30)), -math.tan(math.radians(30))):
            # lines through (cx, cy + k * step / cos30) with slope sl
            b = cy + k * step / math.cos(math.radians(30))
            x1, x2 = -10, w + 10
            lines.append(f'<line x1="{x1}" y1="{b + sl * (x1 - cx):.1f}" x2="{x2}" y2="{b + sl * (x2 - cx):.1f}"/>')
    return (f'<defs><radialGradient id="fd{uid}" cx="{cx}" cy="{cy}" r="{300 * s:.0f}" gradientUnits="userSpaceOnUse">'
            f'<stop offset="0" stop-color="#fff"/><stop offset="1" stop-color="#fff" stop-opacity="0"/></radialGradient>'
            f'<mask id="mk{uid}"><rect width="{w}" height="{h}" fill="url(#fd{uid})"/></mask></defs>'
            f'<g mask="url(#mk{uid})" stroke="{LINE}" stroke-opacity=".12">{"".join(lines)}</g>')


def orbits(cx, cy, s, labels):
    """labels: list of (text, ring 0-1, angle deg, side 'r'|'l')."""
    rings = [150 * s, 225 * s, 300 * s, 375 * s]
    out = [f'<circle cx="{cx}" cy="{cy}" r="{r:.1f}" fill="none" stroke="{LINE}" stroke-opacity="{op}"/>'
           for r, op in zip(rings, [0.24, 0.15, 0.09, 0.05])]
    fs = 12 * max(s, .8)
    for text, ring, ang, side in labels:
        r = rings[ring]
        x, y = cx + r * math.cos(math.radians(ang)), cy + r * math.sin(math.radians(ang))
        tw = len(text) * fs * 0.56 + fs * 1.6
        th = fs * 2
        gx = x + fs * 0.7 if side == "r" else x - fs * 0.7 - tw
        out.append(f'<circle cx="{x:.1f}" cy="{y:.1f}" r="{3 * max(s, .8):.1f}" fill="{LB}"/>'
                   f'<g transform="translate({gx:.1f},{y - th / 2:.1f})"><rect width="{tw:.1f}" height="{th:.1f}" rx="{th / 2:.1f}" '
                   f'fill="#13284f" stroke="#2b4680"/><text x="{tw / 2:.1f}" y="{th / 2 + fs * .36:.1f}" text-anchor="middle" '
                   f'font-family="Inter" font-size="{fs:.1f}" font-weight="500" fill="#dbe4f5">{text}</text></g>')
    return "".join(out)


def svg(kind, w, h, cx, cy, s, uid, labels=()):
    body = {"circles": lambda: circles(cx, cy, s), "hex": lambda: hexes(cx, cy, s), "hexr": lambda: hexes_round(cx, cy, s),
            "arrows": lambda: arrows(cx, cy, s), "iso": lambda: iso(cx, cy, s, w, h, uid),
            "orbit": lambda: orbits(cx, cy, s, labels)}[kind]()
    return f'<svg class="bg" viewBox="0 0 {w} {h}" width="{w}" height="{h}">{body}</svg>'
