# displacement.py : touche E (charge Kael / teleport Seris / vol Aldric)

import logging

from buff_system import player_has_buff
from combat import normalize, segment_point_dist
from constants import (
    ALDRIC_FLYING_DURATION,
    ARENA_HEIGHT, ARENA_WIDTH,
    DISPLACEMENT_COOLDOWNS,
    KAEL_CHARGE_DAMAGE, KAEL_CHARGE_DISTANCE, KAEL_CHARGE_HIT_RADIUS,
    SERIS_INTANGIBLE_DURATION,
    SOUL_REWARDS,
)

logger = logging.getLogger(__name__)


def handle_displacement(player, tx, ty, state):
    if not player.alive or player.cooldowns.get("displacement", 0) > 0:
        return
    if player_has_buff(player, "casting"):
        return  # canalisation sort divin = on bloque le E

    cls = player.class_name
    if cls == "kael":
        _kael_charge(player, tx, ty, state)
    elif cls == "seris":
        _seris_teleport(player, tx, ty)
    elif cls == "aldric":
        _aldric_fly(player)

    player.cooldowns["displacement"] = DISPLACEMENT_COOLDOWNS[cls]


def _kael_charge(player, tx, ty, state):
    # charge en ligne droite, frappe les ennemis dans le couloir
    dx, dy = normalize(tx - player.x, ty - player.y)
    if dx == 0.0 and dy == 0.0:
        return

    half_w, half_h = ARENA_WIDTH / 2, ARENA_HEIGHT / 2
    end_x = max(-half_w, min(half_w, player.x + dx * KAEL_CHARGE_DISTANCE))
    end_y = max(-half_h, min(half_h, player.y + dy * KAEL_CHARGE_DISTANCE))

    dead_ids = set()
    for enemy in state.enemies:
        dist = segment_point_dist(enemy.x, enemy.y, player.x, player.y, end_x, end_y)
        if dist >= KAEL_CHARGE_HIT_RADIUS:
            continue
        enemy.hp = max(0, enemy.hp - KAEL_CHARGE_DAMAGE)
        if enemy.hp <= 0:
            dead_ids.add(enemy.id)
            player.souls += SOUL_REWARDS.get(enemy.type, 0)

    if dead_ids:
        state.enemies = [e for e in state.enemies if e.id not in dead_ids]

    player.x, player.y = end_x, end_y


def _seris_teleport(player, tx, ty):
    half_w, half_h = ARENA_WIDTH / 2, ARENA_HEIGHT / 2
    player.x = max(-half_w, min(half_w, tx))
    player.y = max(-half_h, min(half_h, ty))
    # immunite breve pendant le teleport (sinon on peut tomber sur un boss et perdre direct)
    player.buffs.append({"type": "intangible", "timer": SERIS_INTANGIBLE_DURATION})


def _aldric_fly(player):
    player.buffs.append({"type": "flying", "timer": ALDRIC_FLYING_DURATION})
