"""
Ski Simulator - Pygame
Features: skier control, obstacles, jumping, scoring, terrain
"""

import pygame
import random
import math
import sys
import os

# ==================== Init ====================
pygame.init()
pygame.mixer.init()

# ==================== Config ====================
SCREEN_WIDTH = 900
SCREEN_HEIGHT = 650
FPS = 60

# Colors
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
SKY_TOP = (100, 160, 220)
SKY_BOT = (170, 215, 245)
SNOW_WHITE = (245, 245, 250)
TREE_GREEN = (34, 139, 34)
TREE_DARK = (20, 110, 20)
ROCK_GRAY = (128, 128, 128)
FLAG_RED = (220, 20, 20)
FLAG_BLUE = (30, 144, 255)
GOLD = (255, 215, 0)
ORANGE = (255, 140, 0)
PURPLE = (147, 112, 219)
SKI_RED = (200, 30, 30)
SKI_BLUE = (30, 60, 180)
MOUNTAIN_FAR = (180, 190, 210)
MOUNTAIN_MID = (160, 175, 200)
MOUNTAIN_NEAR = (140, 160, 190)

# Physics
GRAVITY = 0.4
MAX_SPEED = 14
ACCELERATION = 0.08
FRICTION = 0.992
JUMP_POWER = -10

# ==================== Display ====================
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
pygame.display.set_caption("Ski Simulator v1.0")
clock = pygame.time.Clock()

# ==================== Fonts (Cross-platform safe) ====================
def get_font(size):
    """Try multiple font options for cross-platform compatibility."""
    font_names = [
        "Arial", "DejaVuSans", "LiberationSans", "Verdana",
        "Helvetica", "Tahoma", "Calibri", "segoeui"
    ]
    for name in font_names:
        try:
            f = pygame.font.SysFont(name, size)
            # Test render
            f.render("Test", True, WHITE)
            return f
        except:
            continue
    return pygame.font.Font(None, size)

font_tiny = get_font(16)
font_small = get_font(22)
font_mid = get_font(34)
font_large = get_font(52)
font_title = get_font(68)
font_huge = get_font(96)


# ==================== Particle System ====================
class Particle:
    def __init__(self, x, y, color, speed_x=0, speed_y=0, size=None, life=None):
        self.x = x
        self.y = y
        self.color = color
        self.speed_x = speed_x + random.uniform(-0.5, 0.5)
        self.speed_y = speed_y + random.uniform(0, 1)
        self.size = size or random.randint(2, 5)
        self.life = life or random.randint(20, 50)
        self.max_life = self.life
        self.alpha = 255

    def update(self):
        self.x += self.speed_x
        self.y += self.speed_y
        self.life -= 1
        self.alpha = int(255 * (self.life / self.max_life))
        self.size = max(1, self.size - 0.05)

    def draw(self, surface):
        if self.life > 0:
            s = pygame.Surface((self.size * 2, self.size * 2), pygame.SRCALPHA)
            pygame.draw.circle(s, (*self.color, self.alpha), (self.size, self.size), self.size)
            surface.blit(s, (int(self.x - self.size), int(self.y - self.size)))


# ==================== Background ====================
class Mountain:
    def __init__(self, y, color, speed_factor):
        self.y = y
        self.color = color
        self.speed_factor = speed_factor
        self.offset = 0
        self.peaks = []
        x = 0
        while x < SCREEN_WIDTH + 200:
            w = random.randint(60, 150)
            h = random.randint(40, 120)
            self.peaks.append((x, w, h))
            x += w * 0.6

    def update(self, camera_speed):
        self.offset = (self.offset + camera_speed * self.speed_factor) % 1000

    def draw(self, surface):
        points = [(0, SCREEN_HEIGHT)]
        for px, pw, ph in self.peaks:
            x = px - self.offset + 1000
            x = x % (SCREEN_WIDTH + 200) - 100
            points.append((x, self.y - ph))
            points.append((x + pw, self.y))
        points.append((SCREEN_WIDTH, SCREEN_HEIGHT))
        if len(points) > 2:
            pygame.draw.polygon(surface, self.color, points)
        # Snow caps
        for px, pw, ph in self.peaks:
            x = px - self.offset + 1000
            x = x % (SCREEN_WIDTH + 200) - 100
            cap_h = ph * 0.25
            cap_pts = [(x + pw * 0.3, self.y - ph + cap_h),
                       (x + pw * 0.5, self.y - ph),
                       (x + pw * 0.7, self.y - ph + cap_h)]
            pygame.draw.polygon(surface, (220, 225, 235), cap_pts)


class Cloud:
    def __init__(self):
        self.x = random.randint(-100, SCREEN_WIDTH)
        self.y = random.randint(20, 150)
        self.speed = random.uniform(0.2, 0.8)
        self.size = random.randint(20, 45)
        self.parts = [(random.randint(-20, 20), random.randint(-10, 10), random.randint(15, 30)) for _ in range(5)]

    def update(self, camera_speed):
        self.x -= self.speed + camera_speed * 0.1
        if self.x < -150:
            self.x = SCREEN_WIDTH + random.randint(50, 150)
            self.y = random.randint(20, 150)

    def draw(self, surface):
        for dx, dy, r in self.parts:
            pygame.draw.circle(surface, (255, 255, 255, 200), (int(self.x + dx), int(self.y + dy)), r)
        for dx, dy, r in self.parts:
            pygame.draw.circle(surface, (240, 240, 255), (int(self.x + dx), int(self.y + dy)), r - 3)


# ==================== Game Objects ====================
class Skier:
    def __init__(self, x, y):
        self.x = x
        self.y = y
        self.speed_x = 0
        self.speed_y = 0
        self.velocity_y = 0
        self.on_ground = True
        self.is_jumping = False
        self.jump_height = 0
        self.trail_particles = []
        self.snow_kick_timer = 0
        self.lean_angle = 0
        self.invincible = 0
        self.alive = True
        # Jacket color (randomized)
        self.jacket_colors = [(200, 40, 40), (30, 80, 200), (40, 160, 80), (200, 140, 20)]
        self.jacket_color = random.choice(self.jacket_colors)

    def update(self, keys, terrain_speed):
        # Horizontal movement
        if keys[pygame.K_LEFT] or keys[pygame.K_a]:
            self.speed_x -= ACCELERATION * 1.5
            self.lean_angle = max(-0.3, self.lean_angle - 0.02)
        elif keys[pygame.K_RIGHT] or keys[pygame.K_d]:
            self.speed_x += ACCELERATION * 1.5
            self.lean_angle = min(0.3, self.lean_angle + 0.02)
        else:
            self.speed_x *= FRICTION
            self.lean_angle *= 0.95

        # Accelerate / brake
        if keys[pygame.K_DOWN] or keys[pygame.K_s]:
            self.speed_y = min(self.speed_y + ACCELERATION * 2, MAX_SPEED)
        else:
            self.speed_y = min(self.speed_y + ACCELERATION * 0.5, MAX_SPEED)

        # Jump
        if (keys[pygame.K_SPACE] or keys[pygame.K_w] or keys[pygame.K_UP]) and self.on_ground:
            self.velocity_y = JUMP_POWER
            self.is_jumping = True
            self.on_ground = False

        # Air physics
        if not self.on_ground:
            self.velocity_y += GRAVITY * 0.6
            self.jump_height += self.velocity_y
            if self.jump_height >= 0:
                self.jump_height = 0
                self.on_ground = True
                self.is_jumping = False
                self.velocity_y = 0
                for _ in range(12):
                    self.trail_particles.append(Particle(
                        self.x + random.randint(-10, 10), self.y + 15, (200, 220, 255),
                        random.uniform(-2, 2), random.uniform(-1, 1),
                        random.randint(3, 7), random.randint(15, 30)))

        self.speed_x = max(-5, min(5, self.speed_x))
        self.x += self.speed_x
        self.y += terrain_speed * 0.3
        self.x = max(40, min(SCREEN_WIDTH - 40, self.x))

        # Snow kick
        self.snow_kick_timer += 1
        if self.on_ground and self.snow_kick_timer > 2 and abs(self.speed_x) > 1:
            self.snow_kick_timer = 0
            for _ in range(2):
                self.trail_particles.append(Particle(
                    self.x + random.randint(-8, 8) - self.speed_x * 2, self.y + 10,
                    (230, 240, 255), -self.speed_x * 0.5 + random.uniform(-1, 1),
                    random.uniform(-1, 0.5), random.randint(2, 4), random.randint(10, 20)))

        for p in self.trail_particles[:]:
            p.update()
            if p.life <= 0:
                self.trail_particles.remove(p)

        if self.invincible > 0:
            self.invincible -= 1

    def draw(self, surface):
        if not self.alive:
            return
        if self.invincible > 0 and self.invincible % 6 < 3:
            return

        px, py = int(self.x), int(self.y)
        lean = self.lean_angle * 15

        # Shadow
        pygame.draw.ellipse(surface, (180, 185, 195), (px - 14, py + 12, 28, 8))

        # Ski boards
        board_y = py + 8 - self.jump_height * 0.1
        pygame.draw.line(surface, SKI_BLUE if self.speed_y > 5 else SKI_RED,
                         (px - 16 + lean * 0.5, board_y), (px - 4 + lean * 0.5, board_y + 2), 4)
        pygame.draw.line(surface, SKI_BLUE if self.speed_y > 5 else SKI_RED,
                         (px + 4 + lean * 0.5, board_y), (px + 16 + lean * 0.5, board_y + 2), 4)
        pygame.draw.circle(surface, WHITE, (px - 18 + lean * 0.5, board_y - 1), 3)
        pygame.draw.circle(surface, WHITE, (px + 18 + lean * 0.5, board_y + 1), 3)

        # Legs
        pygame.draw.line(surface, (30, 30, 80), (px - 6, py - 2), (px - 10 + lean * 0.7, py + 6), 4)
        pygame.draw.line(surface, (30, 30, 80), (px + 6, py - 2), (px + 10 + lean * 0.7, py + 6), 4)

        # Body (jacket)
        pygame.draw.ellipse(surface, self.jacket_color, (px - 9, py - 16, 18, 18))
        pygame.draw.line(surface, (200, 200, 200), (px, py - 14), (px, py - 2), 2)

        # Head
        head_y = py - 22 - abs(self.jump_height) * 0.05
        pygame.draw.circle(surface, (255, 200, 160), (px + lean * 0.3, head_y), 8)
        # Goggles
        goggle_color = (20, 20, 40) if not self.is_jumping else (255, 100, 0)
        pygame.draw.arc(surface, goggle_color, (px - 6 + lean * 0.3, head_y - 3, 12, 8), 0, math.pi, 3)
        # Helmet
        pygame.draw.arc(surface, self.jacket_color, (px - 9 + lean * 0.3, head_y - 10, 18, 14), 0, math.pi, 5)
        pygame.draw.circle(surface, self.jacket_color, (px + lean * 0.3, head_y - 5), 9)

        # Arms
        arm_angle = math.sin(py * 0.1) * 0.3 + self.lean_angle
        lx = px - 10 + math.cos(arm_angle) * 8
        ly = py - 10 + math.sin(arm_angle) * 8
        pygame.draw.line(surface, self.jacket_color, (px - 7, py - 10), (int(lx), int(ly)), 4)
        rx = px + 10 - math.cos(arm_angle) * 8
        ry = py - 10 + math.sin(-arm_angle) * 8
        pygame.draw.line(surface, self.jacket_color, (px + 7, py - 10), (int(rx), int(ry)), 4)

        # Ski poles
        pygame.draw.line(surface, (180, 180, 180), (int(lx), int(ly)), (int(lx - 8), int(ly + 14)), 2)
        pygame.draw.line(surface, (180, 180, 180), (int(rx), int(ry)), (int(rx + 8), int(ry + 14)), 2)

        # Trail particles
        for p in self.trail_particles:
            p.draw(surface)

    def get_rect(self):
        return pygame.Rect(self.x - 12, self.y - 22, 24, 35)


class Tree:
    def __init__(self, x, y, size_type=None):
        self.x = x
        self.y = y
        self.size_type = size_type or random.choice(['small', 'medium', 'large'])
        sizes = {
            'small':  {'trunk': 3, 'foliage': [12, 18, 14], 'h': 35},
            'medium': {'trunk': 4, 'foliage': [18, 26, 20], 'h': 50},
            'large':  {'trunk': 5, 'foliage': [24, 34, 28], 'h': 68}
        }
        self.s = sizes[self.size_type]
        self.passed = False
        self.sway = random.uniform(0, math.pi * 2)

    def update(self, scroll_speed):
        self.y += scroll_speed
        self.sway += 0.05

    def draw(self, surface):
        sway = math.sin(self.sway) * 2
        pygame.draw.ellipse(surface, (195, 200, 210), (self.x - 12, self.y + self.s['h'] - 5, 24, 6))
        trunk_h = self.s['h'] * 0.3
        pygame.draw.rect(surface, (101, 67, 33),
                         (self.x - self.s['trunk'], self.y + self.s['h'] - trunk_h, self.s['trunk'] * 2, trunk_h))
        for i, r in enumerate(self.s['foliage']):
            layer_y = self.y + self.s['h'] - trunk_h - i * (r * 0.55)
            points = [(self.x + sway, layer_y - r * 0.8),
                      (self.x - r + sway, layer_y + r * 0.3),
                      (self.x + r + sway, layer_y + r * 0.3)]
            c = TREE_GREEN if i == 0 else (max(20, TREE_GREEN[0] - i * 15),
                                            max(80, TREE_GREEN[1] - i * 10),
                                            max(20, TREE_GREEN[2] - i * 5))
            pygame.draw.polygon(surface, c, points)
            if i == 0:
                pygame.draw.polygon(surface, (60, 180, 60),
                                    [(self.x + sway - r * 0.3, layer_y + r * 0.1),
                                     (self.x + sway, layer_y - r * 0.6),
                                     (self.x + sway + r * 0.2, layer_y + r * 0.1)])
        # Snow on branches
        for i in range(3):
            sn_y = self.y + self.s['h'] - trunk_h - i * (self.s['foliage'][0] * 0.55) - self.s['foliage'][0] * 0.7
            pygame.draw.circle(surface, WHITE, (int(self.x + sway + random.randint(-5, 5)), int(sn_y)), 3)

    def get_rect(self):
        r = self.s['foliage'][0] * 0.6
        return pygame.Rect(self.x - r, self.y + self.s['h'] * 0.4, r * 2, self.s['h'] * 0.5)

    def is_off_screen(self):
        return self.y > SCREEN_HEIGHT + 80


class Rock:
    def __init__(self, x, y):
        self.x = x
        self.y = y
        self.radius = random.randint(12, 25)
        self.passed = False

    def update(self, scroll_speed):
        self.y += scroll_speed

    def draw(self, surface):
        pygame.draw.ellipse(surface, (180, 180, 185), (self.x - self.radius, self.y + self.radius * 0.7, self.radius * 2, self.radius * 0.4))
        pygame.draw.circle(surface, ROCK_GRAY, (int(self.x), int(self.y)), self.radius)
        pygame.draw.circle(surface, (170, 170, 175), (int(self.x - self.radius * 0.3), int(self.y - self.radius * 0.3)), self.radius * 0.4)
        pygame.draw.line(surface, (100, 100, 100), (self.x - self.radius * 0.2, self.y - self.radius * 0.1),
                        (self.x + self.radius * 0.3, self.y + self.radius * 0.2), 2)
        pygame.draw.arc(surface, WHITE, (self.x - self.radius, self.y - self.radius * 0.8, self.radius * 2, self.radius), 0, math.pi * 0.6, 3)

    def get_rect(self):
        r = self.radius * 0.7
        return pygame.Rect(self.x - r, self.y - r * 0.5, r * 2, r * 1.5)

    def is_off_screen(self):
        return self.y > SCREEN_HEIGHT + 50


class Flag:
    def __init__(self, x, y, color=FLAG_RED):
        self.x = x
        self.y = y
        self.color = color
        self.passed = False
        self.wave = random.uniform(0, math.pi * 2)
        self.radius = 15

    def update(self, scroll_speed):
        self.y += scroll_speed
        self.wave += 0.15

    def draw(self, surface):
        pygame.draw.line(surface, (200, 200, 200), (self.x, self.y - 30), (self.x, self.y + 5), 3)
        wave = math.sin(self.wave) * 4
        points = [(self.x + 2, self.y - 28), (self.x + 18 + wave, self.y - 22),
                  (self.x + 14 + wave * 0.5, self.y - 14), (self.x + 20 + wave, self.y - 8),
                  (self.x + 2, self.y - 4)]
        pygame.draw.polygon(surface, self.color, points)
        pygame.draw.circle(surface, GOLD, (self.x, self.y - 32), 4)
        pygame.draw.circle(surface, (100, 100, 100), (self.x, self.y + 6), 5)

    def get_rect(self):
        return pygame.Rect(self.x - 12, self.y - 30, 24, 38)

    def is_off_screen(self):
        return self.y > SCREEN_HEIGHT + 40


class JumpRamp:
    def __init__(self, x, y):
        self.x = x
        self.y = y
        self.width = 60
        self.height = 25
        self.passed = False

    def update(self, scroll_speed):
        self.y += scroll_speed

    def draw(self, surface):
        points = [(self.x - self.width // 2, self.y + self.height),
                  (self.x + self.width // 2, self.y + self.height),
                  (self.x + self.width // 2 - 10, self.y - self.height * 0.3),
                  (self.x - self.width // 2 + 5, self.y - self.height * 0.5)]
        pygame.draw.polygon(surface, (200, 200, 220), points)
        pygame.draw.polygon(surface, (160, 160, 180), points, 2)
        for i in range(3):
            ax = self.x - 15 + i * 15
            ay = self.y + 5 - i * 5
            pygame.draw.polygon(surface, FLAG_RED,
                                [(ax, ay), (ax + 8, ay + 5), (ax, ay + 10), (ax - 2, ay + 5)])

    def get_rect(self):
        return pygame.Rect(self.x - self.width // 2, self.y - 15, self.width, self.height + 15)

    def is_off_screen(self):
        return self.y > SCREEN_HEIGHT + 40

    def activate(self, skier):
        if not self.passed:
            self.passed = True
            skier.velocity_y = JUMP_POWER * 1.8
            skier.is_jumping = True
            skier.on_ground = False
            skier.jump_height = -5
            skier.speed_y = min(skier.speed_y + 3, MAX_SPEED + 3)
            return True
        return False


# ==================== Snow Ground ====================
class SnowGround:
    def __init__(self):
        self.offset = 0
        self.snowflakes = []
        for _ in range(80):
            self.snowflakes.append({
                'x': random.randint(0, SCREEN_WIDTH),
                'y': random.randint(0, SCREEN_HEIGHT),
                'speed': random.uniform(0.5, 2.5),
                'size': random.randint(1, 4),
                'wobble': random.uniform(0, math.pi * 2)
            })
        self.ground_lines = []
        for _ in range(30):
            self.ground_lines.append({
                'x': random.randint(0, SCREEN_WIDTH),
                'y': random.randint(SCREEN_HEIGHT // 2, SCREEN_HEIGHT),
                'length': random.randint(20, 80),
            })

    def update(self, camera_speed):
        self.offset += camera_speed * 0.5
        for sf in self.snowflakes:
            sf['y'] += sf['speed'] + camera_speed * 0.3
            sf['wobble'] += 0.1
            sf['x'] += math.sin(sf['wobble']) * 0.5
            if sf['y'] > SCREEN_HEIGHT:
                sf['y'] = random.randint(-50, -10)
                sf['x'] = random.randint(0, SCREEN_WIDTH)

    def draw(self, surface, camera_speed):
        # Sky gradient
        for y in range(0, SCREEN_HEIGHT // 2):
            ratio = y / (SCREEN_HEIGHT // 2)
            r = int(SKY_TOP[0] + (SKY_BOT[0] - SKY_TOP[0]) * ratio)
            g = int(SKY_TOP[1] + (SKY_BOT[1] - SKY_TOP[1]) * ratio)
            b = int(SKY_TOP[2] + (SKY_BOT[2] - SKY_TOP[2]) * ratio)
            pygame.draw.line(surface, (r, g, b), (0, y), (SCREEN_WIDTH, y))

        # Snow ground
        gs = SCREEN_HEIGHT // 2 + int(math.sin(self.offset * 0.01) * 10)
        for y in range(gs, SCREEN_HEIGHT):
            ratio = (y - gs) / (SCREEN_HEIGHT - gs)
            r = int(245 - ratio * 10)
            g = int(248 - ratio * 8)
            b = int(255 - ratio * 5)
            pygame.draw.line(surface, (r, g, b), (0, y), (SCREEN_WIDTH, y))

        # Ground texture lines
        for gl in self.ground_lines:
            y_pos = gl['y'] + (self.offset * 0.3) % 100 - 50
            if y_pos > gs:
                sx = int(gl['x'] - self.offset * 0.8 % 200)
                if sx < 0:
                    sx += 200
                pygame.draw.line(surface, (220, 228, 240),
                                 (sx % SCREEN_WIDTH, int(y_pos)),
                                 ((sx + gl['length']) % SCREEN_WIDTH, int(y_pos + 2)), 1)

        # Snowflakes
        for sf in self.snowflakes:
            a = min(255, int(180 + math.sin(sf['wobble']) * 60))
            s = pygame.Surface((sf['size'] * 2, sf['size'] * 2), pygame.SRCALPHA)
            pygame.draw.circle(s, (255, 255, 255, a), (sf['size'], sf['size']), sf['size'])
            surface.blit(s, (int(sf['x'] - sf['size']), int(sf['y'] - sf['size'])))


# ==================== Game Manager ====================
class GameManager:
    def __init__(self):
        self.reset_game()

    def reset_game(self):
        self.skier = Skier(SCREEN_WIDTH // 2, SCREEN_HEIGHT // 2 + 50)
        self.snow_ground = SnowGround()
        self.mountains = [
            Mountain(SCREEN_HEIGHT // 2 - 20, MOUNTAIN_FAR, 0.1),
            Mountain(SCREEN_HEIGHT // 2 - 40, MOUNTAIN_MID, 0.2),
            Mountain(SCREEN_HEIGHT // 2 - 60, MOUNTAIN_NEAR, 0.35),
        ]
        self.clouds = [Cloud() for _ in range(5)]
        self.trees = []
        self.rocks = []
        self.flags = []
        self.ramps = []
        self.particles = []

        self.score = 0
        self.distance = 0
        self.combo = 0
        self.max_combo = 0
        self.game_state = "playing"
        self.scroll_speed = 4
        self.base_speed = 4
        self.time_alive = 0
        self.hint_alpha = 255

        for i in range(8):
            self.spawn_object(i * 100 + 200)

    def spawn_object(self, y=None):
        if y is None:
            y = -random.randint(50, 150)
        obj_type = random.choices(
            ['tree', 'tree', 'rock', 'flag', 'ramp', 'tree'],
            weights=[35, 25, 20, 12, 8, 10], k=1)[0]
        margin = 60
        x = random.randint(margin, SCREEN_WIDTH - margin)
        for existing in self.trees + self.rocks + self.flags + self.ramps:
            if abs(existing.y - y) < 60 and abs(existing.x - x) < 50:
                x = random.randint(margin, SCREEN_WIDTH - margin)
        if obj_type == 'tree':
            self.trees.append(Tree(x, y))
        elif obj_type == 'rock':
            self.rocks.append(Rock(x, y))
        elif obj_type == 'flag':
            c = random.choice([FLAG_RED, FLAG_BLUE, GOLD, PURPLE])
            self.flags.append(Flag(x, y, c))
        elif obj_type == 'ramp':
            self.ramps.append(JumpRamp(x, y))

    def update(self):
        if self.game_state != "playing":
            return
        self.time_alive += 1

        speed_increase = self.time_alive * 0.0001
        self.scroll_speed = self.base_speed + speed_increase + self.skier.speed_y * 0.3
        self.scroll_speed = min(self.scroll_speed, 12)

        keys = pygame.key.get_pressed()
        self.skier.update(keys, self.scroll_speed)

        self.snow_ground.update(self.scroll_speed)
        for m in self.mountains:
            m.update(self.scroll_speed)
        for c in self.clouds:
            c.update(self.scroll_speed)

        all_objects = self.trees + self.rocks + self.flags + self.ramps
        for obj in all_objects:
            obj.update(self.scroll_speed)

        self.trees = [t for t in self.trees if not t.is_off_screen()]
        self.rocks = [r for r in self.rocks if not r.is_off_screen()]
        self.flags = [f for f in self.flags if not f.is_off_screen()]
        self.ramps = [r for r in self.ramps if not r.is_off_screen()]

        min_y = min([obj.y for obj in all_objects] + [SCREEN_HEIGHT])
        while min_y > -200:
            self.spawn_object(min_y - random.randint(80, 150))
            min_y -= random.randint(80, 150)

        self.check_collisions()

        self.distance += self.scroll_speed * 0.1
        self.score += self.scroll_speed * 0.05

        for p in self.particles[:]:
            p.update()
            if p.life <= 0:
                self.particles.remove(p)

        # Fade hint
        self.hint_alpha = max(0, self.hint_alpha - 2)

    def check_collisions(self):
        skier_rect = self.skier.get_rect()

        for flag in self.flags:
            if not flag.passed and skier_rect.colliderect(flag.get_rect()):
                flag.passed = True
                self.combo += 1
                self.max_combo = max(self.max_combo, self.combo)
                self.score += 50 * self.combo
                for _ in range(8):
                    self.particles.append(Particle(
                        flag.x, flag.y - 20, flag.color,
                        random.uniform(-2, 2), random.uniform(-3, -1),
                        random.randint(3, 6), random.randint(20, 40)))

        for ramp in self.ramps:
            if skier_rect.colliderect(ramp.get_rect()):
                if ramp.activate(self.skier):
                    for _ in range(15):
                        self.particles.append(Particle(
                            ramp.x + random.randint(-20, 20), ramp.y, (255, 200, 50),
                            random.uniform(-3, 3), random.uniform(-2, 0),
                            random.randint(3, 7), random.randint(15, 30)))

        if self.skier.invincible > 0:
            return

        for tree in self.trees:
            if skier_rect.colliderect(tree.get_rect()):
                self.crash_effect(tree.x, tree.y)
                self.game_over()
                return

        for rock in self.rocks:
            if skier_rect.colliderect(rock.get_rect()):
                self.crash_effect(rock.x, rock.y)
                self.game_over()
                return

    def crash_effect(self, x, y):
        for _ in range(30):
            self.particles.append(Particle(
                x + random.randint(-15, 15), y + random.randint(-10, 10),
                random.choice([(255, 50, 50), (255, 200, 50), (200, 200, 255)]),
                random.uniform(-5, 5), random.uniform(-5, 2),
                random.randint(3, 8), random.randint(20, 50)))

    def game_over(self):
        self.game_state = "game_over"
        self.skier.alive = False
        for _ in range(50):
            self.particles.append(Particle(
                self.skier.x, self.skier.y,
                random.choice([(255, 0, 0), (255, 100, 0), (255, 255, 0), (100, 100, 100)]),
                random.uniform(-8, 8), random.uniform(-8, 4),
                random.randint(4, 10), random.randint(30, 60)))

    def draw(self, surface):
        self.snow_ground.draw(surface, self.scroll_speed)
        for m in self.mountains:
            m.draw(surface)
        for c in self.clouds:
            c.draw(surface)

        all_objs = [(o, o.y) for o in self.trees + self.rocks + self.flags + self.ramps]
        all_objs.sort(key=lambda x: x[1])
        for obj, _ in all_objs:
            obj.draw(surface)

        self.skier.draw(surface)
        for p in self.particles:
            p.draw(surface)

        self.draw_ui(surface)

        if self.game_state == "game_over":
            self.draw_game_over(surface)
        if self.game_state == "paused":
            self.draw_paused(surface)

    def draw_ui(self, surface):
        # Top bar
        bar = pygame.Surface((SCREEN_WIDTH, 40), pygame.SRCALPHA)
        bar.fill((0, 0, 0, 100))
        surface.blit(bar, (0, 0))

        # Score
        txt = font_mid.render(f"Score: {int(self.score)}", True, WHITE)
        surface.blit(txt, (15, 8))

        # Distance
        txt = font_small.render(f"Dist: {int(self.distance)}m", True, (200, 220, 255))
        surface.blit(txt, (230, 14))

        # Speed
        spd = int(self.scroll_speed * 8)
        sc = WHITE if spd < 60 else (255, 200, 50) if spd < 80 else (255, 50, 50)
        txt = font_small.render(f"Speed: {spd} km/h", True, sc)
        surface.blit(txt, (360, 14))

        # Combo
        if self.combo > 1:
            cc = GOLD if self.combo < 5 else (255, 100, 50) if self.combo < 10 else (255, 50, 50)
            txt = font_mid.render(f"Combo x{self.combo}!", True, cc)
            scale = 1.0 + math.sin(self.time_alive * 0.3) * 0.15
            sc2 = pygame.transform.scale(txt, (int(txt.get_width() * scale), int(txt.get_height() * scale)))
            surface.blit(sc2, (SCREEN_WIDTH - sc2.get_width() - 20, 5))

        if self.max_combo >= 5:
            txt = font_small.render(f"Best Combo: x{self.max_combo}", True, GOLD)
            surface.blit(txt, (SCREEN_WIDTH // 2 - 60, 14))

        # Jump meter
        if not self.skier.on_ground:
            jh = abs(self.skier.jump_height)
            bw, bh = 80, 6
            bx, by = self.skier.x - bw // 2, self.skier.y - 40
            pygame.draw.rect(surface, (50, 50, 50), (bx, by, bw, bh), border_radius=3)
            fw = min(bw, int(jh * 3))
            pygame.draw.rect(surface, (100, 200, 255), (bx, by, fw, bh), border_radius=3)

        # Hint text
        if self.hint_alpha > 0:
            hint_surf = pygame.Surface((520, 50), pygame.SRCALPHA)
            ht = font_small.render("Arrows/AD: Steer | S/Down: Boost | Space/W: Jump", True, WHITE)
            hint_surf.blit(ht, (260 - ht.get_width() // 2, 15))
            hint_surf.set_alpha(self.hint_alpha)
            surface.blit(hint_surf, (SCREEN_WIDTH // 2 - 260, SCREEN_HEIGHT - 80))

    def draw_game_over(self, surface):
        overlay = pygame.Surface((SCREEN_WIDTH, SCREEN_HEIGHT), pygame.SRCALPHA)
        overlay.fill((0, 0, 0, 170))
        surface.blit(overlay, (0, 0))

        txt = font_huge.render("GAME OVER", True, (255, 50, 50))
        surface.blit(txt, (SCREEN_WIDTH // 2 - txt.get_width() // 2, 110))

        stats = [
            f"Final Score: {int(self.score)}",
            f"Distance: {int(self.distance)}m",
            f"Max Combo: x{self.max_combo}",
            f"Survived: {self.time_alive // FPS}s",
        ]
        for i, s in enumerate(stats):
            c = GOLD if i == 2 and self.max_combo >= 5 else WHITE
            t = font_mid.render(s, True, c)
            surface.blit(t, (SCREEN_WIDTH // 2 - t.get_width() // 2, 240 + i * 48))

        if self.score > 500:
            t = font_mid.render("Awesome Run!", True, GOLD)
            surface.blit(t, (SCREEN_WIDTH // 2 - t.get_width() // 2, 190))

        if math.sin(self.time_alive * 0.15) > 0:
            t = font_mid.render("Press R to Restart | Q to Quit", True, (200, 255, 200))
            surface.blit(t, (SCREEN_WIDTH // 2 - t.get_width() // 2, 470))

    def draw_paused(self, surface):
        overlay = pygame.Surface((SCREEN_WIDTH, SCREEN_HEIGHT), pygame.SRCALPHA)
        overlay.fill((0, 0, 0, 130))
        surface.blit(overlay, (0, 0))
        txt = font_title.render("PAUSED", True, WHITE)
        surface.blit(txt, (SCREEN_WIDTH // 2 - txt.get_width() // 2, SCREEN_HEIGHT // 2 - 50))
        t2 = font_mid.render("Press P to Resume | Q to Quit", True, (200, 220, 255))
        surface.blit(t2, (SCREEN_WIDTH // 2 - t2.get_width() // 2, SCREEN_HEIGHT // 2 + 30))


# ==================== Menus ====================
def draw_main_menu(surface, selected):
    for y in range(SCREEN_HEIGHT):
        r = int(10 + (y / SCREEN_HEIGHT) * 30)
        g = int(10 + (y / SCREEN_HEIGHT) * 50)
        b = int(40 + (y / SCREEN_HEIGHT) * 80)
        pygame.draw.line(surface, (r, g, b), (0, y), (SCREEN_WIDTH, y))

    txt = font_title.render("SKI SIMULATOR", True, WHITE)
    surface.blit(txt, (SCREEN_WIDTH // 2 - txt.get_width() // 2, 100))

    txt2 = font_small.render("A Pygame Skiing Adventure", True, (180, 200, 255))
    surface.blit(txt2, (SCREEN_WIDTH // 2 - txt2.get_width() // 2, 175))

    options = ["Start Game", "How to Play", "Quit"]
    for i, opt in enumerate(options):
        c = GOLD if i == selected else WHITE
        t = font_large.render(opt, True, c)
        yp = 310 + i * 80
        xp = SCREEN_WIDTH // 2 - t.get_width() // 2
        if i == selected:
            pygame.draw.polygon(surface, GOLD, [(xp - 35, yp + 15), (xp - 20, yp + 25), (xp - 35, yp + 35)])
        surface.blit(t, (xp, yp))

    # Decorative skier silhouette
    sx = SCREEN_WIDTH // 2
    pygame.draw.line(surface, WHITE, (sx - 30, SCREEN_HEIGHT - 60), (sx + 30, SCREEN_HEIGHT - 40), 3)
    pygame.draw.circle(surface, WHITE, (sx - 5, SCREEN_HEIGHT - 80), 10)
    pygame.draw.line(surface, WHITE, (sx, SCREEN_HEIGHT - 70), (sx, SCREEN_HEIGHT - 50), 4)


def draw_help_screen(surface):
    overlay = pygame.Surface((SCREEN_WIDTH, SCREEN_HEIGHT), pygame.SRCALPHA)
    overlay.fill((0, 0, 30, 220))
    surface.blit(overlay, (0, 0))

    txt = font_large.render("How to Play", True, GOLD)
    surface.blit(txt, (SCREEN_WIDTH // 2 - txt.get_width() // 2, 50))

    instructions = [
        ("Arrows Left/Right  or  A/D", "Steer left / right"),
        ("Arrow Down  or  S", "Boost speed"),
        ("Space  or  W  or  Arrow Up", "Jump"),
        ("P", "Pause game"),
        ("R", "Restart after crash"),
        ("Q", "Quit to menu"),
        ("", ""),
        ("* Pass through flags to score", "Combo multiplies points!"),
        ("* Hit ramps for super jumps", "Jump + ramp = max air"),
        ("* Avoid trees and rocks!", "Crash = Game Over"),
    ]

    for i, (key, desc) in enumerate(instructions):
        kt = font_small.render(key, True, (255, 255, 100))
        dt = font_small.render(desc, True, WHITE)
        surface.blit(kt, (SCREEN_WIDTH // 2 - 210, 140 + i * 40))
        surface.blit(dt, (SCREEN_WIDTH // 2 + 30, 140 + i * 40))

    t2 = font_mid.render("Press any key to return", True, (150, 200, 255))
    surface.blit(t2, (SCREEN_WIDTH // 2 - t2.get_width() // 2, SCREEN_HEIGHT - 80))


# ==================== Main Loop ====================
def main():
    game = GameManager()
    menu_state = "main"  # main, help, playing
    selected_menu = 0

    running = True
    while running:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                running = False

            elif event.type == pygame.KEYDOWN:
                if menu_state == "main":
                    if event.key in (pygame.K_UP, pygame.K_w):
                        selected_menu = (selected_menu - 1) % 3
                    elif event.key in (pygame.K_DOWN, pygame.K_s):
                        selected_menu = (selected_menu + 1) % 3
                    elif event.key in (pygame.K_RETURN, pygame.K_SPACE):
                        if selected_menu == 0:
                            menu_state = "playing"
                            game.reset_game()
                        elif selected_menu == 1:
                            menu_state = "help"
                        elif selected_menu == 2:
                            running = False
                    elif event.key == pygame.K_ESCAPE:
                        running = False

                elif menu_state == "help":
                    menu_state = "main"

                elif menu_state == "playing":
                    if event.key == pygame.K_p:
                        if game.game_state == "playing":
                            game.game_state = "paused"
                        elif game.game_state == "paused":
                            game.game_state = "playing"
                    elif event.key == pygame.K_r and game.game_state == "game_over":
                        game.reset_game()
                    elif event.key == pygame.K_q:
                        if game.game_state in ("game_over", "paused"):
                            menu_state = "main"

        if menu_state == "playing":
            game.update()
            game.draw(screen)
        elif menu_state == "main":
            draw_main_menu(screen, selected_menu)
        elif menu_state == "help":
            draw_help_screen(screen)

        pygame.display.flip()
        clock.tick(FPS)

    pygame.quit()
    sys.exit()


if __name__ == "__main__":
    main()
