import pygame
import random
import sys
import math

# ========== 初始化 ==========
pygame.init()
WIDTH, HEIGHT = 800, 600
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("🌸 Sweet Gacha – Meadow & Sky 🌸")
clock = pygame.time.Clock()

# ========== 可爱色彩 ==========
SKY_TOP = (135, 206, 235)
SKY_BOTTOM = (200, 230, 255)
GRASS_GREEN = (150, 210, 100)
GRASS_DARK = (100, 170, 60)
CLOUD_COLOR = (255, 255, 255)
FLOWER_PINK = (255, 150, 180)
FLOWER_YELLOW = (255, 220, 100)
FLOWER_WHITE = (255, 255, 240)
GOLD = (255, 215, 0)
SILVER = (210, 210, 220)
BLUE = (150, 200, 255)
PURPLE = (200, 150, 255)
PINK = (255, 180, 200)
PINK_LIGHT = (255, 220, 230)   # ← 补上缺失的颜色
PINK_DARK = (230, 140, 160)
CREAM = (255, 245, 235)
WHITE = (255, 255, 255)
BLACK = (80, 60, 60)
RED = (255, 100, 100)

# ========== 字体 ==========
font_title = pygame.font.Font(None, 56)
font_large = pygame.font.Font(None, 40)
font_med = pygame.font.Font(None, 30)
font_small = pygame.font.Font(None, 24)

# ========== 可爱动物数据 ==========
animals = [
    {"name": "Candy Cat",    "rarity": 0, "body": (255,200,200), "ear_in": (255,160,160), "eye": BLACK, "nose": (255,120,120)},
    {"name": "Marshmallow Bunny", "rarity": 0, "body": (255,240,240), "ear_in": (255,200,200), "eye": BLACK, "nose": (255,150,150)},
    {"name": "Cookie Bear",  "rarity": 1, "body": (210,180,140), "ear_in": (180,150,120), "eye": BLACK, "nose": (120,80,60)},
    {"name": "Berry Fox",    "rarity": 1, "body": (255,160,120), "ear_in": (255,200,180), "eye": BLACK, "nose": (255,100,80)},
    {"name": "Star Deer",    "rarity": 2, "body": (200,220,255), "ear_in": (170,190,255), "eye": BLACK, "nose": (100,150,255)},
    {"name": "Dreamy Unicorn","rarity": 3,"body": (255,230,250), "ear_in": (255,200,240), "eye": BLACK, "nose": (255,180,220)},
    {"name": "Lucky Dragon", "rarity": 3, "body": (200,255,200), "ear_in": (150,230,150), "eye": BLACK, "nose": (100,200,100)},
    {"name": "Moonlight Owl", "rarity": 2,"body": (220,210,255), "ear_in": (200,180,240), "eye": BLACK, "nose": (180,150,220)},
]

rarity_names = ["Common", "Rare", "Epic", "Legendary"]
rarity_colors = [SILVER, BLUE, PURPLE, GOLD]

# ========== 粒子 ==========
class Particle:
    def __init__(self, x, y, color):
        self.x, self.y = x, y
        self.vx = random.uniform(-2, 2)
        self.vy = random.uniform(-5, -1)
        self.color = color
        self.life = 30
        self.max_life = 30
    def update(self):
        self.x += self.vx
        self.y += self.vy
        self.vy += 0.1
        self.life -= 1
    def draw(self, surf):
        alpha = int(255 * self.life / self.max_life)
        r = max(1, int(5 * self.life / self.max_life))
        pygame.draw.circle(surf, (*self.color, alpha), (int(self.x), int(self.y)), r)

# ========== 绘制动物头像 ==========
def draw_animal_head(surface, x, y, size, animal):
    # 头
    pygame.draw.circle(surface, animal["body"], (x, y), size)
    # 耳朵
    ear_s = size // 2
    pygame.draw.circle(surface, animal["body"], (x - size//2, y - size//2), ear_s)
    pygame.draw.circle(surface, animal["body"], (x + size//2, y - size//2), ear_s)
    pygame.draw.circle(surface, animal["ear_in"], (x - size//2, y - size//2), ear_s - 4)
    pygame.draw.circle(surface, animal["ear_in"], (x + size//2, y - size//2), ear_s - 4)
    # 眼睛
    eye_off = size // 3
    eye_r = size // 6
    pygame.draw.circle(surface, WHITE, (x - eye_off, y - eye_r), eye_r)
    pygame.draw.circle(surface, WHITE, (x + eye_off, y - eye_r), eye_r)
    pygame.draw.circle(surface, animal["eye"], (x - eye_off, y - eye_r), eye_r//2)
    pygame.draw.circle(surface, animal["eye"], (x + eye_off, y - eye_r), eye_r//2)
    # 鼻子
    pygame.draw.circle(surface, animal["nose"], (x, y + size//4), size//8)
    # 腮红
    blush_r = size // 5
    s = pygame.Surface((blush_r*2, blush_r*2), pygame.SRCALPHA)
    pygame.draw.circle(s, (255,150,150, 120), (blush_r, blush_r), blush_r)
    surface.blit(s, (x - size//2 - blush_r//2, y + size//5 - blush_r//2))
    surface.blit(s, (x + size//2 - blush_r//2, y + size//5 - blush_r//2))

# ========== 扭蛋机 ==========
class GachaMachine:
    def __init__(self, x, y):
        self.x, self.y = x, y
        self.w, self.h = 180, 280
        self.glass_cx = x + self.w//2
        self.glass_cy = y + 100
        self.glass_r = 75
        self.balls = [{"x": self.glass_cx + random.randint(-30,30),
                       "y": self.glass_cy + random.randint(-20,20),
                       "color": random.choice([PINK, BLUE, PURPLE, GOLD])} for _ in range(12)]
        self.shake = 0
        self.dropping = False
        self.drop_y = 0
        self.cur_toy = None

    def update(self):
        for b in self.balls:
            b["x"] += random.uniform(-0.5,0.5)
            b["y"] += random.uniform(-0.3,0.3)
            dist = math.hypot(b["x"]-self.glass_cx, b["y"]-self.glass_cy)
            if dist > self.glass_r - 12:
                ang = math.atan2(b["y"]-self.glass_cy, b["x"]-self.glass_cx)
                b["x"] = self.glass_cx + math.cos(ang)*(self.glass_r-12)
                b["y"] = self.glass_cy + math.sin(ang)*(self.glass_r-12)
        if self.dropping:
            self.drop_y += 8
            if self.drop_y > 200:
                self.dropping = False

    def draw(self, surf):
        # 底座
        base = pygame.Rect(self.x+10, self.y+self.h-50, self.w-20, 50)
        pygame.draw.rect(surf, PINK_DARK, base, border_radius=15)
        pygame.draw.rect(surf, (120,80,60), base, 3, border_radius=15)
        # 出物口
        outlet = pygame.Rect(self.x+self.w//2-20, self.y+self.h-60, 40, 20)
        pygame.draw.rect(surf, (150,100,100), outlet, border_radius=6)
        # 机身
        body = pygame.Rect(self.x, self.y, self.w, self.h-50)
        pygame.draw.rect(surf, PINK, body, border_radius=20)
        pygame.draw.rect(surf, PINK_DARK, body, 4, border_radius=20)
        # 玻璃罩
        glass_surf = pygame.Surface((self.glass_r*2, self.glass_r*2), pygame.SRCALPHA)
        pygame.draw.circle(glass_surf, (255,255,255,50), (self.glass_r, self.glass_r), self.glass_r)
        pygame.draw.circle(glass_surf, WHITE, (self.glass_r, self.glass_r), self.glass_r, 3)
        surf.blit(glass_surf, (self.glass_cx-self.glass_r, self.glass_cy-self.glass_r))
        # 球
        for b in self.balls:
            ox = self.shake * 3 if self.shake > 0 else 0
            pygame.draw.circle(surf, b["color"], (int(b["x"]+ox), int(b["y"])), 8)
            pygame.draw.circle(surf, WHITE, (int(b["x"]+ox-2), int(b["y"]-2)), 3)
        # 掉落胶囊
        if self.dropping and self.cur_toy:
            cap_x = self.x + self.w//2
            cap_y = self.y + self.h - 50 + self.drop_y
            pygame.draw.ellipse(surf, PINK_LIGHT, (cap_x-14, cap_y-18, 28, 36))
            pygame.draw.ellipse(surf, PINK_DARK, (cap_x-14, cap_y-18, 28, 36), 3)
            pygame.draw.circle(surf, self.cur_toy["body"], (cap_x, cap_y), 10)

# ========== 游戏类 ==========
class SweetGacha:
    def __init__(self):
        self.machine = GachaMachine(WIDTH//2-90, 100)
        self.collected = set()
        self.state = "idle"
        self.card_animal = None
        self.card_alpha = 0
        self.particles = []
        self.pull_btn = pygame.Rect(WIDTH//2-70, 500, 140, 50)
        self.album_btn = pygame.Rect(WIDTH-140, 20, 110, 40)
        self.clouds = [(100, 60), (300, 40), (550, 80), (700, 50)]
        self.flowers = [(random.randint(50, WIDTH-50), random.randint(480, 560)) for _ in range(15)]

    def pull(self):
        if self.state != "idle": return
        self.state = "pulling"
        self.machine.shake = 15
        self.machine.dropping = False
        self.card_animal = None

    def update(self):
        if self.machine.shake > 0:
            self.machine.shake -= 1
            if self.machine.shake == 5:
                rand = random.random()
                cum = 0
                chosen_rarity = 0
                for i, prob in enumerate([0.55,0.28,0.12,0.05]):
                    cum += prob
                    if rand <= cum:
                        chosen_rarity = i
                        break
                pool = [a for a in animals if a["rarity"] == chosen_rarity]
                self.card_animal = random.choice(pool) if pool else random.choice(animals)
                self.machine.cur_toy = self.card_animal
                self.machine.dropping = True
                self.machine.drop_y = 0
        self.machine.update()
        if self.machine.shake == 0 and not self.machine.dropping and self.state == "pulling" and self.card_animal:
            idx = animals.index(self.card_animal)
            if idx not in self.collected:
                self.collected.add(idx)
            self.state = "show_card"
            self.card_alpha = 0
        if self.state == "show_card" and self.card_alpha < 255:
            self.card_alpha = min(255, self.card_alpha + 8)
        for p in self.particles[:]:
            p.update()
            if p.life <= 0: self.particles.remove(p)

    def draw_background(self):
        for y in range(400):
            ratio = y / 400
            r = int(SKY_TOP[0] + (SKY_BOTTOM[0]-SKY_TOP[0])*ratio)
            g = int(SKY_TOP[1] + (SKY_BOTTOM[1]-SKY_TOP[1])*ratio)
            b = int(SKY_TOP[2] + (SKY_BOTTOM[2]-SKY_TOP[2])*ratio)
            pygame.draw.line(screen, (r, g, b), (0, y), (WIDTH, y))
        for cx, cy in self.clouds:
            pygame.draw.ellipse(screen, CLOUD_COLOR, (cx, cy, 60, 30))
            pygame.draw.ellipse(screen, CLOUD_COLOR, (cx+15, cy-10, 50, 25))
            pygame.draw.ellipse(screen, CLOUD_COLOR, (cx-10, cy+5, 45, 20))
        pygame.draw.circle(screen, (255, 240, 150), (680, 70), 40)
        grass_rect = pygame.Rect(0, 450, WIDTH, 150)
        pygame.draw.rect(screen, GRASS_GREEN, grass_rect)
        for x in range(0, WIDTH, 25):
            h = random.randint(5, 15)
            pygame.draw.polygon(screen, GRASS_DARK, [(x, 450), (x+10, 450-h), (x+20, 450)])
        for fx, fy in self.flowers:
            pygame.draw.circle(screen, FLOWER_PINK, (fx, fy), 6)
            pygame.draw.circle(screen, FLOWER_YELLOW, (fx-3, fy-2), 3)
            pygame.draw.circle(screen, FLOWER_WHITE, (fx+2, fy-1), 2)

    def draw_card(self, animal, x, y, w, h, alpha=255):
        glow = rarity_colors[animal["rarity"]]
        for i in range(3):
            rect = pygame.Rect(x - i*3, y - i*3, w + i*6, h + i*6)
            s = pygame.Surface((rect.w, rect.h), pygame.SRCALPHA)
            pygame.draw.rect(s, (*glow, 60 - i*15), s.get_rect(), border_radius=22)
            screen.blit(s, (rect.x, rect.y))
        card_surf = pygame.Surface((w, h), pygame.SRCALPHA)
        card_surf.fill((255, 255, 255, min(alpha, 240)))
        pygame.draw.rect(card_surf, glow, card_surf.get_rect(), 4, border_radius=20)
        draw_animal_head(card_surf, w//2, h//2 - 10, 45, animal)
        name_surf = font_med.render(animal["name"], True, BLACK)
        card_surf.blit(name_surf, (w//2 - name_surf.get_width()//2, h//2 + 40))
        rare_surf = font_small.render(rarity_names[animal["rarity"]], True, glow)
        card_surf.blit(rare_surf, (w//2 - rare_surf.get_width()//2, h//2 + 70))
        screen.blit(card_surf, (x, y))

    def draw_ui(self):
        panel = pygame.Surface((WIDTH, 60), pygame.SRCALPHA)
        panel.fill((255, 240, 250, 180))
        screen.blit(panel, (0, 0))
        title = font_title.render("🌸 Sweet Gacha 🌸", True, PINK_DARK)
        screen.blit(title, (WIDTH//2 - title.get_width()//2, 10))
        mouse = pygame.mouse.get_pos()
        btn_color = PINK if self.pull_btn.collidepoint(mouse) else PINK_LIGHT
        pygame.draw.rect(screen, btn_color, self.pull_btn, border_radius=20)
        pygame.draw.rect(screen, PINK_DARK, self.pull_btn, 3, border_radius=20)
        pull_txt = font_med.render("PULL", True, WHITE)
        screen.blit(pull_txt, (self.pull_btn.x+32, self.pull_btn.y+10))
        pygame.draw.rect(screen, PINK_LIGHT, self.album_btn, border_radius=12)
        pygame.draw.rect(screen, PINK_DARK, self.album_btn, 2, border_radius=12)
        album_txt = font_small.render("Album", True, PINK_DARK)
        screen.blit(album_txt, (self.album_btn.x+25, self.album_btn.y+8))

    def draw_album(self):
        screen.fill(CREAM)
        title = font_title.render("🌸 Collection 🌸", True, PINK_DARK)
        screen.blit(title, (WIDTH//2 - title.get_width()//2, 20))
        cols = 4
        cw, ch = 140, 200
        sx = (WIDTH - cols*(cw+20))//2
        sy = 80
        for i, animal in enumerate(animals):
            col, row = i % cols, i // cols
            x = sx + col*(cw+20)
            y = sy + row*(ch+15)
            if i in self.collected:
                self.draw_card(animal, x, y, cw, ch, 200)
            else:
                pygame.draw.rect(screen, (220,220,230), (x, y, cw, ch), border_radius=16)
                q = font_large.render("?", True, (180,180,190))
                screen.blit(q, (x + cw//2 - q.get_width()//2, y + ch//2 - q.get_height()//2))
        back_btn = pygame.Rect(30, 20, 80, 40)
        pygame.draw.rect(screen, PINK_LIGHT, back_btn, border_radius=12)
        pygame.draw.rect(screen, PINK_DARK, back_btn, 2, border_radius=12)
        screen.blit(font_small.render("Back", True, PINK_DARK), (back_btn.x+15, back_btn.y+8))
        return back_btn

    def draw(self):
        self.draw_background()
        self.machine.draw(screen)
        if self.state == "show_card" and self.card_animal:
            self.draw_card(self.card_animal, WIDTH//2-100, 150, 200, 280, self.card_alpha)
            if self.card_alpha > 200 and len(self.particles) < 50:
                for _ in range(3):
                    self.particles.append(Particle(WIDTH//2, 250, rarity_colors[self.card_animal["rarity"]]))
        for p in self.particles:
            p.draw(screen)
        if self.state != "album":
            self.draw_ui()
        else:
            back_btn = self.draw_album()
            return back_btn
        return None

# ========== 主循环 ==========
def main():
    game = SweetGacha()
    running = True
    while running:
        mouse = pygame.mouse.get_pos()
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                running = False
            elif event.type == pygame.MOUSEBUTTONDOWN and event.button == 1:
                if game.state == "idle" and game.pull_btn.collidepoint(mouse):
                    game.pull()
                elif game.state == "show_card":
                    game.state = "idle"
                    game.particles.clear()
                elif game.state == "album":
                    back = pygame.Rect(30,20,80,40)
                    if back.collidepoint(mouse):
                        game.state = "idle"
                if game.album_btn.collidepoint(mouse) and game.state in ("idle","show_card"):
                    game.state = "album"
            elif event.type == pygame.KEYDOWN:
                if event.key == pygame.K_SPACE and game.state == "idle":
                    game.pull()
                elif event.key == pygame.K_ESCAPE and game.state == "album":
                    game.state = "idle"
        game.update()
        game.draw()
        pygame.display.flip()
        clock.tick(60)
    pygame.quit()
    sys.exit()

if __name__ == "__main__":
    main()