package com.ghost.technic.server;

import com.ghost.technic.server.board.PlayArea;
import com.ghost.technic.server.card.impl.ArchonIdentityCard;
import com.ghost.technic.server.card.keyword.BeforeFightEffect;
import com.ghost.technic.server.card.misc.House;
import com.ghost.technic.server.card.playable.PlayableCard;
import com.ghost.technic.server.card.playable.usable.impl.CreatureCard;
import com.ghost.technic.server.game.event.EventBus;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;

import java.util.*;

@Data
@Slf4j
@Builder
@AllArgsConstructor
public class Player {
    private String name;
    private int amber;
    private int keysForged;
    @Builder.Default
    private PlayArea playArea = new PlayArea();
    @Builder.Default
    private LinkedList<PlayableCard> deck = new LinkedList<>();
    @Builder.Default
    private LinkedList<PlayableCard> discardPile = new LinkedList<>();
    @Builder.Default
    private List<PlayableCard> hand = new ArrayList<>();
    @Builder.Default
    private List<PlayableCard> archives = new ArrayList<>();
    private ArchonIdentityCard archonIdentityCard;
    private House activeHouse;

    public Player(Player player) {
        this.name = player.getName();
        this.amber = player.getAmber();
        this.keysForged = player.getKeysForged();
        this.playArea = player.getPlayArea();
        this.deck = player.getDeck();
        this.discardPile = player.getDiscardPile();
        this.hand = player.getHand();
        this.archives = player.getArchives();
        this.archonIdentityCard = player.getArchonIdentityCard();
        this.activeHouse = player.getActiveHouse();
    }

    public Set<House> getAvailableHouses() {
        var results = new HashSet<House>();
        results.addAll(archonIdentityCard.getHouses());
        results.addAll(playArea.getAllUsableCardsHouse());
        return results;
    }

    public void drawCards(int count) {
        for (int i = 0; i < count && !deck.isEmpty(); i++) {
            hand.add(deck.remove(0));
        }
    }

    public void drawCardsToSix() {
//        while (hand.size() < 6) {
        while (hand.size() < 6 && !deck.isEmpty()) {
            drawCards(1);
        }
    }

    public void forgeKey(int keyCost) {
        if (amber >= keyCost) {
            amber -= keyCost;
            keysForged++;
            log.info("{} forges a key at cost {}! Keys forged: {}", name, keyCost, keysForged);
        } else {
            log.info("{} cannot afford a key (needs {}, has {})", name, keyCost, amber);
        }
    }

    public House chooseHouse(Set<House> house) {
        // Placeholder for UI, use override for testing
        log.info("{} chooses house: {}", name, activeHouse);
        return null;
    }

    public void pickUpArchives() {
        if (!archives.isEmpty()) {
            hand.addAll(archives);
            archives.clear();
            log.info("{} picked up archives.", name);
        }
    }

    public void readyCards() {
        for (CreatureCard creatureCard : playArea.getBattleline().getCreatures()) {
            creatureCard.setReady(true);
        }
    }

    public PlayableCard takeTopCardOfDeck() {
        if (!deck.isEmpty()) {
            var topCard = deck.getFirst();
            deck.remove(topCard);
            return topCard;
        } else {
            return null;
        }
    }

    public void fightWithCreature(CreatureCard creature, CreatureCard target) {
        if (!creature.isReady()) return;
        creature.beforeFight();
        target.beforeFight();

        log.info(name + "'s " + creature.getName() + " fights " + target.getName());

//        target.takeDamage(creature.);
//        creature.takeDamage(target.getPower());

        creature.afterFight();
        target.afterFight();

        creature.setReady(false);
        removeDestroyedCreatures();
    }

    public void reapWithCreature(CreatureCard creature, EventBus eventBus) {
        if (!creature.isReady()) {
            log.info("Creature is exhausted, cannot reap");
            return;
        }
        creature.beforeReap();
        // Perform the actual reap logic (creature gains 1 amber, exhausts, etc.)
        creature.reap(this, eventBus);
        amber++;
        log.info("{} reaps with {} and gains 1 amber.", name, creature.getName());
        creature.afterReap();
        creature.setReady(false);
    }

    public List<BeforeFightEffect> chooseBeforeFightOrder(List<BeforeFightEffect> effects) {
        // 🔧 TEMP: Default to resolving in order as-is (assault first, then hazardous)
        // Later: prompt human or AI to choose order
        return effects;
    }

    public CreatureCard chooseCreature(List<CreatureCard> options, String reason) {
        // Placeholder for UI, use override for testing
        log.info("[chooseCreature] {} selects creature for: {}", getName(), reason);
        return options.stream().findFirst().orElse(null); // pick first for now
    }

    public void removeDestroyedCreatures() {
        playArea.getBattleline().getCreatures().removeIf(card -> {
            if (card instanceof CreatureCard creature && creature.isDestroyed()) {
                log.info("{}'s {} is removed from battleline.", name, creature.getName());
                return true;
            }
            return false;
        });
    }
}
