import { Container } from "./Container.js";
import { Settings } from "./Settings.js";
/**
* Container handling utilities abstracted for both native dnd5e containers and
* Beaver's Crafting container subtype.
*/
/**
* Find children of a source container by scanning siblings next to the source
* (either in its compendium pack or in world items), matching:
* - `flags.beavers-crafting.containerId === source.id` (Beaver's Crafting)
* Returns Components for convenience.
*/
export async function findSourceChildrenComponents(sourceEntity, property = `flags.${Settings.NAMESPACE}.containerId`) {
	if (!(Container.isContainer(sourceEntity) || isDnd5eContainer(sourceEntity)))
		return [];
	const srcId = sourceEntity.id;
	const uuid = sourceEntity.uuid;
	let sourceChildren = [];
	// Case 1: Item is on an Actor (World or Compendium)
	// UUID for actor item is often "Actor.<id>.Item.<id>" or "Compendium.<pack>.Actor.<id>.Item.<id>"
	if (uuid?.includes(".Actor.") || uuid?.startsWith("Actor.")) {
		try {
			const actor = sourceEntity.actor || (await fromUuid(uuid.split(".Item.")[0]));
			if (actor && actor.items) {
				sourceChildren = actor.items.filter((i) => {
					if (i.id === srcId)
						return false;
					const beaversContainerId = foundry.utils.getProperty(i, property);
					return beaversContainerId === srcId;
				});
			}
		}
		catch (e) {
			console.warn("Beavers Crafting | container copy: actor scan failed", e);
		}
	}
	// Case 2: Item is in a Compendium (top-level)
	// UUID is "Compendium.<pack>.Item.<id>"
	if (sourceChildren.length === 0 && uuid?.startsWith("Compendium.")) {
		try {
			const parts = uuid.split(".");
			const packId = parts[1] + "." + parts[2];
			const pack = game.packs?.get(packId);
			if (pack) {
				const docs = await pack.getDocuments();
				sourceChildren = docs.filter((i) => {
					if (i.id === srcId)
						return false;
					const beaversContainerId = foundry.utils.getProperty(i, property);
					return beaversContainerId === srcId;
				});
			}
		}
		catch (e) {
			console.warn("Beavers Crafting | container copy: pack scan failed", e);
		}
	}
	// Case 3: Fallback: scan world items
	if (sourceChildren.length === 0 && game.items) {
		const worldItems = game?.items?.contents || [];
		sourceChildren = worldItems.filter((i) => {
			if (i.id === srcId)
				return false;
			const beaversContainerId = foundry.utils.getProperty(i, property);
			return beaversContainerId === srcId;
		});
	}
	return sourceChildren.map((child) => beaversSystemInterface.componentFromEntity(child));
}
/**
* Attach discovered source container contents to the created container,
*/
export async function attachContentsToCreatedContainer(createdContainerItem, sourceComponent, property) {
	const children = await findSourceChildrenComponents(await sourceComponent.getEntity(), property);
	if (children.length === 0)
		return;
	const cont = new Container(createdContainerItem);
	for (const cc of children) {
		await cont.addContent(cc, property);
	}
}
/**
* Unified read API to get the content pool an actor offers to crafting logic.
* For now, this simply maps actor.items to components; hiding is a UI concern.
*/
export function getActorContentPool(actor, asComponents = true) {
	const filteredItems = actor.items
		.filter((i) => {
		const isBeaversContainer = foundry.utils.getProperty(i, `flags.${Settings.NAMESPACE}.subtype`) === 'container';
		const isNativeDnd5eContainer = (game.system?.id === 'dnd5e') && i.type === 'container';
		// Filter OUT containers themselves, but KEEP their contents and regular items
		return !(isBeaversContainer || isNativeDnd5eContainer);
	});
	if (asComponents) {
		return filteredItems.map((i) => beaversSystemInterface.componentFromEntity(i));
	}
	return filteredItems;
}
/**
* Utility helpers for beavers-crafting container subtype (non-dnd5e native case).
*/
export function isBeaversContainer(item) {
	return foundry.utils.getProperty(item, `flags.${Settings.NAMESPACE}.subtype`) === 'container';
}
export function isDnd5eContainer(item) {
	return game.system.id === 'dnd5e' && item.type === 'container';
}
/**
* Cleanup script to remove containerId flags from items that no longer have a valid container.
*/
export async function runCleanup() {
	if (!game?.user?.isGM)
		return;
	console.log("Beavers Crafting | Running cleanup...");
	// 1. World Items
	const worldItems = game?.items?.contents || [];
	const worldContainerIds = new Set(worldItems
		.filter(i => Container.isContainer(i))
		.map(i => i.id));
	await _cleanupItems(worldItems, game?.items, worldContainerIds);
	// 2. PC Actor Items
	const pcActors = game?.actors?.filter(a => a.type === "character" || a.hasPlayerOwner) || [];
	for (const actor of pcActors) {
		const actorItems = actor.items.contents;
		const actorContainerIds = new Set(actorItems
			.filter(i => Container.isContainer(i))
			.map(i => i.id));
		await _cleanupItems(actorItems, actor, actorContainerIds);
	}
	console.log("Beavers Crafting | Cleanup finished.");
	Settings.set(Settings.LAST_CLEANUP_TIMESTAMP, Date.now());
}
async function _cleanupItems(items, parent, validContainerIds) {
	const updates = [];
	for (const item of items) {
		const containerId = foundry.utils.getProperty(item, `flags.${Settings.NAMESPACE}.containerId`);
		if (containerId && !validContainerIds.has(containerId)) {
			// @ts-ignore
			updates.push({ _id: item.id, [`flags.${Settings.NAMESPACE}.-=containerId`]: null });
		}
	}
	if (updates.length > 0) {
		if (parent instanceof Actor) {
			await parent.updateEmbeddedDocuments("Item", updates);
		}
		else {
			await Item.updateDocuments(updates);
		}
	}
}
export async function dnd5eCopyContent(componentList, itemChange) {
	if (game.system.id !== "dnd5e") {
		return;
	}
	try {
		for (const component of componentList) {
			if (component.quantity > 0) {
				// Find the created container item that matches this component
				const createdItems = (itemChange.create || []);
				for (const createdItem of createdItems) {
					if (createdItem.type !== "container")
						continue;
					const createdComp = beaversSystemInterface.componentFromEntity(createdItem);
					if (!(createdComp.isSame(component) && component.isSame(createdComp)))
						continue;
					try {
						await attachContentsToCreatedContainer(createdItem, component, `system.container`);
					}
					catch (inner) {
						console.warn('Beavers Crafting | Failed copying container contents from source:', inner);
					}
				}
			}
		}
	}
	catch (e) {
		console.warn("Beavers Crafting | Failed to attach contents to produced container:", e);
	}
}
