import os
from client.resource_path import get_asset_path, get_resource_path
import pygame


def load_spritesheet(path, rows=None, cols=None, frame_width=64, frame_height=64, scale=2.8):
    """Load a spritesheet, slice it into frames safely."""
    # Resolve the path for bundled executable
    resolved_path = get_resource_path(path)
    
    try:
        sheet = pygame.image.load(resolved_path).convert_alpha()
    except (pygame.error, FileNotFoundError) as e:
        print(f"Missing sprite: {path} - {e}")
        scaled_width, scaled_height = int(frame_width * scale), int(frame_height * scale)
        if rows is None: rows = 1
        if cols is None: cols = 1
        return [[pygame.Surface((scaled_width, scaled_height), pygame.SRCALPHA) for _ in range(cols)] for _ in range(rows)]

    sheet_width, sheet_height = sheet.get_size()

    # If the caller provided both rows and cols, compute frame sizes from the sheet dimensions.
    # This makes it safe to call load_spritesheet(rows=4, cols=2) for a 256x512 sheet (128x128 frames).
    if rows is not None and cols is not None:
        # integer division to avoid fractional pixel sizes
        frame_width = max(1, sheet_width // cols)
        frame_height = max(1, sheet_height // rows)
    else:
        if cols is None:
            cols = sheet_width // frame_width
        if rows is None:
            rows = sheet_height // frame_height

    frames = []
    for row in range(rows):
        row_frames = []
        for col in range(cols):
            rect = pygame.Rect(col * frame_width, row * frame_height, frame_width, frame_height)
            rect = rect.clip(sheet.get_rect())  # prevent subsurface errors
            frame = sheet.subsurface(rect)
            # ensure integer sizes for scale
            scaled_frame = pygame.transform.scale(frame, (int(frame_width * scale), int(frame_height * scale)))
            row_frames.append(scaled_frame)
        frames.append(row_frames)
    return frames


def load_hair_color_sprites(hair_style, action, hair_color, rows=None, cols=None):
    """Load hair spritesheets from color-specific folders if available."""
    base_path = f"client/assets/images/characters/Hair/{hair_style}"
    default_path = f"{base_path}/{action.capitalize()}.png"  # default hair sprite
    color_path = f"{base_path}/{action}/{hair_color}.png"    # colored hair sprite

    # Try loading colored version first, then fallback to default
    if hair_color:
        try:
            resolved_path = get_resource_path(color_path)
            pygame.image.load(resolved_path)  # Test if it exists
            return load_spritesheet(color_path, rows=rows, cols=cols)
        except (pygame.error, FileNotFoundError):
            pass  # Fall through to default
    
    return load_spritesheet(default_path, rows=rows, cols=cols)


def load_player_animations(player):
    """Load all layer animations for a given player."""
    gender = player.gender
    hair_style = player.hair_style
    hair_color = getattr(player, 'hair_color', None)

    animations = {
        "walk": {
            "body": load_spritesheet(f"client/assets/images/characters/Body/{gender}/Walk.png"),
            "hair": load_hair_color_sprites(hair_style, "walk", hair_color),
            "head": load_spritesheet(f"client/assets/images/characters/Head/{gender}/Walk.png"),
            "torso": load_spritesheet(f"client/assets/images/characters/Clothing/{gender}/Torso/Shirt 04 - T-shirt/Walk.png"),
            "legs": load_spritesheet(f"client/assets/images/characters/Clothing/{gender}/Legs/Pants 03 - Pants/Walk.png"),
            "feet": load_spritesheet(f"client/assets/images/characters/Clothing/{gender}/Feet/Shoes 01 - Shoes/Walk.png"),
        },
        "idle": {
            "body": load_spritesheet(f"client/assets/images/characters/Body/{gender}/Idle.png"),
            "hair": load_hair_color_sprites(hair_style, "idle", hair_color),
            "head": load_spritesheet(f"client/assets/images/characters/Head/{gender}/Idle.png"),
            "torso": load_spritesheet(f"client/assets/images/characters/Clothing/{gender}/Torso/Shirt 04 - T-shirt/Idle.png"),
            "legs": load_spritesheet(f"client/assets/images/characters/Clothing/{gender}/Legs/Pants 03 - Pants/Idle.png"),
            "feet": load_spritesheet(f"client/assets/images/characters/Clothing/{gender}/Feet/Shoes 01 - Shoes/Idle.png"),
        },
        "jump": {
            "body": load_spritesheet(f"client/assets/images/characters/Body/{gender}/Jump.png", rows=4, cols=6),
            "hair": load_hair_color_sprites(hair_style, "jump", hair_color, rows=4, cols=6),
            "head": load_spritesheet(f"client/assets/images/characters/Head/{gender}/Jump.png", rows=4, cols=6),
            "torso": load_spritesheet(f"client/assets/images/characters/Clothing/{gender}/Torso/Shirt 04 - T-shirt/Jump.png", rows=4, cols=6),
            "legs": load_spritesheet(f"client/assets/images/characters/Clothing/{gender}/Legs/Pants 03 - Pants/Jump.png", rows=4, cols=6),
            "feet": load_spritesheet(f"client/assets/images/characters/Clothing/{gender}/Feet/Shoes 01 - Shoes/Jump.png", rows=4, cols=6),
        },
        "attack": {
            "body": load_spritesheet(f"client/assets/images/characters/Body/{gender}/Combat 1h - Halfslash.png", rows=4, cols=6),
            "hair": load_hair_color_sprites(hair_style, "Combat 1h - Halfslash", hair_color),
            "head": load_spritesheet(f"client/assets/images/characters/Head/{gender}/Combat 1h - Halfslash.png", rows=4, cols=6),
            "torso": load_spritesheet(f"client/assets/images/characters/Clothing/{gender}/Torso/Shirt 04 - T-shirt/Combat 1h - Halfslash.png", rows=4, cols=6),
            "legs": load_spritesheet(f"client/assets/images/characters/Clothing/{gender}/Legs/Pants 03 - Pants/Combat 1h - Halfslash.png", rows=4, cols=6),
            "feet": load_spritesheet(f"client/assets/images/characters/Clothing/{gender}/Feet/Shoes 01 - Shoes/Combat 1h - Halfslash.png", rows=4, cols=6),
        },
        "attack_idle": {
            # Note: if the idle weapon sheet is 256x512 (cols=2, rows=4) this will now compute 128x128 frame size automatically
            "body": load_spritesheet(f"client/assets/images/characters/Body/{gender}/Combat 1h - Idle.png", rows=4, cols=2),
            "hair": load_hair_color_sprites(hair_style, "Combat 1h - Idle", hair_color),
            "head": load_spritesheet(f"client/assets/images/characters/Head/{gender}/Combat 1h - Idle.png", rows=4, cols=2),
            "torso": load_spritesheet(f"client/assets/images/characters/Clothing/{gender}/Torso/Shirt 04 - T-shirt/Combat 1h - Idle.png", rows=4, cols=2),
            "legs": load_spritesheet(f"client/assets/images/characters/Clothing/{gender}/Legs/Pants 03 - Pants/Combat 1h - Idle.png", rows=4, cols=2),
            "feet": load_spritesheet(f"client/assets/images/characters/Clothing/{gender}/Feet/Shoes 01 - Shoes/Combat 1h - Idle.png", rows=4, cols=2),
        },
    }
    
    # Load weapon animations (will be selected based on equipped weapon)
    animations["weapons"] = load_weapon_animations()
    
    return animations

def load_weapon_animations():
    """Load all weapon sprite animations"""
    return {
        "sword_01": {
            "idle": load_spritesheet(
                "client/assets/images/characters/Props/Sword 01/Combat 1h - Idle.png",
                rows=4, cols=2, scale=3.3
            ),
            "halfslash": load_spritesheet(
                "client/assets/images/characters/Props/Sword 01/Combat 1h - Halfslash.png",
                rows=4, cols=6, scale=2.5
            ),
        },
    }