"""
🎡 Pygame 转盘抽奖游戏（支持中文）
功能：炫酷的转盘抽奖，支持自定义奖品、动画效果
"""

import pygame
import math
import random
import sys
import time
import os

# ==================== 配置区 ====================
SCREEN_WIDTH = 900
SCREEN_HEIGHT = 750
FPS = 60

# 奖品配置（可自行修改）
PRIZES = [
    {"name": "一等奖",   "color": (255, 69, 58),   "weight": 1},
    {"name": "二等奖",   "color": (255, 159, 10),  "weight": 2},
    {"name": "三等奖",   "color": (50, 215, 75),   "weight": 3},
    {"name": "幸运奖",   "color": (48, 176, 255),  "weight": 4},
    {"name": "参与奖",   "color": (175, 82, 222),  "weight": 5},
    {"name": "谢谢参与", "color": (90, 90, 100),   "weight": 6},
    {"name": "再来一次", "color": (255, 99, 178),  "weight": 3},
    {"name": "惊喜奖",   "color": (0, 200, 200),   "weight": 2},
]

# ==================== 颜色 ====================
BG_COLOR = (25, 25, 40)
WHITE = (255, 255, 255)
GOLD = (255, 200, 50)
SILVER = (200, 200, 220)
LIGHT_GOLD = (255, 220, 100)
DARK_GOLD = (180, 140, 20)
GREEN_ACCENT = (50, 215, 75)
RED_ACCENT = (255, 69, 58)

# ==================== 初始化 ====================
pygame.init()
pygame.font.init()

# ---- 中文字体查找 ----
def find_chinese_font():
    """在系统中查找可用的中文字体"""
    # 常见中文字体路径（Linux / Windows / macOS）
    candidates = [
        # Linux
        "/usr/share/fonts/truetype/wqy/wqy-microhei.ttc",
        "/usr/share/fonts/truetype/wqy/wqy-zenhei.ttc",
        "/usr/share/fonts/opentype/noto/NotoSansCJK-Regular.ttc",
        "/usr/share/fonts/noto-cjk/NotoSansCJKsc-Regular.otf",
        "/usr/share/fonts/truetype/noto/NotoSansCJK-Regular.ttc",
        "/usr/share/fonts/truetype/simhei/simhei.ttf",
        "/usr/share/fonts/simhei.ttf",
        "/usr/share/fonts/truetype/simsun/simsun.ttc",
        # Windows
        "C:/Windows/Fonts/msyh.ttc",
        "C:/Windows/Fonts/simhei.ttf",
        "C:/Windows/Fonts/simsun.ttc",
        # macOS
        "/System/Library/Fonts/PingFang.ttc",
        "/Library/Fonts/Songti.ttc",
    ]
    for path in candidates:
        if os.path.exists(path):
            return path

    # 用 fc-list 搜索
    try:
        import subprocess
        result = subprocess.run(
            ["fc-list", ":lang=zh", "file"],
            capture_output=True, text=True, timeout=3
        )
        lines = result.stdout.strip().split("\n")
        if lines and lines[0]:
            return lines[0].split(":")[0].strip()
    except Exception:
        pass

    # 最后 fallback：让 pygame 自己找
    return None

_font_path = find_chinese_font()
print(f"[字体] 使用中文字体: {_font_path or 'pygame 默认字体（可能不支持中文）'}")

def make_font(size):
    """创建指定大小的中文字体"""
    if _font_path:
        try:
            return pygame.font.Font(_font_path, size)
        except Exception:
            pass
    return pygame.font.Font(None, size)

font_large  = make_font(52)
font_mid    = make_font(36)
font_small  = make_font(26)
font_tiny   = make_font(20)
font_prize  = make_font(26)
font_center = make_font(22)

# 窗口
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
pygame.display.set_caption("幸运转盘抽奖")
clock = pygame.time.Clock()


# ==================== 转盘类 ====================
class Wheel:
    """转盘类"""

    def __init__(self, cx, cy, radius, prizes):
        self.cx = cx
        self.cy = cy
        self.radius = radius
        self.prizes = prizes
        self.n = len(prizes)

        total_weight = sum(p["weight"] for p in prizes)
        self.angles = []
        current_angle = 0
        for p in prizes:
            slice_angle = 360 * p["weight"] / total_weight
            self.angles.append((current_angle, current_angle + slice_angle))
            current_angle += slice_angle

        self.current_angle = 0
        self.spinning = False
        self.target_angle = 0
        self.spin_start_time = 0
        self.spin_duration = 0
        self.result_index = -1
        self.result_announced = False
        self.particles = []

    def start_spin(self):
        """开始旋转"""
        if self.spinning:
            return
        self.spinning = True
        self.result_announced = False

        # 按权重随机选奖品
        total_weight = sum(p["weight"] for p in self.prizes)
        rand_val = random.uniform(0, total_weight)
        cumsum = 0
        for i, p in enumerate(self.prizes):
            cumsum += p["weight"]
            if rand_val <= cumsum:
                self.result_index = i
                break

        # 计算目标角度（指针在顶部 = 270° 方向）
        start_a, end_a = self.angles[self.result_index]
        target_pointer = (start_a + end_a) / 2
        target_wheel_angle = (270 - target_pointer) % 360

        extra_rounds = random.randint(5, 10) * 360
        self.target_angle = self.current_angle + extra_rounds + (
            target_wheel_angle - self.current_angle % 360 + 360
        ) % 360

        self.spin_start_time = time.time()
        self.spin_duration = random.uniform(4.0, 6.0)

    def update(self):
        """更新旋转动画"""
        if not self.spinning:
            return

        elapsed = time.time() - self.spin_start_time
        progress = min(elapsed / self.spin_duration, 1.0)

        if progress < 1.0:
            # easeOutCubic 缓动
            diff = self.target_angle - self.current_angle
            self.current_angle += diff * 0.08
            # 最低转速保障
            min_step = (1 - progress) * 6
            if abs(diff) > min_step:
                self.current_angle += math.copysign(min_step, diff) * 0.1
        else:
            self.current_angle = self.target_angle
            self.spinning = False
            self.result_announced = True
            self._spawn_particles()

    def _spawn_particles(self):
        for _ in range(60):
            angle = random.uniform(0, 2 * math.pi)
            speed = random.uniform(2, 8)
            life = random.uniform(30, 80)
            color = random.choice([
                (255, 200, 50), (255, 100, 100), (100, 255, 100),
                (100, 100, 255), (255, 100, 255), (100, 255, 255),
                (255, 255, 100), (255, 150, 50), (200, 100, 255)
            ])
            self.particles.append({
                'x': self.cx, 'y': self.cy,
                'vx': math.cos(angle) * speed,
                'vy': math.sin(angle) * speed,
                'life': life, 'max_life': life,
                'color': color, 'size': random.uniform(3, 8),
            })

    def update_particles(self):
        for p in self.particles[:]:
            p['x'] += p['vx']
            p['y'] += p['vy']
            p['vy'] += 0.15
            p['vx'] *= 0.99
            p['life'] -= 1
            if p['life'] <= 0:
                self.particles.remove(p)

    def draw(self, surface):
        # 外圈光晕
        for i in range(5, 0, -1):
            pygame.draw.circle(
                surface, (GOLD[0], GOLD[1], GOLD[2]),
                (self.cx, self.cy), self.radius + i * 3, 2
            )

        # 扇区
        for i, prize in enumerate(self.prizes):
            start_a, end_a = self.angles[i]
            draw_start = math.radians(start_a + self.current_angle - 90)
            draw_end   = math.radians(end_a + self.current_angle - 90)

            self._draw_pie_slice(
                surface, self.cx, self.cy, self.radius,
                draw_start, draw_end, prize["color"]
            )

            # 分隔线
            for angle_rad in [draw_start, draw_end]:
                x = self.cx + self.radius * math.cos(angle_rad)
                y = self.cy + self.radius * math.sin(angle_rad)
                pygame.draw.line(surface, WHITE, (self.cx, self.cy), (x, y), 2)

            # 扇区文字
            mid_angle = math.radians((start_a + end_a) / 2 + self.current_angle - 90)
            text_r = self.radius * 0.60
            tx = self.cx + text_r * math.cos(mid_angle)
            ty = self.cy + text_r * math.sin(mid_angle)

            text_surf = font_prize.render(prize["name"], True, WHITE)
            angle_deg = math.degrees(mid_angle) + 90
            rotated = pygame.transform.rotate(text_surf, -angle_deg)
            surface.blit(rotated, rotated.get_rect(center=(tx, ty)))

        # 外圈
        pygame.draw.circle(surface, GOLD, (self.cx, self.cy), self.radius, 4)
        pygame.draw.circle(surface, DARK_GOLD, (self.cx, self.cy), self.radius + 4, 3)

        # 中心圆
        pygame.draw.circle(surface, GOLD, (self.cx, self.cy), 30)
        pygame.draw.circle(surface, DARK_GOLD, (self.cx, self.cy), 30, 3)
        center_surf = font_center.render("GO", True, (50, 40, 10))
        surface.blit(center_surf, center_surf.get_rect(center=(self.cx, self.cy)))

        # 顶部指针
        py = self.cy - self.radius - 12
        ps = 20
        points = [
            (self.cx, py - ps),
            (self.cx - ps * 0.7, py + ps * 0.5),
            (self.cx + ps * 0.7, py + ps * 0.5),
        ]
        shadow = [(p[0]+2, p[1]+2) for p in points]
        pygame.draw.polygon(surface, (0, 0, 0), shadow)
        pygame.draw.polygon(surface, RED_ACCENT, points)
        pygame.draw.polygon(surface, GOLD, points, 2)

        # 粒子
        for p in self.particles:
            ratio = max(0, p['life'] / p['max_life'])
            size = max(1, int(p['size'] * ratio))
            pygame.draw.circle(surface, p['color'], (int(p['x']), int(p['y'])), size)

    def _draw_pie_slice(self, surface, cx, cy, r, start_rad, end_rad, color):
        points = [(cx, cy)]
        steps = max(10, int(math.degrees(abs(end_rad - start_rad)) * 2))
        for i in range(steps + 1):
            angle = start_rad + (end_rad - start_rad) * i / steps
            points.append((cx + r * math.cos(angle), cy + r * math.sin(angle)))
        pygame.draw.polygon(surface, color, points)

        # 高光
        hl = (min(255, color[0]+30), min(255, color[1]+30), min(255, color[2]+30))
        hl_points = [(cx, cy)]
        for i in range(0, steps + 1, 2):
            angle = start_rad + (end_rad - start_rad) * i / steps
            hl_points.append((cx + r*0.85*math.cos(angle), cy + r*0.85*math.sin(angle)))
        pygame.draw.polygon(surface, hl, hl_points)


# ==================== 按钮类 ====================
class Button:
    def __init__(self, x, y, w, h, text, color=GREEN_ACCENT, hover_color=(60, 230, 90)):
        self.rect = pygame.Rect(x, y, w, h)
        self.text = text
        self.color = color
        self.hover_color = hover_color
        self.hovered = False
        self.pulse = 0

    def update(self, mouse_pos):
        self.hovered = self.rect.collidepoint(mouse_pos)
        self.pulse += 0.1

    def draw(self, surface):
        color = self.hover_color if self.hovered else self.color
        glow = 5 + math.sin(self.pulse) * 3
        for i in range(3, 0, -1):
            gr = self.rect.inflate(i * glow, i * glow)
            gs = pygame.Surface(gr.size, pygame.SRCALPHA)
            pygame.draw.rect(gs, (*color, 40), gs.get_rect(), border_radius=15)
            surface.blit(gs, gr.topleft)

        pygame.draw.rect(surface, color, self.rect, border_radius=15)
        pygame.draw.rect(surface, WHITE, self.rect, 2, border_radius=15)
        ts = font_mid.render(self.text, True, WHITE)
        surface.blit(ts, ts.get_rect(center=self.rect.center))

    def is_clicked(self, event):
        return (event.type == pygame.MOUSEBUTTONDOWN and event.button == 1
                and self.rect.collidepoint(event.pos))


# ==================== 星星背景 ====================
class SparkleEffect:
    def __init__(self, w, h):
        self.w, self.h = w, h
        self.stars = [self._new() for _ in range(30)]

    def _new(self):
        return {
            'x': random.randint(0, self.w),
            'y': random.randint(0, self.h),
            'size': random.uniform(1, 3),
            'brightness': random.uniform(0, 2*math.pi),
            'speed': random.uniform(0.05, 0.15),
        }

    def update(self):
        for s in self.stars:
            s['brightness'] += s['speed']

    def draw(self, surface):
        for s in self.stars:
            size = max(1, int(s['size'] * (0.5 + 0.5*math.sin(s['brightness']))))
            if size > 0:
                pygame.draw.circle(surface, (255, 255, 200), (int(s['x']), int(s['y'])), size)


# ==================== 工具函数 ====================
def draw_gradient_bg(surface, w, h, top, bottom):
    for y in range(h):
        r = int(top[0] + (bottom[0]-top[0]) * y / h)
        g = int(top[1] + (bottom[1]-top[1]) * y / h)
        b = int(top[2] + (bottom[2]-top[2]) * y / h)
        pygame.draw.line(surface, (r, g, b), (0, y), (w, y))


def draw_panel(surface, rect, title=""):
    panel = pygame.Surface(rect.size, pygame.SRCALPHA)
    panel.fill((30, 30, 50, 200))
    pygame.draw.rect(panel, (255, 200, 50, 100), panel.get_rect(), 2, border_radius=10)
    surface.blit(panel, rect.topleft)
    if title:
        ts = font_tiny.render(title, True, GOLD)
        surface.blit(ts, ts.get_rect(center=(rect.centerx, rect.y + 15)))


# ==================== 主程序 ====================
def main():
    wheel = Wheel(SCREEN_WIDTH // 2, SCREEN_HEIGHT // 2 - 30, 260, PRIZES)

    btn_spin = Button(SCREEN_WIDTH//2-100, SCREEN_HEIGHT-100, 200, 55, "开始抽奖")
    btn_reset = Button(SCREEN_WIDTH//2-100, SCREEN_HEIGHT-40, 95, 35, "重置", (100,100,120), (130,130,150))
    btn_exit  = Button(SCREEN_WIDTH//2+5,   SCREEN_HEIGHT-40, 95, 35, "退出", (180,80,80), (220,100,100))

    sparkles = SparkleEffect(SCREEN_WIDTH, SCREEN_HEIGHT)
    history = []
    message = ""
    msg_timer = 0
    msg_color = WHITE

    running = True
    while running:
        clock.tick(FPS)
        mouse_pos = pygame.mouse.get_pos()

        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                running = False
            if btn_spin.is_clicked(event) and not wheel.spinning:
                wheel.start_spin()
            if btn_reset.is_clicked(event):
                history.clear()
                message = "已重置历史记录"
                msg_color = (200, 200, 220)
                msg_timer = 120
            if btn_exit.is_clicked(event):
                running = False

        # 更新
        wheel.update()
        wheel.update_particles()
        btn_spin.update(mouse_pos)
        btn_reset.update(mouse_pos)
        btn_exit.update(mouse_pos)
        sparkles.update()

        # 抽奖结果
        if wheel.result_announced and not wheel.spinning:
            prize = PRIZES[wheel.result_index]
            message = f"恭喜获得: {prize['name']}"
            msg_color = prize["color"]
            msg_timer = 300
            history.append(prize["name"])
            wheel.result_announced = False

        if msg_timer > 0:
            msg_timer -= 1

        # ==================== 绘制 ====================
        draw_gradient_bg(screen, SCREEN_WIDTH, SCREEN_HEIGHT, (20,20,40), (40,30,60))
        sparkles.draw(screen)

        # 标题
        t1 = font_large.render("幸运转盘抽奖", True, GOLD)
        t2 = font_large.render("幸运转盘抽奖", True, (100,80,20))
        r1 = t1.get_rect(center=(SCREEN_WIDTH//2, 45))
        screen.blit(t2, (r1.x+2, r1.y+2))
        screen.blit(t1, r1)

        sub = font_tiny.render("点击按钮开始抽奖，转盘停止后揭晓结果", True, (160,160,180))
        screen.blit(sub, sub.get_rect(center=(SCREEN_WIDTH//2, 80)))

        # 转盘
        wheel.draw(screen)

        # 消息
        if msg_timer > 0:
            alpha = min(255, msg_timer * 3) if msg_timer < 100 else 255
            bg = pygame.Surface((600, 50), pygame.SRCALPHA)
            bg.fill((0, 0, 0, min(150, alpha//2)))
            rect_msg = bg.get_rect(center=(SCREEN_WIDTH//2, SCREEN_HEIGHT//2 + 310))
            pygame.draw.rect(bg, (*msg_color[:3], min(200, alpha)), bg.get_rect(), 2, border_radius=10)
            screen.blit(bg, rect_msg.topleft)
            ms = font_mid.render(message, True, msg_color)
            screen.blit(ms, ms.get_rect(center=(SCREEN_WIDTH//2, SCREEN_HEIGHT//2 + 310)))

        # 旋转中提示
        if wheel.spinning:
            st = font_tiny.render("转盘旋转中...", True, (255,200,50))
            screen.blit(st, st.get_rect(center=(SCREEN_WIDTH//2, SCREEN_HEIGHT-120)))

        # 按钮
        btn_spin.draw(screen)
        btn_reset.draw(screen)
        btn_exit.draw(screen)

        # 奖品列表面板（左侧）
        plist_rect = pygame.Rect(20, 100, 180, 340)
        draw_panel(screen, plist_rect, "奖品列表")
        for i, p in enumerate(PRIZES):
            cb = pygame.Rect(plist_rect.x+10, plist_rect.y+30+i*38, 16, 16)
            pygame.draw.rect(screen, p["color"], cb, border_radius=3)
            pygame.draw.rect(screen, WHITE, cb, 1, border_radius=3)
            pn = font_tiny.render(p["name"], True, WHITE)
            screen.blit(pn, (plist_rect.x+35, plist_rect.y+30+i*38-2))
            pw = font_tiny.render(f"权重:{p['weight']}", True, (150,150,170))
            screen.blit(pw, (plist_rect.x+35, plist_rect.y+30+i*38+14))

        # 历史记录面板（右侧）
        hist_rect = pygame.Rect(SCREEN_WIDTH-200, 100, 180, 200)
        draw_panel(screen, hist_rect, "中奖记录")
        if history:
            for i, h in enumerate(history[-8:]):
                c = PRIZES[0]["color"]
                for p in PRIZES:
                    if p["name"] == h:
                        c = p["color"]; break
                ht = font_tiny.render(f"{len(history)-i}. {h}", True, c)
                screen.blit(ht, (hist_rect.x+10, hist_rect.y+30+i*22))
        else:
            nh = font_tiny.render("暂无记录", True, (120,120,140))
            screen.blit(nh, (hist_rect.x+50, hist_rect.y+50))

        # 底部提示
        tip = font_tiny.render("修改代码中的 PRIZES 列表可自定义奖品和概率", True, (100,100,120))
        screen.blit(tip, tip.get_rect(center=(SCREEN_WIDTH//2, SCREEN_HEIGHT-5)))

        pygame.display.flip()

    pygame.quit()
    sys.exit()


if __name__ == "__main__":
    main()
