import pygame
import random
import sys

pygame.init()
SCREEN_WIDTH = 800
SCREEN_HEIGHT = 600
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
pygame.display.set_caption("Blind‑Box Simulator")
clock = pygame.time.Clock()
FPS = 60

# Font compatibility
try:
    font_big = pygame.font.SysFont("Arial", 45)
    font_mid = pygame.font.SysFont("Arial", 28)
    font_small = pygame.font.SysFont("Arial", 20)
except Exception:
    font_big = pygame.font.Font(pygame.font.get_default_font(), 45)
    font_mid = pygame.font.Font(pygame.font.get_default_font(), 28)
    font_small = pygame.font.Font(pygame.font.get_default_font(), 20)

# Advanced color palette
WHITE = (255, 255, 255)
BLACK = (8, 8, 12)
GRAY = (135, 135, 135)
GREEN_LIGHT = (52, 225, 95)
BLUE = (25, 125, 250)
PURPLE = (145, 35, 220)
ORANGE = (255, 115, 0)
RED = (225, 25, 25)
GOLD = (255, 220, 35)
BOX_RED = (186, 22, 22)
BG_TOP = (242, 234, 222)
BG_BOTTOM = (224, 212, 196)

# Six rarity tiers
rank_names = ["Common", "Uncommon", "Rare", "Epic", "Legendary", "Mythic"]
rank_colors = [GRAY, GREEN_LIGHT, BLUE, PURPLE, ORANGE, GOLD]

item_list = [
    {"rank": 0, "name": "Sticker Pack", "color": GRAY},
    {"rank": 0, "name": "Plastic Keychain", "color": GRAY},
    {"rank": 0, "name": "Small Badge", "color": GRAY},
    {"rank": 1, "name": "Glowing Pendant", "color": GREEN_LIGHT},
    {"rank": 1, "name": "Mini Figurine", "color": GREEN_LIGHT},
    {"rank": 2, "name": "Crystal Ornament", "color": BLUE},
    {"rank": 2, "name": "Anime Card", "color": BLUE},
    {"rank": 3, "name": "Silver Statue", "color": PURPLE},
    {"rank": 3, "name": "Limited‑Edition Pin", "color": PURPLE},
    {"rank": 4, "name": "Golden Trophy", "color": ORANGE},
    {"rank": 4, "name": "Rare Gemstone", "color": ORANGE},
    {"rank": 5, "name": "Divine Secret Item", "color": GOLD}
]

# Fixed particle class (always use RGBA four‑element list)
class Particle:
    def __init__(self, x, y, color):
        self.x = float(x)
        self.y = float(y)
        self.vx = random.uniform(-7.2, 7.2)
        self.vy = random.uniform(-7.2, 7.2)
        self.life = 75
        self.max_life = 75
        # Force RGBA format
        if len(color) == 3:
            self.color = list(color) + [255]
        else:
            self.color = list(color)
        self.size = random.randint(3, 8)

    def update(self):
        self.x += self.vx
        self.y += self.vy
        self.vy += 0.08
        self.life -= 1
        self.size *= 0.965
        alpha = int(255 * (self.life / self.max_life))
        self.color[3] = alpha

    def draw(self):
        trans_surf = pygame.Surface((16, 16), pygame.SRCALPHA)
        pygame.draw.circle(trans_surf, tuple(self.color), (8, 8), int(self.size))
        screen.blit(trans_surf, (int(self.x) - 8, int(self.y) - 8))


# Game settings
box_open_state = False
open_timer = 0
current_get = None
inventory = []
box_x, box_y = 400, 280
box_size = 122
btn_open = pygame.Rect(280, 450, 240, 70)
btn_storage = pygame.Rect(50, 450, 200, 70)
show_storage = False
particles = []


def draw_gradient_background():
    for y in range(SCREEN_HEIGHT):
        ratio = y / SCREEN_HEIGHT
        r = int(BG_TOP[0] * (1 - ratio) + BG_BOTTOM[0] * ratio)
        g = int(BG_TOP[1] * (1 - ratio) + BG_BOTTOM[1] * ratio)
        b = int(BG_TOP[2] * (1 - ratio) + BG_BOTTOM[2] * ratio)
        pygame.draw.line(screen, (r, g, b), (0, y), (SCREEN_WIDTH, y))


def get_random_item():
    roll = random.randint(1, 100)
    if roll <= 50:
        pool = [i for i in item_list if i["rank"] == 0]
    elif roll <= 75:
        pool = [i for i in item_list if i["rank"] == 1]
    elif roll <= 88:
        pool = [i for i in item_list if i["rank"] == 2]
    elif roll <= 95:
        pool = [i for i in item_list if i["rank"] == 3]
    elif roll <= 99:
        pool = [i for i in item_list if i["rank"] == 4]
    else:
        pool = [i for i in item_list if i["rank"] == 5]
    return random.choice(pool)


def spawn_open_effect(rank):
    spawn_x = box_x
    spawn_y = box_y
    particle_amounts = [15, 28, 45, 70, 100, 180]
    count = particle_amounts[rank]
    for _ in range(count):
        base_color = list(rank_colors[rank])
        particles.append(Particle(spawn_x, spawn_y, base_color))


def draw_shadow(rect, offset_x=4, offset_y=4):
    shadow_rect = pygame.Rect(rect.x + offset_x, rect.y + offset_y, rect.w, rect.h)
    pygame.draw.rect(screen, (40, 40, 40, 85), shadow_rect, 0, 14)


running = True
while running:
    draw_gradient_background()
    clock.tick(FPS)
    mx, my = pygame.mouse.get_pos()

    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
        if event.type == pygame.MOUSEBUTTONDOWN:
            if btn_open.collidepoint(mx, my) and not box_open_state:
                box_open_state = True
                open_timer = 0
                current_get = get_random_item()
                inventory.append(current_get)
                spawn_open_effect(current_get["rank"])
            if btn_storage.collidepoint(mx, my):
                show_storage = not show_storage

    if box_open_state:
        open_timer += 1
        if open_timer > 90:
            box_open_state = False

    # Update‑render particles
    for p in particles[:]:
        p.update()
        p.draw()
        if p.life <= 0:
            particles.remove(p)

    box_rect = pygame.Rect(box_x - box_size // 2, box_y - box_size // 2, box_size, box_size)
    draw_shadow(box_rect)

    if not box_open_state:
        pygame.draw.rect(screen, BOX_RED, box_rect, 0, 14)
        pygame.draw.rect(screen, BLACK, box_rect, 4, 14)
        text_box = font_mid.render("BAG", True, WHITE)
        screen.blit(text_box, (box_x - 22, box_y - 22))
    else:
        offset = min(open_timer * 1.3, box_size / 2)
        open_box_rect = pygame.Rect(box_x - box_size // 2,
                                        box_y - box_size // 2 + offset, box_size, box_size - offset)
        pygame.draw.rect(screen, BOX_RED, open_box_rect, 0, 10)
        if open_timer > 40:
            r = current_get["rank"]
            item_color = current_get["color"]
            # Glow‑effect for high‑rank items
            if r >= 2:
                for glow in range(3):
                    glow_radius = 42 + glow * 7
                    surf_glow = pygame.Surface((glow_radius * 2, glow_radius * 2), pygame.SRCALPHA)
                    pygame.draw.circle(surf_glow, (*item_color, 35), (glow_radius, glow_radius), glow_radius)
                    screen.blit(surf_glow, (box_x - glow_radius, box_y + 20 - glow_radius))
            pygame.draw.circle(screen, item_color, (box_x, box_y + 20), 38)
            name_surf = font_small.render(current_get["name"], True, WHITE)
            rank_surf = font_small.render(f"Rank:{rank_names[r]}", True, rank_colors[r])
            screen.blit(name_surf, (box_x - 50, box_y + 65))
            screen.blit(rank_surf, (box_x - 55, box_y - 90))

    # Draw buttons with shadow
    draw_shadow(btn_open)
    pygame.draw.rect(screen, GREEN_LIGHT, btn_open, 0, 14)
    screen.blit(font_mid.render("Open BAG", True, WHITE), (btn_open.x + 55, btn_open.y + 8))

    draw_shadow(btn_storage)
    pygame.draw.rect(screen, BLUE, btn_storage, 0, 14)
    screen.blit(font_mid.render("Collection", True, WHITE), (btn_storage.x + 30, btn_storage.y + 8))

    # Collection UI
    if show_storage:
        panel_rect = pygame.Rect(50, 80, 700, 340)
        draw_shadow(panel_rect)
        pygame.draw.rect(screen, WHITE, panel_rect, 0, 12)
        pygame.draw.rect(screen, GRAY, panel_rect, 3, 12)
        title = font_mid.render(f"Your Collection | Total:{len(inventory)}", True, BLACK)
        screen.blit(title, (70, 90))
        for index, goods in enumerate(inventory[-24:]):
            x = 70 + (index % 6) * 110
            y = 130 + (index // 6) * 80
            if goods["rank"] >= 2:
                s = pygame.Surface((52, 52), pygame.SRCALPHA)
                pygame.draw.circle(s, (*goods["color"], 30), (26, 26), 26)
                screen.blit(s, (x - 26, y - 26))
            pygame.draw.circle(screen, goods["color"], (x, y), 22)
            item_text = font_small.render(goods["name"], True, BLACK)
            screen.blit(item_text, (x - 45, y + 30))

    pygame.display.update()

pygame.quit()
sys.exit()