import pygame
import sys
import random
import math

pygame.init()
WIDTH, HEIGHT = 500, 700
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("Fruit Merge - Fixed Merging")
clock = pygame.time.Clock()
FPS = 60

# ==================== COLORS ====================
WHITE      = (255, 255, 255)
BLACK      = (0, 0, 0)
BG_TOP     = (255, 210, 200)
BG_BOTTOM  = (255, 245, 235)
PANEL_BG   = (255, 255, 255, 180)

FRUITS = [
    {"name":"Cherry",     "r":15, "color":(220,20,60),   "dark":(170,0,30),   "score":1},
    {"name":"Strawberry", "r":22, "color":(255,50,80),   "dark":(200,20,50),   "score":2},
    {"name":"Grape",      "r":30, "color":(160,0,180),   "dark":(110,0,130),   "score":4},
    {"name":"Orange",     "r":38, "color":(255,140,0),   "dark":(200,100,0),   "score":8},
    {"name":"Apple",      "r":46, "color":(255,50,50),   "dark":(190,20,20),   "score":16},
    {"name":"Pear",       "r":54, "color":(200,220,0),   "dark":(160,180,0),   "score":32},
    {"name":"Peach",      "r":62, "color":(255,180,140), "dark":(220,140,100), "score":64},
    {"name":"Pineapple",  "r":70, "color":(200,180,0),   "dark":(160,140,0),   "score":128},
    {"name":"Watermelon", "r":80, "color":(0,180,0),     "dark":(0,130,0),     "score":256},
]
MAX_LEVEL = len(FRUITS) - 1

# ==================== PARTICLE ====================
class Particle:
    def __init__(self, x, y, color):
        self.x = x
        self.y = y
        self.vx = random.uniform(-4, 4)
        self.vy = random.uniform(-4, 4)
        self.life = 20
        self.color = color
        self.size = random.randint(3, 6)

    def update(self):
        self.x += self.vx
        self.y += self.vy
        self.life -= 1
        self.vy += 0.1
        return self.life > 0

    def draw(self, surface):
        alpha = int(255 * (self.life / 20))
        color = (*self.color, alpha) if len(self.color)==3 else self.color
        s = pygame.Surface((self.size*2, self.size*2), pygame.SRCALPHA)
        pygame.draw.circle(s, color, (self.size, self.size), self.size)
        surface.blit(s, (self.x - self.size, self.y - self.size))

# ==================== FRUIT CLASS ====================
class Fruit:
    def __init__(self, x, y, level):
        self.x = x
        self.y = y
        self.level = level
        info = FRUITS[level]
        self.radius = info["r"]
        self.color = info["color"]
        self.dark  = info["dark"]
        self.name  = info["name"]
        self.score = info["score"]
        self.vy = 0.0
        self.landed = False
        self.to_remove = False
        self.bob_offset = random.uniform(0, 2*math.pi)

    def update(self, fruits, particles):
        if self.landed:
            return

        # Strong gravity
        self.vy += 1.5
        new_y = self.y + self.vy

        # Bottom boundary
        if new_y + self.radius >= HEIGHT - 10:
            self.y = HEIGHT - 10 - self.radius
            self.vy = 0
            self.landed = True
            return

        # ★ 使用圆形碰撞检测（距离）
        collision = False
        for other in fruits:
            if other is self or not other.landed or other.to_remove:
                continue
            # 计算两个圆心距离
            dist = math.hypot(self.x - other.x, new_y - other.y)
            if dist < self.radius + other.radius:
                collision = True
                # 等级相同且可以合成
                if other.level == self.level and self.level < MAX_LEVEL:
                    # 合成在两者中间位置
                    new_x = (self.x + other.x) / 2
                    new_y_merge = (new_y + other.y) / 2
                    new_fruit = Fruit(new_x, new_y_merge, self.level + 1)
                    # 不直接落地，让它自然下落
                    fruits.append(new_fruit)
                    # 粒子特效
                    for _ in range(15):
                        particles.append(Particle(new_x, new_y_merge, self.color))
                        particles.append(Particle(new_x, new_y_merge, other.color))
                    self.to_remove = True
                    other.to_remove = True
                break

        if collision and not self.to_remove:
            # 停在碰撞水果的上方
            self.y = other.y - self.radius - other.radius  # 精确放置
            self.vy = 0
            self.landed = True
            return

        self.y = new_y

    def rect(self):
        return pygame.Rect(self.x - self.radius, self.y - self.radius,
                           self.radius*2, self.radius*2)

    def draw(self, surface, frame_count):
        y_offset = 0
        if self.landed:
            y_offset = math.sin(frame_count * 0.05 + self.bob_offset) * 2

        cx, cy = int(self.x), int(self.y + y_offset)
        r = self.radius

        pygame.draw.circle(surface, (0,0,0,50), (cx+2, cy+3), r)
        pygame.draw.circle(surface, self.color, (cx, cy), r)
        dark_rect = pygame.Rect(cx - r, cy, r*2, r)
        pygame.draw.ellipse(surface, self.dark, dark_rect)
        hl_r = r // 3
        pygame.draw.circle(surface, (255,255,255,180), (cx - hl_r, cy - hl_r), hl_r)
        pygame.draw.circle(surface, BLACK, (cx, cy), r, 2)

        font = pygame.font.Font(None, 20)
        text = font.render(self.name, True, WHITE)
        text_rect = text.get_rect(center=(cx, cy))
        surface.blit(text, text_rect)

        eye_y = cy - r//3
        pygame.draw.circle(surface, BLACK, (cx - r//3, eye_y), max(2, r//10))
        pygame.draw.circle(surface, BLACK, (cx + r//3, eye_y), max(2, r//10))
        mouth_rect = pygame.Rect(cx - r//4, cy + r//4, r//2, r//4)
        pygame.draw.arc(surface, BLACK, mouth_rect, 0, math.pi, 2)

# ==================== GAME CLASS ====================
class Game:
    def __init__(self):
        self.fruits = []
        self.particles = []
        self.next_fruit = random.randint(0, 3)
        self.score = 0
        self.game_over = False
        self.spawn_x = WIDTH // 2
        self.frame = 0
        self.font = pygame.font.Font(None, 36)
        self.small_font = pygame.font.Font(None, 24)

    def handle_events(self):
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit(); sys.exit()
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_SPACE and self.game_over:
                    self.__init__()
                elif event.key == pygame.K_ESCAPE:
                    pygame.quit(); sys.exit()

            if not self.game_over:
                if event.type == pygame.MOUSEMOTION:
                    self.spawn_x = max(30, min(event.pos[0], WIDTH - 30))
                if event.type == pygame.MOUSEBUTTONDOWN:
                    if event.button == 1:
                        new_fruit = Fruit(self.spawn_x, 30, self.next_fruit)
                        if not self.is_overlapping(new_fruit):
                            self.fruits.append(new_fruit)
                            self.score += FRUITS[self.next_fruit]["score"]
                            self.next_fruit = random.randint(0, 3)
                        if self.check_game_over():
                            self.game_over = True

    def is_overlapping(self, fruit):
        for other in self.fruits:
            dist = math.hypot(fruit.x - other.x, fruit.y - other.y)
            if dist < fruit.radius + other.radius:
                return True
        return False

    def check_game_over(self):
        for fruit in self.fruits:
            if fruit.landed and fruit.y - fruit.radius < 10:
                return True
        return False

    def update(self):
        if self.game_over:
            return
        for fruit in self.fruits:
            fruit.update(self.fruits, self.particles)
        self.fruits = [f for f in self.fruits if not f.to_remove]
        self.particles = [p for p in self.particles if p.update()]
        if self.check_game_over():
            self.game_over = True

    def draw_background(self):
        for y in range(HEIGHT):
            t = y / HEIGHT
            r = int(BG_TOP[0] + (BG_BOTTOM[0] - BG_TOP[0]) * t)
            g = int(BG_TOP[1] + (BG_BOTTOM[1] - BG_TOP[1]) * t)
            b = int(BG_TOP[2] + (BG_BOTTOM[2] - BG_TOP[2]) * t)
            pygame.draw.line(screen, (r, g, b), (0, y), (WIDTH, y))
        pygame.draw.line(screen, (255,150,150), (0, HEIGHT-10), (WIDTH, HEIGHT-10), 3)

    def draw_ui(self):
        panel = pygame.Surface((WIDTH, 80), pygame.SRCALPHA)
        panel.fill(PANEL_BG)
        screen.blit(panel, (0, 0))
        score_text = self.font.render(f"⭐ {self.score}", True, BLACK)
        screen.blit(score_text, (15, 15))
        next_text = self.small_font.render("Next:", True, BLACK)
        screen.blit(next_text, (WIDTH - 130, 10))
        preview = FRUITS[self.next_fruit]
        px, py = WIDTH - 60, 45
        pygame.draw.circle(screen, preview["color"], (px, py), preview["r"])
        pygame.draw.circle(screen, BLACK, (px, py), preview["r"], 2)
        name_s = self.small_font.render(preview["name"], True, BLACK)
        screen.blit(name_s, (WIDTH - 110, 55))

    def draw(self):
        self.draw_background()
        for fruit in self.fruits:
            fruit.draw(screen, self.frame)
        for p in self.particles:
            p.draw(screen)

        if not self.game_over:
            for y in range(30, HEIGHT-10, 8):
                if y % 16 == 0:
                    pygame.draw.circle(screen, (100,100,100,100), (self.spawn_x, y), 2)
            preview_info = FRUITS[self.next_fruit]
            preview = Fruit(self.spawn_x, 30, self.next_fruit)
            s = pygame.Surface((preview.radius*2, preview.radius*2), pygame.SRCALPHA)
            pygame.draw.circle(s, (*preview_info["color"], 150), (preview.radius, preview.radius), preview.radius)
            screen.blit(s, (preview.x - preview.radius, preview.y - preview.radius))

        self.draw_ui()

        if self.game_over:
            overlay = pygame.Surface((WIDTH, HEIGHT), pygame.SRCALPHA)
            overlay.fill((0,0,0,180))
            screen.blit(overlay, (0,0))
            go_text = self.font.render("GAME OVER", True, WHITE)
            screen.blit(go_text, (WIDTH//2 - 90, HEIGHT//2 - 40))
            restart = self.small_font.render("Press SPACE to restart", True, WHITE)
            screen.blit(restart, (WIDTH//2 - 100, HEIGHT//2 + 10))

        pygame.display.flip()
        self.frame += 1

    def run(self):
        while True:
            self.handle_events()
            self.update()
            self.draw()
            clock.tick(FPS)

if __name__ == "__main__":
    game = Game()
    game.run()