package com.tiedup.remake.entities;

import com.tiedup.remake.v2.bondage.PoseTypeHelper;
import com.tiedup.remake.state.IBondageState;
import com.tiedup.remake.util.KidnappedHelper;
import com.tiedup.remake.v2.BodyRegionV2;
import java.util.Objects;
import javax.annotation.ParametersAreNonnullByDefault;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.ServerScoreboard;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.Pose;
import net.minecraft.world.entity.animal.Turtle;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.phys.Vec3;
import net.minecraft.world.scores.PlayerTeam;

/**
 * Invisible proxy entity that follows a player and holds the leash.
 *
 * Based on PlayerCollars LeashProxyEntity implementation.
 * Uses Turtle as base because it's a simple, leashable mob.
 *
 * Key features:
 * - Baby turtle (small hitbox)
 * - Invisible and invulnerable
 * - No physics or collision
 * - Follows target player's position (offset to neck height)
 * - Leash renders from this entity to the holder
 */
@ParametersAreNonnullByDefault
public final class LeashProxyEntity extends Turtle {

    /** Team name for preventing collision display */
    public static final String TEAM_NAME = "tiedup_leash_proxy";

    /** The player this proxy follows */
    private final LivingEntity target;

    /**
     * Create a new leash proxy for a target player.
     *
     * @param target The player to follow
     */
    public LeashProxyEntity(LivingEntity target) {
        super(EntityType.TURTLE, target.level());
        this.target = target;

        // Make it invisible and invulnerable
        setHealth(1.0F);
        setInvulnerable(true);
        setBaby(true);
        setInvisible(true);
        noPhysics = true;

        // Add to team to prevent collision nameplate display
        MinecraftServer server = getServer();
        if (server != null) {
            ServerScoreboard scoreboard = server.getScoreboard();

            PlayerTeam team = scoreboard.getPlayerTeam(TEAM_NAME);
            if (team == null) {
                team = scoreboard.addPlayerTeam(TEAM_NAME);
            }
            if (team.getCollisionRule() != PlayerTeam.CollisionRule.NEVER) {
                team.setCollisionRule(PlayerTeam.CollisionRule.NEVER);
            }

            scoreboard.addPlayerToTeam(getScoreboardName(), team);
        }
    }

    // ==================== Position Sync ====================

    /**
     * Update proxy position to match target.
     *
     * @return true if proxy should be removed (target invalid)
     */
    private boolean proxyUpdate() {
        if (proxyIsRemoved()) return false;

        if (target == null) return true;
        if (target.level() != level() || !target.isAlive()) return true;

        // If target is a player who disconnected, remove proxy
        if (
            target instanceof ServerPlayer serverPlayer &&
            serverPlayer.hasDisconnected()
        ) {
            return true;
        }

        Vec3 posActual = this.position();

        // Dynamic Y offset based on bind type
        // DOGBINDER = lower height for 4-legged pose (0.6)
        // Default = neck height (1.3)
        double yOffset = 1.3D;
        if (target instanceof ServerPlayer player) {
            IBondageState state = KidnappedHelper.getKidnappedState(player);
            if (state != null && state.isTiedUp()) {
                ItemStack bind = state.getEquipment(BodyRegionV2.ARMS);
                if (
                    !bind.isEmpty() &&
                    PoseTypeHelper.getPoseType(bind) == com.tiedup.remake.items.base.PoseType.DOG
                ) {
                    yOffset = 0.35D; // Lower for 4-legged dogwalk pose (back/hip level)
                }
            }
        }

        Vec3 posTarget = target.position().add(0.0D, yOffset, -0.15D);

        if (!Objects.equals(posActual, posTarget)) {
            setRot(0.0F, 0.0F);
            setPos(posTarget.x(), posTarget.y(), posTarget.z());
            setBoundingBox(
                getDimensions(Pose.DYING).makeBoundingBox(posTarget)
            );
        }

        // Update leash (handles vanilla leash physics)
        tickLeash();

        return false;
    }

    @Override
    public void tick() {
        if (this.level().isClientSide) return;

        if (proxyUpdate() && !proxyIsRemoved()) {
            proxyRemove();
        }
    }

    // ==================== Lifecycle ====================

    /**
     * Check if this proxy has been removed.
     */
    public boolean proxyIsRemoved() {
        return this.isRemoved();
    }

    /**
     * Remove this proxy entity.
     */
    public void proxyRemove() {
        super.remove(RemovalReason.DISCARDED);
    }

    /**
     * Override remove() to prevent accidental removal.
     * Use proxyRemove() for intentional removal.
     */
    @Override
    public void remove(RemovalReason reason) {
        // Only allow removal via proxyRemove() or if truly killed
        if (
            reason == RemovalReason.KILLED ||
            reason == RemovalReason.CHANGED_DIMENSION
        ) {
            super.remove(reason);
        }
        // Ignore other removal attempts
    }

    // ==================== Override to Prevent Behavior ====================

    @Override
    public float getHealth() {
        return 1.0F;
    }

    @Override
    public void dropLeash(boolean sendPacket, boolean dropItem) {
        // Don't drop leash - managed by mixin
    }

    @Override
    public boolean canBeLeashed(Player player) {
        return false;
    }

    @Override
    protected void registerGoals() {
        // No AI goals
    }

    @Override
    protected void doPush(Entity entity) {
        // No pushing
    }

    @Override
    public void push(Entity entity) {
        // No pushing
    }

    @Override
    public void playerTouch(Player player) {
        // No interaction
    }

    @Override
    public boolean isPushable() {
        return false;
    }

    @Override
    protected Vec3 getLeashOffset() {
        // The proxy is already positioned at the player's neck (Y+1.3)
        // No additional offset needed - leash attaches exactly at proxy position
        return Vec3.ZERO;
    }

    @Override
    public boolean isInvulnerableTo(
        net.minecraft.world.damagesource.DamageSource source
    ) {
        return true;
    }

    @Override
    public boolean hurt(
        net.minecraft.world.damagesource.DamageSource source,
        float amount
    ) {
        return false;
    }

    /**
     * Get the target entity this proxy follows.
     */
    public LivingEntity getTarget() {
        return target;
    }
}
