import pygame
import math
import random

# --- 红警风格配置 ---
WIDTH, HEIGHT = 900, 600
GRID = 40
FPS = 60

# 经典配色
BG_COLOR = (20, 30, 20)          # 战场草地
PATH_COLOR = (40, 50, 40)        # 压烂的土路
UI_BG = (30, 30, 30)             # 底部UI栏
ALLIED_BLUE = (0, 150, 255)      # 盟军蓝
SOVIET_RED = (200, 30, 30)       # 苏军红
PRISM_COLOR = (200, 100, 255)    # 光棱紫
TESLA_COLOR = (100, 200, 255)    # 磁暴蓝
ORE_COLOR = (255, 200, 0)        # 矿石黄
HP_GREEN = (0, 200, 0)
HP_RED = (200, 0, 0)

# 建筑/单位配置
BUILDINGS = {
    1: {"name": "Prism Tower", "cost": 100, "color": PRISM_COLOR, "range": 160, "dmg": 20, "cd": 40, "type": "prism"},
    2: {"name": "Tesla Coil", "cost": 150, "color": TESLA_COLOR, "range": 120, "dmg": 40, "cd": 60, "type": "tesla"}
}

# --- 核心类 ---

class Harvester(pygame.sprite.Sprite):
    """矿车：自动在路径上移动并产生资金"""
    def __init__(self, waypoints):
        super().__init__()
        self.image = pygame.Surface((30, 30), pygame.SRCALPHA)
        self.rect = self.image.get_rect()
        self.waypoints = waypoints
        self.wp_idx = 0
        self.speed = 1.5
        self.ore = 0
        self.max_ore = 50
        self.state = "mining"  # mining, returning
        self.timer = 0
        
        self.rect.center = (waypoints[0][0]*GRID+GRID//2, waypoints[0][1]*GRID+GRID//2)

    def update(self, gold_callback):
        # 简单状态机：挖矿 -> 回基地 -> 卸货 -> 挖矿
        if self.state == "mining":
            self.timer += 1
            if self.timer > 60:  # 挖2秒
                self.ore = min(self.ore + 10, self.max_ore)
                self.timer = 0
                if self.ore >= self.max_ore:
                    self.state = "returning"
                    self.wp_idx = len(self.waypoints) - 1  # 直接跳回起点逻辑简化
        elif self.state == "returning":
            # 简化：直接瞬移回起点或缓慢移动，这里用缓慢移动
            target = self.waypoints[0]
            tx, ty = target[0]*GRID+GRID//2, target[1]*GRID+GRID//2
            dx, dy = tx - self.rect.centerx, ty - self.rect.centery
            dist = math.hypot(dx, dy)
            if dist > 5:
                self.rect.centerx += dx/dist * self.speed * 2
                self.rect.centery += dy/dist * self.speed * 2
            else:
                gold_callback(self.ore)
                self.ore = 0
                self.state = "mining"
                self.rect.center = (self.waypoints[-1][0]*GRID+GRID//2, self.waypoints[-1][1]*GRID+GRID//2)

        self.draw_model()

    def draw_model(self):
        self.image.fill((0,0,0,0))
        # 车身
        pygame.draw.rect(self.image, ORE_COLOR, (5, 5, 20, 20))
        pygame.draw.rect(self.image, (150, 150, 150), (8, 8, 14, 14))
        # 矿石指示
        if self.ore > 0:
            h = int(10 * (self.ore / self.max_ore))
            pygame.draw.rect(self.image, ORE_COLOR, (10, 20-h, 10, h))

class EnemyTank(pygame.sprite.Sprite):
    def __init__(self, path):
        super().__init__()
        self.image = pygame.Surface((36, 36), pygame.SRCALPHA)
        self.rect = self.image.get_rect()
        self.path = path
        self.path_idx = 0
        self.speed = 1.2
        self.hp = 150
        self.max_hp = 150
        self.armor = 2  # 护甲减伤
        self.angle = 0
        self.rect.center = (path[0][0]*GRID+GRID//2, path[0][1]*GRID+GRID//2)

    def update(self):
        if self.path_idx < len(self.path) - 1:
            tx = self.path[self.path_idx+1][0]*GRID+GRID//2
            ty = self.path[self.path_idx+1][1]*GRID+GRID//2
            dx, dy = tx - self.rect.centerx, ty - self.rect.centery
            dist = math.hypot(dx, dy)
            self.angle = math.atan2(dy, dx)
            
            if dist > self.speed:
                self.rect.centerx += dx/dist * self.speed
                self.rect.centery += dy/dist * self.speed
            else:
                self.path_idx += 1
        self.draw_model()

    def take_damage(self, dmg):
        actual = max(1, dmg - self.armor)
        self.hp -= actual

    def draw_model(self):
        self.image.fill((0,0,0,0))
        center = (18, 18)
        # 炮塔旋转
        gun_end = (center[0] + 15*math.cos(self.angle), center[1] + 15*math.sin(self.angle))
        pygame.draw.line(self.image, SOVIET_RED, center, gun_end, 4)
        # 车身
        pygame.draw.circle(self.image, SOVIET_RED, center, 12)
        pygame.draw.circle(self.image, (100, 20, 20), center, 12, 2)
        # 血条
        ratio = self.hp / self.max_hp
        pygame.draw.rect(self.image, HP_RED, (6, 2, 24, 3))
        pygame.draw.rect(self.image, HP_GREEN, (6, 2, int(24*ratio), 3))

class DefenseTower(pygame.sprite.Sprite):
    def __init__(self, x, y, config):
        super().__init__()
        self.image = pygame.Surface((GRID, GRID), pygame.SRCALPHA)
        self.rect = self.image.get_rect()
        self.rect.center = (x*GRID+GRID//2, y*GRID+GRID//2)
        self.config = config
        self.range = config["range"]
        self.dmg = config["dmg"]
        self.cd = config["cd"]
        self.timer = 0
        self.angle = 0
        self.target = None
        self.beam_end = None  # 光棱/磁暴光束终点

    def update(self, enemies, bullets):
        if self.timer > 0: self.timer -= 1
        self.target = None
        self.beam_end = None

        # 索敌
        min_d = float('inf')
        for e in enemies:
            d = math.hypot(e.rect.centerx-self.rect.centerx, e.rect.centery-self.rect.centery)
            if d <= self.range and d < min_d:
                min_d = d
                self.target = e

        if self.target and self.timer <= 0:
            dx = self.target.rect.centerx - self.rect.centerx
            dy = self.target.rect.centery - self.rect.centery
            self.angle = math.atan2(dy, dx)
            self.target.take_damage(self.dmg)
            self.timer = self.cd
            self.beam_end = (self.target.rect.centerx, self.target.rect.centery)
            # 红警光束不需要子弹实体，直接画线
        self.draw_model()

    def draw_model(self):
        self.image.fill((0,0,0,0))
        c = (GRID//2, GRID//2)
        col = self.config["color"]
        
        # 底座
        pygame.draw.polygon(self.image, (100,100,100), [(10,30), (30,30), (35,20), (5,20)])
        # 炮塔
        pygame.draw.circle(self.image, col, c, 10)
        # 炮管
        end = (c[0]+18*math.cos(self.angle), c[1]+18*math.sin(self.angle))
        pygame.draw.line(self.image, (200,200,200), c, end, 3)

        # 绘制光束 (在屏幕层绘制更好，这里简化画在自身surface上会有裁剪问题，所以光束在主循环画)

# --- 主程序 ---
def main():
    pygame.init()
    screen = pygame.display.set_mode((WIDTH, HEIGHT))
    pygame.display.set_caption("Red Alert: Base Defense (Python)")
    clock = pygame.time.Clock()
    font = pygame.font.Font(None, 30)

    # 地图路径 (两条路)
    path_top = [(0, 2), (5, 2), (5, 5), (10, 5), (10, 7), (22, 7)]
    path_bot = [(0, 12), (5, 12), (5, 9), (10, 9), (10, 7), (22, 7)]
    harvest_path = [(22, 7), (18, 7), (18, 10), (22, 10)] # 矿车路线

    groups = {
        "enemies": pygame.sprite.Group(),
        "towers": pygame.sprite.Group(),
        "harvesters": pygame.sprite.Group()
    }

    gold = 300
    selected_build = 1
    spawn_timer = 0
    occupied = set()

    # 初始矿车
    groups["harvesters"].add(Harvester(harvest_path))

    running = True
    while running:
        dt = clock.tick(FPS)
        screen.fill(BG_COLOR)

        # 1. 事件
        for event in pygame.event.get():
            if event.type == pygame.QUIT: running = False
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_1: selected_build = 1
                if event.key == pygame.K_2: selected_build = 2
            if event.type == pygame.MOUSEBUTTONDOWN:
                mx, my = pygame.mouse.get_pos()
                if my > HEIGHT - 60: continue  # UI区域
                gx, gy = mx // GRID, my // GRID
                cfg = BUILDINGS[selected_build]
                if gold >= cfg["cost"] and (gx, gy) not in occupied:
                    groups["towers"].add(DefenseTower(gx, gy, cfg))
                    gold -= cfg["cost"]
                    occupied.add((gx, gy))

        # 2. 生成敌人
        spawn_timer += 1
        if spawn_timer > 120:
            path = path_top if random.random() > 0.5 else path_bot
            groups["enemies"].add(EnemyTank(path))
            spawn_timer = 0

        # 3. 更新
        def add_gold(amt): nonlocal gold; gold += amt
        groups["harvesters"].update(add_gold)
        groups["enemies"].update()
        groups["towers"].update(groups["enemies"], None)

        # 清理
        for e in groups["enemies"]:
            if e.hp <= 0: 
                gold += 15  # 击杀奖励
                e.kill()
            elif e.path_idx >= len(e.path) - 1:
                e.kill()  # 漏怪扣血逻辑可加

        # 4. 渲染
        # 画路径
        for path in [path_top, path_bot, harvest_path]:
            for p in path:
                pygame.draw.rect(screen, PATH_COLOR, (p[0]*GRID, p[1]*GRID, GRID, GRID))
        
        # 画光束 (红警精髓)
        for tower in groups["towers"]:
            if tower.beam_end:
                col = BUILDINGS[1]["color"] if tower.config["type"] == "prism" else BUILDINGS[2]["color"]
                pygame.draw.line(screen, col, tower.rect.center, tower.beam_end, 3)
                pygame.draw.line(screen, (255,255,255), tower.rect.center, tower.beam_end, 1) # 高光

        groups["harvesters"].draw(screen)
        groups["towers"].draw(screen)
        groups["enemies"].draw(screen)

        # UI 栏
        pygame.draw.rect(screen, UI_BG, (0, HEIGHT-60, WIDTH, 60))
        info = font.render(f"Funds: ${gold} | [1] Prism (${BUILDINGS[1]['cost']}) | [2] Tesla (${BUILDINGS[2]['cost']})", True, (255,255,255))
        screen.blit(info, (10, HEIGHT-45))
        sel = font.render(f"Selected: {BUILDINGS[selected_build]['name']}", True, BUILDINGS[selected_build]['color'])
        screen.blit(sel, (10, HEIGHT-20))

        pygame.display.flip()

    pygame.quit()

if __name__ == "__main__":
    main()