#!/usr/bin/env python3
"""Genera mockups SVG de los sistemas para el portafolio."""
import os

W, H = 1600, 1000
BG = "#070b14"
PANEL = "#0e1220"
PANEL2 = "#121828"
BORDER = "#1e2536"
INK = "#e8ecf5"
MUTED = "#8891a7"
ACC = "#6ee7ff"
ACC2 = "#a78bfa"
ACC3 = "#34d399"
WARN = "#fbbf24"

OUT = os.path.join(os.path.dirname(__file__), "..", "src", "assets", "images")


def esc(s):
    return (s.replace("&", "&amp;").replace("<", "&lt;").replace(">", "&gt;"))


def rect(x, y, w, h, fill, r=0, stroke=None, sw=1, op=1):
    s = f'<rect x="{x}" y="{y}" width="{w}" height="{h}" rx="{r}" fill="{fill}"'
    if op != 1:
        s += f' fill-opacity="{op}"'
    if stroke:
        s += f' stroke="{stroke}" stroke-width="{sw}"'
    return s + "/>"


def text(x, y, s, size=15, fill=INK, weight=400, anchor="start", mono=False, op=1):
    fam = "'JetBrains Mono',monospace" if mono else "'Inter','Segoe UI',sans-serif"
    return (f'<text x="{x}" y="{y}" font-family="{fam}" font-size="{size}" '
            f'fill="{fill}" fill-opacity="{op}" font-weight="{weight}" '
            f'text-anchor="{anchor}">{esc(s)}</text>')


def bar(x, y, w, h=8, fill=MUTED, op=0.35, r=4):
    return rect(x, y, w, h, fill, r=r, op=op)


def circle(cx, cy, r, fill, op=1, stroke=None, sw=1):
    s = f'<circle cx="{cx}" cy="{cy}" r="{r}" fill="{fill}" fill-opacity="{op}"'
    if stroke:
        s += f' stroke="{stroke}" stroke-width="{sw}"'
    return s + "/>"


def header(defs_id, url, dot_accent=ACC):
    """Chrome de navegador."""
    o = [rect(0, 0, W, H, BG, r=0)]
    o.append(rect(0, 0, W, 56, "#0b101c"))
    o.append(f'<line x1="0" y1="56" x2="{W}" y2="56" stroke="{BORDER}" stroke-width="1.5"/>')
    for i, c in enumerate(["#ff5f57", "#febc2e", "#28c840"]):
        o.append(circle(38 + i * 26, 28, 7, c, op=0.85))
    o.append(rect(150, 15, 520, 26, PANEL2, r=13, stroke=BORDER))
    o.append(circle(170, 28, 5, dot_accent, op=0.9))
    o.append(text(186, 33, url, size=13, fill=MUTED, mono=True))
    return o


def sidebar(title, items, active, accent=ACC, x=0, y=56, w=230):
    o = [rect(x, y, w, H - y, "#0a0e18")]
    o.append(f'<line x1="{x+w}" y1="{y}" x2="{x+w}" y2="{H}" stroke="{BORDER}" stroke-width="1.5"/>')
    o.append(rect(x + 24, y + 26, 34, 34, accent, r=10, op=0.16))
    o.append(text(x + 41, y + 49, title[0], size=18, fill=accent, weight=700, anchor="middle"))
    o.append(text(x + 68, y + 49, title, size=17, weight=600))
    cy = y + 96
    for i, it in enumerate(items):
        if it is None:
            cy += 14
            continue
        if i == active:
            o.append(rect(x + 16, cy, w - 32, 40, accent, r=10, op=0.14))
            o.append(rect(x + 16, cy, 3, 40, accent, r=2))
        o.append(rect(x + 34, cy + 14, 12, 12, accent if i == active else MUTED, r=3,
                      op=1 if i == active else 0.5))
        o.append(text(x + 58, cy + 26, it, size=14,
                      fill=INK if i == active else MUTED,
                      weight=600 if i == active else 400))
        cy += 46
    return o


def topbar(title, subtitle, accent=ACC, x=230):
    o = [rect(x, 56, W - x, 78, "#0b101c")]
    o.append(f'<line x1="{x}" y1="134" x2="{W}" y2="134" stroke="{BORDER}" stroke-width="1.5"/>')
    o.append(text(x + 32, 90, title, size=20, weight=600))
    o.append(text(x + 32, 113, subtitle, size=13, fill=MUTED))
    o.append(rect(W - 260, 78, 150, 34, PANEL2, r=17, stroke=BORDER))
    o.append(circle(W - 243, 95, 6, MUTED, op=0.5))
    o.append(bar(W - 228, 91, 90, 8, MUTED, 0.3))
    o.append(circle(W - 76, 95, 20, accent, op=0.18))
    o.append(text(W - 76, 101, "AC", size=13, fill=accent, weight=700, anchor="middle"))
    return o


def card(x, y, w, h, r=16):
    return rect(x, y, w, h, PANEL, r=r, stroke=BORDER, sw=1.5)


def stat(x, y, w, label, value, accent):
    o = [card(x, y, w, 96)]
    o.append(text(x + 20, y + 34, label, size=12, fill=MUTED, mono=True))
    o.append(text(x + 20, y + 70, value, size=26, fill=accent, weight=700))
    return o


def wrap(body):
    return ('<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 %d %d" '
            'width="%d" height="%d" role="img">\n%s\n</svg>\n'
            % (W, H, W, H, "\n".join(body)))


# ---------------------------------------------------------------- AlPunto
def alpunto():
    o = header("ap", "alpunto.alfredochm.com/pos")
    o += sidebar("AlPunto", ["Punto de venta", "Inventario", "Clientes", "Depósitos SIGES",
                             "Cierre de caja", "Reportes", "Configuración"], 0, ACC)
    o += topbar("Punto de venta", "Turno abierto · Caja 01 · Cajero", ACC)

    # Buscador + productos
    x0, y0 = 262, 160
    o.append(card(x0, y0, 640, 62))
    o.append(circle(x0 + 30, y0 + 31, 8, MUTED, op=0.6))
    o.append(text(x0 + 52, y0 + 37, "Buscar producto por nombre o código…", size=14, fill=MUTED))
    o.append(rect(x0 + 500, y0 + 14, 122, 34, ACC, r=17, op=0.16))
    o.append(text(x0 + 561, y0 + 36, "F2 Buscar", size=12, fill=ACC, weight=600,
                  anchor="middle", mono=True))

    # Tabla carrito
    ty = y0 + 82
    o.append(card(x0, ty, 640, 480))
    cols = [("Producto", 24), ("Cant.", 330), ("P. Unit.", 430), ("Total", 550)]
    for c, cx in cols:
        o.append(text(x0 + cx, ty + 34, c, size=12, fill=MUTED, mono=True))
    o.append(f'<line x1="{x0+16}" y1="{ty+50}" x2="{x0+624}" y2="{ty+50}" stroke="{BORDER}"/>')
    rows = [("Arroz Costeño 5 kg", "2", "24.90", "49.80"),
            ("Aceite Primor 1 L", "3", "11.50", "34.50"),
            ("Leche Gloria 400 g", "6", "4.20", "25.20"),
            ("Azúcar rubia 1 kg", "4", "4.80", "19.20"),
            ("Fideos Don Vittorio", "5", "3.60", "18.00"),
            ("Atún Florida 170 g", "8", "5.90", "47.20"),
            ("Detergente Bolívar", "2", "18.40", "36.80")]
    ry = ty + 82
    for i, (n, q, p, t) in enumerate(rows):
        if i % 2 == 0:
            o.append(rect(x0 + 16, ry - 22, 608, 44, "#ffffff", r=8, op=0.02))
        o.append(circle(x0 + 34, ry - 5, 11, ACC, op=0.14))
        o.append(text(x0 + 56, ry, n, size=13.5))
        o.append(text(x0 + 340, ry, q, size=13.5, fill=MUTED))
        o.append(text(x0 + 440, ry, p, size=13.5, fill=MUTED))
        o.append(text(x0 + 560, ry, t, size=13.5, weight=600))
        ry += 52

    # Panel derecho: totales
    px = 940
    o.append(card(px, y0, 398, 316))
    o.append(text(px + 24, y0 + 38, "COMPROBANTE", size=12, fill=MUTED, mono=True))
    o.append(rect(px + 240, y0 + 20, 134, 30, ACC2, r=15, op=0.16))
    o.append(text(px + 307, y0 + 40, "Boleta B001", size=12, fill=ACC2, weight=600,
                  anchor="middle", mono=True))
    o.append(text(px + 24, y0 + 86, "Cliente", size=13, fill=MUTED))
    o.append(text(px + 374, y0 + 86, "Bodega Sarita SAC", size=13, anchor="end"))
    o.append(text(px + 24, y0 + 118, "RUC", size=13, fill=MUTED))
    o.append(text(px + 374, y0 + 118, "20512345678", size=13, anchor="end", mono=True))
    o.append(f'<line x1="{px+24}" y1="{y0+142}" x2="{px+374}" y2="{y0+142}" stroke="{BORDER}"/>')
    o.append(text(px + 24, y0 + 176, "Subtotal", size=13, fill=MUTED))
    o.append(text(px + 374, y0 + 176, "S/ 195.52", size=13, anchor="end"))
    o.append(text(px + 24, y0 + 208, "IGV (18%)", size=13, fill=MUTED))
    o.append(text(px + 374, y0 + 208, "S/ 35.18", size=13, anchor="end"))
    o.append(rect(px + 16, y0 + 230, 366, 68, ACC, r=12, op=0.12))
    o.append(text(px + 36, y0 + 272, "TOTAL", size=14, fill=ACC, weight=700, mono=True))
    o.append(text(px + 362, y0 + 274, "S/ 230.70", size=28, fill=ACC, weight=700, anchor="end"))

    # Botones
    by = y0 + 336
    o.append(rect(px, by, 190, 54, ACC, r=14))
    o.append(text(px + 95, by + 34, "Cobrar (F9)", size=15, fill="#05070d", weight=700,
                  anchor="middle"))
    o.append(rect(px + 208, by, 190, 54, PANEL, r=14, stroke=BORDER, sw=1.5))
    o.append(text(px + 303, by + 34, "Cancelar", size=15, fill=MUTED, weight=600, anchor="middle"))

    # Cierre de caja
    cy = by + 76
    o.append(card(px, cy, 398, 186))
    o.append(text(px + 24, cy + 36, "Cierre de caja — Turno actual", size=14, weight=600))
    o.append(text(px + 24, cy + 74, "Ventas del turno", size=13, fill=MUTED))
    o.append(text(px + 374, cy + 74, "S/ 4,182.60", size=13, anchor="end", fill=ACC3))
    o.append(text(px + 24, cy + 106, "Comprobantes emitidos", size=13, fill=MUTED))
    o.append(text(px + 374, cy + 106, "68", size=13, anchor="end"))
    o.append(rect(px + 24, cy + 128, 160, 36, ACC3, r=10, op=0.16))
    o.append(text(px + 104, cy + 152, "Cierre X", size=13, fill=ACC3, weight=600, anchor="middle"))
    o.append(rect(px + 200, cy + 128, 174, 36, ACC2, r=10, op=0.16))
    o.append(text(px + 287, cy + 152, "Cierre Z", size=13, fill=ACC2, weight=600, anchor="middle"))
    return wrap(o)


# ------------------------------------------------------------ Aula Virtual
def evalpinguino():
    o = header("ev", "examen2026.alfredochm.com/docente")
    o += sidebar("Aula Virtual", ["Panel", "Exámenes", "Cursos", "Estudiantes",
                                  "Notas", "Resultados", "Asistencia QR"], 1, ACC2)
    o += topbar("Exámenes", "Docente · Periodo 2026-I", ACC2)

    x0, y0 = 262, 158
    gap = 20
    sw = (W - x0 - 32 - gap * 3) / 4
    for i, (lb, val, col) in enumerate([("EXÁMENES ACTIVOS", "12", ACC2),
                                        ("ESTUDIANTES", "148", ACC),
                                        ("RINDIENDO AHORA", "23", ACC3),
                                        ("PROMEDIO GENERAL", "15.4", WARN)]):
        o += stat(x0 + i * (sw + gap), y0, sw, lb, val, col)

    # Examen en curso
    ey = y0 + 118
    o.append(card(x0, ey, 700, 424))
    o.append(text(x0 + 24, ey + 40, "Examen en curso", size=17, weight=600))
    o.append(rect(x0 + 560, ey + 20, 116, 30, ACC3, r=15, op=0.16))
    o.append(circle(x0 + 582, ey + 35, 5, ACC3))
    o.append(text(x0 + 626, ey + 40, "EN VIVO", size=12, fill=ACC3, weight=700,
                  anchor="middle", mono=True))
    o.append(text(x0 + 24, ey + 70, "Base de Datos II · Unidad 3", size=13, fill=MUTED))

    o.append(rect(x0 + 24, ey + 92, 652, 118, PANEL2, r=12, stroke=BORDER))
    o.append(text(x0 + 44, ey + 124, "Pregunta 7 de 20", size=12, fill=ACC2, mono=True))
    o.append(text(x0 + 44, ey + 154, "¿Qué restricción garantiza la integridad", size=15))
    o.append(text(x0 + 44, ey + 182, "referencial entre dos tablas?", size=15))
    o.append(rect(x0 + 520, ey + 112, 136, 44, ACC2, r=10, op=0.14))
    o.append(text(x0 + 588, ey + 141, "18:42", size=20, fill=ACC2, weight=700,
                  anchor="middle", mono=True))

    opts = [("A", "PRIMARY KEY", False), ("B", "FOREIGN KEY", True),
            ("C", "UNIQUE", False), ("D", "CHECK", False)]
    oy = ey + 232
    for i, (letra, txt, sel) in enumerate(opts):
        col = ACC3 if sel else BORDER
        o.append(rect(x0 + 24, oy, 652, 42, ACC3 if sel else PANEL2, r=10,
                      stroke=col, sw=1.5, op=0.14 if sel else 1))
        o.append(circle(x0 + 48, oy + 21, 11, ACC3 if sel else MUTED, op=0.9 if sel else 0.3))
        o.append(text(x0 + 48, oy + 26, letra, size=12,
                      fill="#05070d" if sel else MUTED, weight=700, anchor="middle"))
        o.append(text(x0 + 74, oy + 27, txt, size=14, fill=INK if sel else MUTED,
                      weight=600 if sel else 400))
        oy += 50

    # Panel derecho: progreso
    px = x0 + 720
    pw = W - px - 32
    o.append(card(px, ey, pw, 424))
    o.append(text(px + 24, ey + 40, "Progreso en tiempo real", size=16, weight=600))
    prog = [("Cusi Rojas, M.", 95, ACC3), ("Quispe Luna, A.", 80, ACC3),
            ("Ramos Diaz, K.", 65, ACC), ("Flores Pino, J.", 45, ACC),
            ("Huamán V., L.", 30, WARN), ("Torres Yaya, S.", 15, WARN)]
    py = ey + 78
    for name, pct, col in prog:
        o.append(text(px + 24, py + 12, name, size=13, fill=MUTED))
        o.append(text(px + pw - 24, py + 12, f"{pct}%", size=12, fill=col,
                      anchor="end", mono=True))
        o.append(rect(px + 24, py + 24, pw - 48, 8, "#ffffff", r=4, op=0.07))
        o.append(rect(px + 24, py + 24, (pw - 48) * pct / 100, 8, col, r=4, op=0.85))
        py += 52

    o.append(f'<line x1="{px+24}" y1="{py+8}" x2="{px+pw-24}" y2="{py+8}" stroke="{BORDER}"/>')
    o.append(text(px + 24, py + 44, "Asistencia por QR", size=14, weight=600))
    qx, qy, qs = px + 24, py + 60, 76
    o.append(rect(qx, qy, qs, qs, "#ffffff", r=8, op=0.9))
    import random
    random.seed(7)
    for i in range(7):
        for j in range(7):
            if random.random() > 0.45:
                o.append(rect(qx + 8 + j * 9, qy + 8 + i * 9, 8, 8, "#05070d", r=1))
    o.append(text(qx + qs + 20, qy + 32, "Sesión activa", size=13, fill=ACC3))
    o.append(text(qx + qs + 20, qy + 58, "31 de 34 marcaron", size=13, fill=MUTED))
    return wrap(o)


# ---------------------------------------------------------------- Clínica
def clinica():
    o = header("cl", "clinica.alfredochm.com/citas", ACC3)
    o += sidebar("Clínica", ["Panel", "Pacientes", "Médicos", "Especialidades",
                             "Consultorios", "Citas", "Historias clínicas"], 5, ACC3)
    o += topbar("Agenda de citas", "Lunes 27 de julio · 4 consultorios activos", ACC3)

    x0, y0 = 262, 158
    for i, (lb, val, col) in enumerate([("CITAS DE HOY", "38", ACC3),
                                        ("ATENDIDAS", "21", ACC),
                                        ("PENDIENTES", "14", WARN),
                                        ("PACIENTES", "612", ACC2)]):
        sw = (W - x0 - 32 - 60) / 4
        o += stat(x0 + i * (sw + 20), y0, sw, lb, val, col)

    ty = y0 + 118
    o.append(card(x0, ty, 700, 424))
    o.append(text(x0 + 24, ty + 40, "Citas programadas", size=17, weight=600))
    o.append(rect(x0 + 520, ty + 20, 156, 32, ACC3, r=10, op=0.14))
    o.append(text(x0 + 598, ty + 41, "+ Nueva cita", size=13, fill=ACC3, weight=600,
                  anchor="middle"))
    for c, cx in [("Hora", 24), ("Paciente", 110), ("Especialidad", 330), ("Estado", 550)]:
        o.append(text(x0 + cx, ty + 78, c, size=12, fill=MUTED, mono=True))
    o.append(f'<line x1="{x0+16}" y1="{ty+94}" x2="{x0+684}" y2="{ty+94}" stroke="{BORDER}"/>')
    rows = [("08:30", "Mendoza Ríos, Carla", "Medicina General", "Atendida", ACC3),
            ("09:00", "Salas Peña, Julio", "Cardiología", "Atendida", ACC3),
            ("09:40", "Vega Ríos, Ana", "Pediatría", "En consulta", ACC),
            ("10:20", "Ortiz Campos, Luis", "Traumatología", "Pendiente", WARN),
            ("11:00", "Reyes Soto, María", "Dermatología", "Pendiente", WARN),
            ("11:45", "Cárdenas B., Pedro", "Odontología", "Reprogramada", ACC2)]
    ry = ty + 128
    for i, (hora, pac, esp, est, col) in enumerate(rows):
        if i % 2 == 0:
            o.append(rect(x0 + 16, ry - 24, 668, 48, "#ffffff", r=8, op=0.02))
        o.append(text(x0 + 24, ry, hora, size=13.5, fill=INK, mono=True))
        o.append(circle(x0 + 122, ry - 5, 12, ACC3, op=0.14))
        o.append(text(x0 + 144, ry, pac, size=13.5))
        o.append(text(x0 + 330, ry, esp, size=13.5, fill=MUTED))
        o.append(rect(x0 + 546, ry - 20, 128, 28, col, r=14, op=0.14))
        o.append(text(x0 + 610, ry - 1, est, size=12, fill=col, weight=600, anchor="middle"))
        ry += 52

    # Comprobante con QR
    px = x0 + 720
    pw = W - px - 32
    o.append(card(px, ty, pw, 262))
    o.append(text(px + 24, ty + 40, "Comprobante de cita", size=16, weight=600))
    o.append(rect(px + 24, ty + 62, 92, 28, ACC, r=8, op=0.14))
    o.append(text(px + 70, ty + 81, "PDF", size=12, fill=ACC, weight=700, anchor="middle",
                  mono=True))
    o.append(text(px + 24, ty + 122, "Paciente", size=12, fill=MUTED))
    o.append(text(px + 24, ty + 146, "Vega Ríos, Ana", size=14))
    o.append(text(px + 24, ty + 180, "Consultorio 03 · 09:40", size=13, fill=MUTED))
    o.append(text(px + 24, ty + 208, "Dr. Rivas · Pediatría", size=13, fill=MUTED))
    qs = 104
    qx, qy = px + pw - qs - 28, ty + 110
    o.append(rect(qx - 8, qy - 8, qs + 16, qs + 16, "#ffffff", r=10, op=0.92))
    import random
    random.seed(11)
    n = 9
    cell = qs / n
    for i in range(n):
        for j in range(n):
            if random.random() > 0.44:
                o.append(rect(qx + j * cell, qy + i * cell, cell - 1, cell - 1, "#05070d", r=1))

    # Ocupación por especialidad
    cy = ty + 282
    o.append(card(px, cy, pw, 142))
    o.append(text(px + 24, cy + 36, "Ocupación por especialidad", size=15, weight=600))
    data = [("Med. General", 82, ACC3), ("Pediatría", 64, ACC), ("Cardiología", 48, ACC2)]
    by = cy + 62
    for name, pct, col in data:
        o.append(text(px + 24, by + 10, name, size=12, fill=MUTED))
        o.append(rect(px + 150, by + 2, pw - 200, 9, "#ffffff", r=5, op=0.07))
        o.append(rect(px + 150, by + 2, (pw - 200) * pct / 100, 9, col, r=5, op=0.85))
        by += 26
    return wrap(o)


if __name__ == "__main__":
    for name, fn in [("mockup-alpunto.svg", alpunto),
                     ("mockup-evalpinguino.svg", evalpinguino),
                     ("mockup-clinica.svg", clinica)]:
        p = os.path.join(OUT, name)
        with open(p, "w", encoding="utf-8") as f:
            f.write(fn())
        print("ok", p, os.path.getsize(p), "bytes")
