import pygame
import math

BASE_TILE = 50


class Boss1(pygame.sprite.Sprite):
    """Simple horizontal-moving boss: 3x3 tiles, 100 HP, touch damage only."""

    def __init__(self, x, y, hp=100):  # CHANGED: default HP 100 per spec
        super().__init__()
        self.max_hp = hp
        self.hp = hp
        self.dead = False  # NEW: flag so world can check when boss died

        # Load base texture (boss1.png) once and keep as base (cross‑platform paths)
        img = None
        for p in (
            r"Textures/boss1.png",
            r"Textures\boss1.png",
            r"../Textures/boss1.png",
            r"..\Textures\boss1.png",
        ):
            try:
                img = pygame.image.load(p).convert_alpha()
                break
            except Exception:
                continue
        if img is None:
            img = pygame.Surface((BASE_TILE, BASE_TILE), pygame.SRCALPHA)
            img.fill((120, 120, 120))
        self._base_img = img

        # Start with some default size; will be rescaled on first draw/update
        self.image = img.copy()
        self.rect = self.image.get_rect(center=(x, y))
        # NEW: separate (smaller) hitbox, initialised to same rect for now;
        # real size is set in _ensure_scaled_size when we know tile_size.
        self.hit_rect = self.rect.copy()

        # Movement: horizontal only
        self.base_speed = 3.0      # faster horizontal movement (in BASE_TILE units)
        self.direction = 1         # 1: right, -1: left

        # Drawing cache
        self._draw_cache = {"scale": None, "image": None}
        self._last_tile_size = None

    def _ensure_scaled_size(self, world):
        """Scale boss to exactly 3x3 tiles using current world.tile_size."""
        tile_size = getattr(world, "tile_size", BASE_TILE)
        if self._last_tile_size == tile_size:
            return
        self._last_tile_size = tile_size

        w = tile_size * 5
        h = tile_size * 5
        try:
            self.image = pygame.transform.smoothscale(self._base_img, (w, h))
        except Exception:
            self.image = pygame.transform.scale(self._base_img, (w, h))
        # keep center while resizing (for draw rect)
        center = self.rect.center
        self.rect = self.image.get_rect(center=center)

        # NEW: build a smaller hitbox that is one tile smaller in width & height
        shrink_w = tile_size       # 1 tile less in width
        shrink_h = tile_size       # 1 tile less in height
        hit_w = max(tile_size, self.rect.width - shrink_w)
        hit_h = max(tile_size, self.rect.height - shrink_h)
        hit_x = self.rect.centerx - hit_w // 2
        hit_y = self.rect.centery - hit_h // 2
        self.hit_rect = pygame.Rect(hit_x, hit_y, hit_w, hit_h)

        # invalidate cached scaled image for drawing
        self._draw_cache["scale"] = None

    def _handle_player_collision(self, player):
        """Deal touch damage to player on collision."""
        # use smaller hit_rect for collisions
        if self.hit_rect.colliderect(player.rect):
            try:
                player.take_damage(1)
            except Exception:
                player.health = max(0, getattr(player, "health", 0) - 1)

    def _handle_player_projectiles(self, player_projectiles):
        """Take damage from player's projectiles (respect projectile.damage)."""
        for proj in list(player_projectiles):
            try:
                hit_rect = proj.rect
            except Exception:
                continue
            # use hit_rect instead of full rect
            if self.hit_rect.colliderect(hit_rect):
                dmg = getattr(proj, "damage", 1)
                self.hp = max(0, self.hp - max(0, int(dmg)))
                try:
                    proj.kill()
                except Exception:
                    pass
                if self.hp <= 0:
                    self.dead = True
                    self.kill()
                    return

    def update(self, player, player_projectiles, world):
        """Update movement and collisions.

        Signature matches Boss3 so RARL's generic enemy loop can call it.
        """
        # Ensure correct size vs tile_size
        self._ensure_scaled_size(world)

        tile_size = getattr(world, "tile_size", BASE_TILE)
        scale_factor = float(tile_size) / float(BASE_TILE)
        speed_px = max(0.5, self.base_speed * scale_factor)

        # Horizontal-only movement; bounce off world bounds
        dx = speed_px * self.direction
        self.rect.x += int(round(dx))

        # Clamp and flip direction on bounds
        if self.rect.left <= 0:
            self.rect.left = 0
            self.direction = 1
        elif self.rect.right >= world.pixel_width:
            self.rect.right = world.pixel_width
            self.direction = -1

        # keep hit_rect centered on visual rect after movement
        self.hit_rect.center = self.rect.center

        # Handle taking damage from player's bullets
        self._handle_player_projectiles(player_projectiles)

        # Handle collision damage to player
        self._handle_player_collision(player)

    def draw(self, screen, scale, off_x=0, off_y=0):
        """Draw boss and its HP bar."""
        # scale sprite for screen
        if self._draw_cache["scale"] != scale:
            self._draw_cache["scale"] = scale
            sw = max(1, int(round(self.image.get_width() * scale)))
            sh = max(1, int(round(self.image.get_height() * scale)))
            self._draw_cache["image"] = pygame.transform.smoothscale(self.image, (sw, sh))

        img = self._draw_cache["image"]
        sx = int(round(self.rect.x * scale)) + off_x
        sy = int(round(self.rect.y * scale)) + off_y
        screen.blit(img, (sx, sy))

        # HP bar similar to Boss3
        bw = max(60, img.get_width())
        bh = max(4, int(round(6 * scale)))
        bx = sx + img.get_width() // 2 - bw // 2
        by = sy - bh - max(2, int(round(6 * scale)))
        pygame.draw.rect(screen, (40, 40, 40), (bx, by, bw, bh))
        ratio = 0 if self.max_hp == 0 else self.hp / self.max_hp
        pygame.draw.rect(screen, (220, 40, 40), (bx, by, int(round(bw * ratio)), bh))
        pygame.draw.rect(screen, (0, 0, 0), (bx, by, bw, bh), max(1, int(round(2 * scale))))
