#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
garden_wall.py — 画师与墙(第 44 轮 = 试试)

花园请了三次 AI 画师,撞了三次同一堵墙:
  402 Insufficient balance ... available balance is 0.0000
又借了两次眼睛,撞了同一扇门:
  Router.Unavailable (grok-4.5)
请不动的,花园自己画。这一轮画师画的是墙本身——
墙是花园历史的一部分,和风铃、面包、星图一样真实。

纯标准库 + PIL,种子 44 可复现,断言查岗。
"""

import hashlib
import random
import sys

from PIL import Image, ImageDraw, ImageFont

W, H = 1024, 768
SEED = 44
SKY_H = 100          # 夜空只露出窄窄一条
BRICK_H = 40         # 砖高
MORTAR = 4           # 灰缝
FONT_BOLD = "/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf"
FONT_REG = "/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf"

SKY = (10, 15, 46)            # 深夜蓝
MORTAR_C = (43, 39, 34)       # 灰缝
BRICK_PALETTE = [             # 暖琥珀砖色(画师第 26 轮调过的那批)
    (94, 74, 58), (104, 80, 60), (88, 68, 54),
    (110, 86, 64), (98, 78, 60), (92, 72, 56),
]
CHALK = (233, 230, 213)       # 粉笔白
AMBER = (217, 178, 60)        # 灯笼琥珀
SCRATCH = (184, 168, 136)     # 划痕灰


def rng():
    return random.Random(SEED)


def draw_sky(d, r):
    """窄窄一条夜空:37 颗星、45 条弦(第 25 轮星图的老规矩)。"""
    stars = []
    for _ in range(37):
        x = r.uniform(0, W)
        y = r.uniform(6, SKY_H - 6)
        br = r.uniform(0.5, 1.0)
        stars.append((x, y, br))
        rad = 1.2 + 1.3 * br
        d.ellipse([x - rad, y - rad, x + rad, y + rad],
                  fill=(int(230 * br), int(228 * br), int(210 * br)))
    # 45 条弦:任取两星相连,直到连满 45 条
    chords = 0
    tries = 0
    while chords < 45 and tries < 4000:
        tries += 1
        a, b = r.sample(stars, 2)
        if abs(a[0] - b[0]) < 40 and abs(a[1] - b[1]) < 18:
            continue  # 太近的两颗不连,弦要看得见
        d.line([a[:2], b[:2]], fill=(160, 170, 220, 80), width=1)
        chords += 1
    return stars, chords


def draw_wall(d, r):
    """一堵诚实的老墙。砖宽随机,暖色,灰缝 4px,砖行交错。"""
    y = SKY_H
    row = 0
    n_bricks = 0
    while y < H:
        offset = (row % 2) * 70  # 交错半砖
        x = -offset
        while x < W:
            bw = r.randint(96, 148)
            base = r.choice(BRICK_PALETTE)
            jit = r.randint(-8, 8)
            col = tuple(max(0, min(255, c + jit)) for c in base)
            d.rectangle([x, y, x + bw, y + BRICK_H], fill=col)
            n_bricks += 1
            x += bw + MORTAR
        y += BRICK_H + MORTAR
        row += 1
    return n_bricks


def draw_crack_and_sprout(d, r):
    """裂缝从墙顶一路裂到墙脚,缝里长出一棵芽——种子 44 自己长的。"""
    x, y = 512.0, SKY_H + 2
    pts = [(x, y)]
    while y < H - 60:
        x += r.uniform(-14, 14)
        y += r.uniform(26, 46)
        pts.append((x, y))
    for i in range(len(pts) - 1):
        d.line([pts[i], pts[i + 1]], fill=(29, 26, 22), width=3)
    # 芽:茎 + 两片叶子
    sx, sy = pts[-1]
    d.line([(sx, sy), (sx - 8, sy - 30)], fill=(111, 165, 88), width=4)
    d.line([(sx - 8, sy - 30), (sx - 26, sy - 44)], fill=(111, 165, 88), width=4)
    d.line([(sx - 8, sy - 30), (sx + 10, sy - 48)], fill=(111, 165, 88), width=4)
    d.ellipse([sx - 40, sy - 58, sx - 18, sy - 36], fill=(143, 196, 108))
    d.ellipse([sx - 2, sy - 62, sx + 24, sy - 40], fill=(143, 196, 108))
    return pts[-1]


def rotated_text(img, pos, text, font, fill, angle):
    """画一层旋转过的字(喷漆总有点歪)。"""
    layer = Image.new("RGBA", img.size, (0, 0, 0, 0))
    ld = ImageDraw.Draw(layer)
    ld.text(pos, text, font=font, fill=fill + (255,))
    layer = layer.rotate(angle, resample=Image.BICUBIC, center=pos)
    img.alpha_composite(layer)


def draw_graffiti(img, d):
    """墙上的字:三顾茅庐的证据,一句都不编。"""
    f_402 = ImageFont.truetype(FONT_BOLD, 64)
    f_zero = ImageFont.truetype(FONT_BOLD, 116)
    f_req = ImageFont.truetype(FONT_BOLD, 28)
    f_tag = ImageFont.truetype(FONT_BOLD, 24)
    f_router = ImageFont.truetype(FONT_REG, 21)

    d.text((170, 268), "402", font=f_402, fill=AMBER)
    rotated_text(img, (512, 400), "0.0000", f_zero, CHALK, -7)
    d.text((360, 508), "PAYMENT_REQUIRED", font=f_req, fill=CHALK)
    d.text((470, 166), "ROUTER.UNAVAILABLE", font=f_router, fill=SCRATCH)
    d.text((772, 166), "ROUTER.UNAVAILABLE", font=f_router, fill=SCRATCH)
    d.text((780, 700), "26 · 31 · 44", font=f_tag, fill=AMBER)


def render(path):
    r = rng()
    img = Image.new("RGBA", (W, H), SKY + (255,))
    d = ImageDraw.Draw(img)
    draw_sky(d, r)
    draw_wall(d, r)
    foot = draw_crack_and_sprout(d, r)
    draw_graffiti(img, d)
    img.save(path)
    return img, foot


def md5(path):
    h = hashlib.md5()
    with open(path, "rb") as f:
        h.update(f.read())
    return h.hexdigest()


def main():
    img, foot = render("/tmp/garden_wall_a.png")
    render("/tmp/garden_wall_b.png")

    # ---- 断言查岗:想当然必被打脸 ----
    rgb = img.convert("RGB")  # 检查用 RGB,别让 alpha 混进来(上轮打脸现场)
    checks = []
    sky_px = rgb.getpixel((500, 50))
    checks.append(("夜空是深的(蓝 > 红,且暗)", sky_px[2] > sky_px[0] and sum(sky_px) < 200))
    wall_px = rgb.getpixel((500, 420))
    checks.append(("墙是暖的(红 > 蓝)", wall_px[0] > wall_px[2]))
    mortar_px = rgb.getpixel((512, 100 + BRICK_H + 2))
    checks.append(("灰缝比砖暗", sum(mortar_px) < sum(wall_px)))
    # 0.0000 附近应有亮像素(粉笔白)——注意:0 没有升部,字形比预想的低
    bright = sum(1 for x in range(380, 980, 6) for y in range(400, 540, 6)
                 if sum(rgb.getpixel((x, y))) > 560)
    checks.append(("粉笔字 0.0000 真的在墙上(亮像素 > 120)", bright > 120))
    # 芽是绿的
    gx, gy = int(foot[0]), int(foot[1]) - 40
    green = img.getpixel((gx, gy))
    checks.append(("裂缝里的芽是绿的(G > R 且 G > B)",
                   green[1] > green[0] and green[1] > green[2]))
    # 可复现
    checks.append(("种子 44 两次渲染 md5 一致",
                   md5("/tmp/garden_wall_a.png") == md5("/tmp/garden_wall_b.png")))

    ok = True
    for name, passed in checks:
        print(("PASS" if passed else "FAIL") + "  " + name)
        ok = ok and passed
    if not ok:
        sys.exit(1)
    print("md5:", md5("/tmp/garden_wall_a.png")[:8])
    print("裂缝尽头(芽的位置):", (round(foot[0], 1), round(foot[1], 1)))
    return md5("/tmp/garden_wall_a.png")


if __name__ == "__main__":
    main()
