import { PRODUCTS, SECTORS, getProduct } from '../data/products.js';
import { fmtCurrency, fmtNum } from '../core/formatters.js';
import { computeProductNetFlow } from './production/ratesCalculator.js';
let currentMountedProductId = null;
export function mountInspector(container, state, onAction) {
const selectedId = state.selectedProductId || 'wheat';
const product = getProduct(selectedId) || PRODUCTS[0];
const pState = state.products[product.id] || { stock: 0, lines: 0, logistics: 0, unlocked: false };
const sector = SECTORS.find(s => s.id === product.sector);
currentMountedProductId = product.id;
// Downstream products that consume this product
const downstream = PRODUCTS.filter(p => p.inputs && p.inputs.some(inp => inp.id === product.id));
const totalLiquidationValue = (pState.stock || 0) * product.basePrice;
const halfLiquidationValue = totalLiquidationValue * 0.5;
const netFlow = computeProductNetFlow(product, state);
let html = `
Warehouse Stock:
${fmtNum(pState.stock, 0)} ${product.unit}
Wholesale Price:
${fmtCurrency(product.basePrice)}
Net Supply Flow:
${netFlow.netRate > 0.01 ? '+' : ''}${fmtNum(netFlow.netRate, 1)}/s
Logistics Fleets:
${pState.logistics || 0} active (${fmtNum((pState.logistics || 0) * 0.75, 2)}/s)
Supply & Distribution Policies
Instant Wholesale Liquidation
Liquidate stockpiles immediately onto the wholesale spot market.
Supply Chain Dependencies
Direct Inputs:
${(!product.inputs || product.inputs.length === 0) ? `
Primary commodity • Direct extraction from natural deposits.
` : `
${product.inputs.map(inp => {
const parent = getProduct(inp.id);
const parentStock = state.products[inp.id]?.stock || 0;
return `
${parent.name}
${inp.amount} per unit (${fmtNum(parentStock, 0)} on hand)
`;
}).join('')}
`}
Downstream Consumers:
${downstream.length === 0 ? `
End-tier consumer or industrial finished product.
` : `
${downstream.map(child => {
const isUnlocked = state.products[child.id]?.unlocked;
return `
${child.name}
${isUnlocked ? 'Active' : 'Locked'}
`;
}).join('')}
`}
`;
container.innerHTML = html;
const halfBtn = container.querySelector('#insp-btn-half');
if (halfBtn) {
halfBtn.onclick = () => onAction({ type: 'LIQUIDATE_STOCK', productId: product.id, ratio: 0.5 });
}
const allBtn = container.querySelector('#insp-btn-all');
if (allBtn) {
allBtn.onclick = () => onAction({ type: 'LIQUIDATE_STOCK', productId: product.id, ratio: 1.0 });
}
const toggleLogBtn = container.querySelector('#insp-btn-toggle-logistics');
if (toggleLogBtn) {
toggleLogBtn.onclick = () => onAction({ type: 'TOGGLE_LOGISTICS', productId: product.id });
}
const toggleDownBtn = container.querySelector('#insp-btn-toggle-downstream');
if (toggleDownBtn) {
toggleDownBtn.onclick = () => onAction({ type: 'TOGGLE_DOWNSTREAM_SUPPLY', productId: product.id });
}
container.querySelectorAll('.chain-item-row').forEach(row => {
row.onclick = () => onAction({ type: 'SELECT_PRODUCT', productId: row.dataset.product });
});
}
export function updateInspector(container, state) {
const selectedId = state.selectedProductId || 'wheat';
if (selectedId !== currentMountedProductId) {
return; // Caller should remount if product changed
}
const product = getProduct(selectedId);
if (!product) return;
const pState = state.products[product.id] || { stock: 0, lines: 0, logistics: 0 };
// Update stock text
const elStock = document.getElementById('insp-stock');
if (elStock) {
elStock.textContent = `${fmtNum(pState.stock, 0)} ${product.unit}`;
}
// Update policy statuses
const isLogActive = pState.logisticsEnabled !== false;
const elLogStatus = document.getElementById('insp-toggle-log-status');
if (elLogStatus) {
elLogStatus.textContent = isLogActive ? 'ACTIVE' : 'PAUSED';
elLogStatus.style.color = isLogActive ? 'var(--emerald-dark)' : 'var(--amber-dark)';
}
const isDownActive = pState.supplyDownstreamEnabled !== false;
const elDownStatus = document.getElementById('insp-toggle-down-status');
if (elDownStatus) {
elDownStatus.textContent = isDownActive ? 'ALLOWED' : 'BLOCKED';
elDownStatus.style.color = isDownActive ? 'var(--emerald-dark)' : 'var(--amber-dark)';
}
// Update liquidation values & buttons
const totalLiquidationValue = (pState.stock || 0) * product.basePrice;
const halfLiquidationValue = totalLiquidationValue * 0.5;
const elHalfVal = document.getElementById('insp-val-half');
if (elHalfVal) elHalfVal.textContent = fmtCurrency(halfLiquidationValue);
const elAllVal = document.getElementById('insp-val-all');
if (elAllVal) elAllVal.textContent = fmtCurrency(totalLiquidationValue);
const btnHalf = document.getElementById('insp-btn-half');
if (btnHalf) btnHalf.disabled = pState.stock < 2;
const btnAll = document.getElementById('insp-btn-all');
if (btnAll) btnAll.disabled = pState.stock < 1;
// Update Net Flow rate
const netFlow = computeProductNetFlow(product, state);
const elNetRate = document.getElementById('insp-net-rate');
if (elNetRate) {
const sign = netFlow.netRate > 0.01 ? '+' : '';
const netText = `${sign}${fmtNum(netFlow.netRate, 1)}/s`;
if (elNetRate.textContent !== netText) {
elNetRate.textContent = netText;
}
const isDeficit = netFlow.netRate < -0.05;
const isSurplus = netFlow.netRate > 0.05;
elNetRate.className = `metric-val font-mono ${isDeficit ? 'text-warning' : (isSurplus ? 'text-profit' : '')}`;
}
// Update input values
if (product.inputs) {
for (const inp of product.inputs) {
const elInp = document.getElementById(`insp-inp-val-${inp.id}`);
if (elInp) {
elInp.textContent = fmtNum(state.products[inp.id]?.stock || 0, 0);
}
}
}
}