"""Nexo Snake — Python 3.10+. Instale: python -m pip install pygame
Execute: python snake.py | Setas/WASD: mover | Espaço: pausar | R: reiniciar.
A lógica independe de Pygame e tem testes automatizados no projeto Nexo.
"""
from dataclasses import dataclass, field
import random

@dataclass
class Snake:
    width: int = 24
    height: int = 18
    body: list = field(default_factory=lambda: [(5, 5), (4, 5), (3, 5)])
    direction: tuple = (1, 0)
    food: tuple | None = None
    score: int = 0
    over: bool = False
    won: bool = False

    def __post_init__(self):
        if self.food is None:
            self.spawn_food()

    def spawn_food(self):
        empty = [(x, y) for y in range(self.height) for x in range(self.width)
                 if (x, y) not in self.body]
        if not empty:
            self.food = None
            self.over = self.won = True
        else:
            self.food = random.choice(empty)

    def step(self, requested=None):
        if self.over:
            return
        if requested in ((1, 0), (-1, 0), (0, 1), (0, -1)):
            reverse = (-self.direction[0], -self.direction[1])
            if requested != reverse:
                self.direction = requested
        dx, dy = self.direction
        head = (self.body[0][0] + dx, self.body[0][1] + dy)
        grows = head == self.food
        occupied = self.body if grows else self.body[:-1]
        if not (0 <= head[0] < self.width and 0 <= head[1] < self.height) or head in occupied:
            self.over = True
            return
        self.body.insert(0, head)
        if grows:
            self.score += 1
            self.spawn_food()
        else:
            self.body.pop()

def main():
    try:
        import pygame
    except ImportError:
        print('Instale Pygame: python -m pip install pygame')
        return
    pygame.init()
    cell, top = 26, 70
    game = Snake()
    screen = pygame.display.set_mode((game.width * cell, game.height * cell + top))
    pygame.display.set_caption('Nexo • Snake em Python')
    font = pygame.font.Font(None, 26)
    clock = pygame.time.Clock()
    directions = {pygame.K_UP:(0,-1), pygame.K_w:(0,-1), pygame.K_DOWN:(0,1),
                  pygame.K_s:(0,1), pygame.K_LEFT:(-1,0), pygame.K_a:(-1,0),
                  pygame.K_RIGHT:(1,0), pygame.K_d:(1,0)}
    running, paused = True, False
    elapsed, requested = 0, None
    while running:
        elapsed += clock.tick(60)
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                running = False
            elif event.type == pygame.KEYDOWN:
                if event.key == pygame.K_ESCAPE:
                    running = False
                elif event.key == pygame.K_r:
                    game, paused, elapsed, requested = Snake(), False, 0, None
                elif event.key == pygame.K_SPACE:
                    paused = not paused
                    elapsed = 0
                elif event.key in directions and requested is None:
                    candidate = directions[event.key]
                    if candidate != (-game.direction[0], -game.direction[1]):
                        requested = candidate
        interval = max(65, 160 - game.score * 4)
        if not paused and not game.over and elapsed >= interval:
            game.step(requested)
            requested, elapsed = None, 0
        screen.fill((16, 21, 19))
        screen.blit(font.render(f'NEXO SNAKE  |  Pontos: {game.score}', True, (196, 245, 130)), (14, 12))
        screen.blit(font.render('Setas/WASD • Espaço: pausa • R: reinicia', True, (157, 175, 149)), (14, 40))
        for x, y in game.body:
            pygame.draw.rect(screen, (196, 245, 130), (x*cell+2, y*cell+top+2, cell-4, cell-4), border_radius=5)
        if game.food is not None:
            x, y = game.food
            pygame.draw.circle(screen, (237, 150, 109), (x*cell+cell//2, y*cell+top+cell//2), cell//3)
        if game.over or paused:
            text = ('Você venceu! R para reiniciar' if game.won else 'Fim de jogo! R para reiniciar') if game.over else 'Pausado — Espaço para continuar'
            box = pygame.Surface((screen.get_width(), 60))
            box.fill((35, 47, 36))
            box.blit(font.render(text, True, (240, 245, 236)), (18, 18))
            screen.blit(box, (0, screen.get_height()//2))
        pygame.display.flip()
    pygame.quit()

if __name__ == '__main__':
    main()
