package com.tiedup.remake.compat.mca.capability;

import com.tiedup.remake.compat.mca.personality.TiedUpTrait;
import com.tiedup.remake.util.tasks.ItemTask;
import com.tiedup.remake.v2.BodyRegionV2;
import java.util.UUID;
import javax.annotation.Nullable;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.world.item.ItemStack;
import net.minecraftforge.common.util.INBTSerializable;

/**
 * Capability that stores bondage state for MCA villagers.
 *
 * Stores:
 * - 7 bondage equipment slots (bind, gag, blindfold, earplugs, collar, clothes, mittens)
 * - Captor UUID
 * - For sale state and price
 * - Resistance values for struggle system
 */
public class MCAKidnappedCapability implements INBTSerializable<CompoundTag> {

    // BONDAGE EQUIPMENT SLOTS

    private ItemStack bind = ItemStack.EMPTY;
    private ItemStack gag = ItemStack.EMPTY;
    private ItemStack blindfold = ItemStack.EMPTY;
    private ItemStack earplugs = ItemStack.EMPTY;
    private ItemStack collar = ItemStack.EMPTY;
    private ItemStack clothes = ItemStack.EMPTY;
    private ItemStack mittens = ItemStack.EMPTY;

    // CAPTURE STATE

    /** UUID of the captor entity (null if not captured) */
    @Nullable
    private UUID captorUUID = null;

    /** Whether this villager is for sale */
    private boolean forSale = false;

    /** Sale price (null if not for sale) */
    @Nullable
    private ItemTask salePrice = null;

    // RESISTANCE VALUES

    private int bindResistance = 0;
    private int collarResistance = 0;

    // TIEDUP TRAIT

    /** TiedUp-specific trait (MASO, REBELLIOUS, etc.) */
    private TiedUpTrait trait = TiedUpTrait.NONE;

    // EQUIPMENT GETTERS

    public ItemStack getBind() {
        return bind;
    }

    public ItemStack getGag() {
        return gag;
    }

    public ItemStack getBlindfold() {
        return blindfold;
    }

    public ItemStack getEarplugs() {
        return earplugs;
    }

    public ItemStack getCollar() {
        return collar;
    }

    public ItemStack getClothes() {
        return clothes;
    }

    public ItemStack getMittens() {
        return mittens;
    }

    /**
     * Get item by body region.
     */
    public ItemStack getItem(BodyRegionV2 region) {
        return switch (region) {
            case ARMS -> bind;
            case MOUTH -> gag;
            case EYES -> blindfold;
            case EARS -> earplugs;
            case NECK -> collar;
            case TORSO -> clothes;
            case HANDS -> mittens;
            default -> ItemStack.EMPTY;
        };
    }

    // EQUIPMENT SETTERS

    public void setBind(ItemStack stack) {
        this.bind = stack.copy();
    }

    public void setGag(ItemStack stack) {
        this.gag = stack.copy();
    }

    public void setBlindfold(ItemStack stack) {
        this.blindfold = stack.copy();
    }

    public void setEarplugs(ItemStack stack) {
        this.earplugs = stack.copy();
    }

    public void setCollar(ItemStack stack) {
        this.collar = stack.copy();
    }

    public void setClothes(ItemStack stack) {
        this.clothes = stack.copy();
    }

    public void setMittens(ItemStack stack) {
        this.mittens = stack.copy();
    }

    /**
     * Set item by body region.
     */
    public void setItem(BodyRegionV2 region, ItemStack stack) {
        switch (region) {
            case ARMS -> setBind(stack);
            case MOUTH -> setGag(stack);
            case EYES -> setBlindfold(stack);
            case EARS -> setEarplugs(stack);
            case NECK -> setCollar(stack);
            case TORSO -> setClothes(stack);
            case HANDS -> setMittens(stack);
            default -> {
            } // Unsupported region — no-op
        }
    }

    /**
     * Clear a region and return the old item.
     */
    public ItemStack clearSlot(BodyRegionV2 region) {
        ItemStack old = getItem(region).copy();
        setItem(region, ItemStack.EMPTY);
        return old;
    }

    // STATE QUERIES

    public boolean hasBind() {
        return !bind.isEmpty();
    }

    public boolean hasGag() {
        return !gag.isEmpty();
    }

    public boolean hasBlindfold() {
        return !blindfold.isEmpty();
    }

    public boolean hasEarplugs() {
        return !earplugs.isEmpty();
    }

    public boolean hasCollar() {
        return !collar.isEmpty();
    }

    public boolean hasClothes() {
        return !clothes.isEmpty();
    }

    public boolean hasMittens() {
        return !mittens.isEmpty();
    }

    // CAPTURE STATE

    @Nullable
    public UUID getCaptorUUID() {
        return captorUUID;
    }

    public void setCaptorUUID(@Nullable UUID uuid) {
        this.captorUUID = uuid;
    }

    public boolean isCaptured() {
        return captorUUID != null;
    }

    public boolean isForSale() {
        return forSale;
    }

    public void setForSale(boolean forSale) {
        this.forSale = forSale;
    }

    @Nullable
    public ItemTask getSalePrice() {
        return salePrice;
    }

    public void setSalePrice(@Nullable ItemTask price) {
        this.salePrice = price;
    }

    // RESISTANCE

    public int getBindResistance() {
        return bindResistance;
    }

    public void setBindResistance(int resistance) {
        this.bindResistance = Math.max(0, resistance);
    }

    public int getCollarResistance() {
        return collarResistance;
    }

    public void setCollarResistance(int resistance) {
        this.collarResistance = Math.max(0, resistance);
    }

    // TIEDUP TRAIT

    public TiedUpTrait getTrait() {
        return trait;
    }

    public void setTrait(TiedUpTrait trait) {
        this.trait = trait != null ? trait : TiedUpTrait.NONE;
    }

    // CLEAR ALL

    /**
     * Clear all bondage equipment.
     */
    public void clearAllEquipment() {
        bind = ItemStack.EMPTY;
        gag = ItemStack.EMPTY;
        blindfold = ItemStack.EMPTY;
        earplugs = ItemStack.EMPTY;
        collar = ItemStack.EMPTY;
        clothes = ItemStack.EMPTY;
        mittens = ItemStack.EMPTY;
    }

    /**
     * Clear all state (equipment + capture state).
     * Note: Does NOT clear trait - that persists across captures.
     */
    public void clearAll() {
        clearAllEquipment();
        captorUUID = null;
        forSale = false;
        salePrice = null;
        bindResistance = 0;
        collarResistance = 0;
        // trait is NOT cleared - it persists
    }

    // NBT SERIALIZATION

    private static final String TAG_BIND = "Bind";
    private static final String TAG_GAG = "Gag";
    private static final String TAG_BLINDFOLD = "Blindfold";
    private static final String TAG_EARPLUGS = "Earplugs";
    private static final String TAG_COLLAR = "Collar";
    private static final String TAG_CLOTHES = "Clothes";
    private static final String TAG_MITTENS = "Mittens";
    private static final String TAG_CAPTOR = "Captor";
    private static final String TAG_FOR_SALE = "ForSale";
    private static final String TAG_SALE_PRICE = "SalePrice";
    private static final String TAG_BIND_RESISTANCE = "BindResistance";
    private static final String TAG_COLLAR_RESISTANCE = "CollarResistance";
    private static final String TAG_TRAIT = "TiedUpTrait";

    @Override
    public CompoundTag serializeNBT() {
        CompoundTag tag = new CompoundTag();

        // Equipment
        if (!bind.isEmpty()) {
            tag.put(TAG_BIND, bind.save(new CompoundTag()));
        }
        if (!gag.isEmpty()) {
            tag.put(TAG_GAG, gag.save(new CompoundTag()));
        }
        if (!blindfold.isEmpty()) {
            tag.put(TAG_BLINDFOLD, blindfold.save(new CompoundTag()));
        }
        if (!earplugs.isEmpty()) {
            tag.put(TAG_EARPLUGS, earplugs.save(new CompoundTag()));
        }
        if (!collar.isEmpty()) {
            tag.put(TAG_COLLAR, collar.save(new CompoundTag()));
        }
        if (!clothes.isEmpty()) {
            tag.put(TAG_CLOTHES, clothes.save(new CompoundTag()));
        }
        if (!mittens.isEmpty()) {
            tag.put(TAG_MITTENS, mittens.save(new CompoundTag()));
        }

        // Capture state
        if (captorUUID != null) {
            tag.putUUID(TAG_CAPTOR, captorUUID);
        }
        tag.putBoolean(TAG_FOR_SALE, forSale);
        if (salePrice != null) {
            tag.put(TAG_SALE_PRICE, salePrice.save());
        }

        // Resistance
        tag.putInt(TAG_BIND_RESISTANCE, bindResistance);
        tag.putInt(TAG_COLLAR_RESISTANCE, collarResistance);

        // TiedUp Trait
        tag.putString(TAG_TRAIT, trait.getId());

        return tag;
    }

    @Override
    public void deserializeNBT(CompoundTag tag) {
        // Equipment
        bind = tag.contains(TAG_BIND)
            ? ItemStack.of(tag.getCompound(TAG_BIND))
            : ItemStack.EMPTY;
        gag = tag.contains(TAG_GAG)
            ? ItemStack.of(tag.getCompound(TAG_GAG))
            : ItemStack.EMPTY;
        blindfold = tag.contains(TAG_BLINDFOLD)
            ? ItemStack.of(tag.getCompound(TAG_BLINDFOLD))
            : ItemStack.EMPTY;
        earplugs = tag.contains(TAG_EARPLUGS)
            ? ItemStack.of(tag.getCompound(TAG_EARPLUGS))
            : ItemStack.EMPTY;
        collar = tag.contains(TAG_COLLAR)
            ? ItemStack.of(tag.getCompound(TAG_COLLAR))
            : ItemStack.EMPTY;
        clothes = tag.contains(TAG_CLOTHES)
            ? ItemStack.of(tag.getCompound(TAG_CLOTHES))
            : ItemStack.EMPTY;
        mittens = tag.contains(TAG_MITTENS)
            ? ItemStack.of(tag.getCompound(TAG_MITTENS))
            : ItemStack.EMPTY;

        // Capture state
        captorUUID = tag.hasUUID(TAG_CAPTOR) ? tag.getUUID(TAG_CAPTOR) : null;
        forSale = tag.getBoolean(TAG_FOR_SALE);
        if (tag.contains(TAG_SALE_PRICE)) {
            salePrice = ItemTask.load(tag.getCompound(TAG_SALE_PRICE));
        } else {
            salePrice = null;
        }

        // Resistance
        bindResistance = tag.getInt(TAG_BIND_RESISTANCE);
        collarResistance = tag.getInt(TAG_COLLAR_RESISTANCE);

        // TiedUp Trait
        trait = tag.contains(TAG_TRAIT)
            ? TiedUpTrait.fromId(tag.getString(TAG_TRAIT))
            : TiedUpTrait.NONE;
    }
}
