package com.tiedup.remake.cells;

import com.tiedup.remake.core.TiedUpMod;
import com.tiedup.remake.prison.PrisonerManager;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import net.minecraft.server.level.ServerLevel;
import org.jetbrains.annotations.Nullable;

/**
 * Manages maid lifecycle within camps: death, respawn timers, prisoner reassignment.
 *
 * <p>This is a stateless utility class. All state lives in {@link CampOwnership}
 * (the SavedData singleton). Methods here orchestrate maid-specific side effects.
 */
public final class CampMaidManager {

    private CampMaidManager() {} // utility class

    /**
     * Mark the maid as dead for a camp.
     * The camp remains alive but prisoners are paused until new maid spawns.
     *
     * @param campId      The camp UUID
     * @param currentTime The current game time
     * @param level       The server level
     */
    public static void markMaidDead(
        UUID campId,
        long currentTime,
        ServerLevel level
    ) {
        CampOwnership ownership = CampOwnership.get(level);
        CampOwnership.CampData data = ownership.getCamp(campId);
        if (data == null || !data.isAlive()) {
            return;
        }

        // Save maid UUID before clearing (fix NPE)
        UUID deadMaidId = data.getMaidUUID();

        data.setMaidDeathTime(currentTime);
        data.setMaidUUID(null);

        // Reset prisoners who were being escorted by the dead maid
        if (deadMaidId != null) {
            reassignPrisonersFromMaid(deadMaidId, null, level);
        }

        ownership.setDirty();

        TiedUpMod.LOGGER.info(
            "[CampMaidManager] Maid died for camp {} - respawn available in 5 minutes",
            campId.toString().substring(0, 8)
        );
    }

    /**
     * Assign a new maid to a camp (after respawn or initial setup).
     *
     * @param campId      The camp UUID
     * @param newMaidUUID The new maid's UUID
     * @param level       The server level
     */
    public static void assignNewMaid(
        UUID campId,
        UUID newMaidUUID,
        ServerLevel level
    ) {
        CampOwnership ownership = CampOwnership.get(level);
        CampOwnership.CampData data = ownership.getCamp(campId);
        if (data == null) {
            return;
        }

        UUID oldMaidId = data.getMaidUUID();
        data.setMaidUUID(newMaidUUID);
        data.setMaidDeathTime(-1); // Reset death time

        // Transfer prisoners to new maid
        reassignPrisonersFromMaid(oldMaidId, newMaidUUID, level);

        ownership.setDirty();

        TiedUpMod.LOGGER.info(
            "[CampMaidManager] New maid {} assigned to camp {}",
            newMaidUUID.toString().substring(0, 8),
            campId.toString().substring(0, 8)
        );
    }

    /**
     * Get camps that need a new maid spawned.
     *
     * @param currentTime The current game time
     * @param level       The server level
     * @return List of camp IDs ready for maid respawn
     */
    public static List<UUID> getCampsNeedingMaidRespawn(
        long currentTime,
        ServerLevel level
    ) {
        CampOwnership ownership = CampOwnership.get(level);
        List<UUID> result = new ArrayList<>();
        for (CampOwnership.CampData data : ownership.getAllCamps()) {
            if (data.isAlive() && data.canRespawnMaid(currentTime)) {
                result.add(data.getCampId());
            }
        }
        return result;
    }

    /**
     * Reassign all prisoners from one maid to another (for maid death/replacement).
     * The new PrisonerManager tracks labor state separately via LaborRecord.
     *
     * @param oldMaidId The old maid's UUID (or null to assign to all unassigned prisoners)
     * @param newMaidId The new maid's UUID (or null if maid died with no replacement)
     * @param level     The server level
     */
    public static void reassignPrisonersFromMaid(
        @Nullable UUID oldMaidId,
        @Nullable UUID newMaidId,
        ServerLevel level
    ) {
        PrisonerManager manager = PrisonerManager.get(level);

        for (UUID playerId : manager.getAllPrisonerIds()) {
            com.tiedup.remake.prison.LaborRecord labor = manager.getLaborRecord(
                playerId
            );
            if (labor == null) continue;

            // Check if this prisoner was managed by the old maid
            UUID assignedMaid = labor.getMaidId();
            boolean shouldReassign =
                (oldMaidId == null && assignedMaid == null) ||
                (oldMaidId != null && oldMaidId.equals(assignedMaid));

            if (shouldReassign) {
                // Update maid ID in labor record
                labor.setMaidId(newMaidId);

                // If maid died (no replacement) during active work, prisoner can rest
                if (
                    newMaidId == null &&
                    labor.getPhase() !=
                    com.tiedup.remake.prison.LaborRecord.WorkPhase.IDLE
                ) {
                    labor.setPhase(
                        com.tiedup.remake.prison.LaborRecord.WorkPhase.IDLE,
                        level.getGameTime()
                    );
                    TiedUpMod.LOGGER.info(
                        "[CampMaidManager] Prisoner {} labor reset to IDLE - maid died during escort",
                        playerId.toString().substring(0, 8)
                    );
                }
                // If there's a replacement maid, keep current state so they get picked up
            }
        }
        CampOwnership.get(level).setDirty();
    }
}
