package calc

func ShipProductionCost(shipEmptyMass float64) float64 {
	return shipEmptyMass * 10.
}

func PlanetProduceShipMass(L, Mat, Res float64) float64 {
	result := L / 10
	if result <= Mat {
		return result
	}
	return (L + Mat/Res) / (10 + 1/Res)
}

// ShipBuildCost returns the total per-turn cost (production units) to
// build one ship of empty mass shipMass on a planet that currently
// holds material stockpile and has natural resources. The cost is the
// ship's production cost ([ShipProductionCost]) plus the cost of
// farming any missing material from the planet (the missing-material
// volume divided by the planet's resources rating).
//
// resources is expected to be positive in normal play; the helper
// guards against a non-positive value by collapsing the material-
// farming term to zero, which keeps callers numerically stable on
// pathological synthetic data. [ProduceShipsInTurn] composes this cost
// into the per-turn build loop that the engine's controller.ProduceShip
// delegates to, so the engine, the calculator, and the
// legacy-report-to-json dev tool (which derives prod_used from percent)
// all share one formula.
func ShipBuildCost(shipMass, material, resources float64) float64 {
	matNeed := shipMass - material
	if matNeed < 0 {
		matNeed = 0
	}
	matFarm := 0.
	if resources > 0 {
		matFarm = matNeed / resources
	}
	return ShipProductionCost(shipMass) + matFarm
}

// ProduceShipsInTurn simulates one turn of ship production on a planet
// that has productionAvailable production units to spend, a material
// stockpile, a resources rating, building ships of empty mass shipMass.
// It returns the number of whole ships completed this turn, the material
// left afterwards, the production units spent on the next (still
// incomplete) ship, and that ship's progress fraction in [0, 1).
//
// Each ship consumes shipMass units of material; any shortfall is farmed
// through [ShipBuildCost] at the planet's resources rating, draining the
// stockpile to zero before farming. The loop mirrors the engine's
// per-turn build step so the calculator and the turn generator agree on
// how many ships a planet yields. productionAvailable or shipMass that is
// non-positive yields no ships and leaves the stockpile untouched.
func ProduceShipsInTurn(
	productionAvailable, material, resources, shipMass float64,
) (ships uint, materialLeft, productionUsed, progress float64) {
	if productionAvailable <= 0 || shipMass <= 0 {
		return 0, material, 0, 0
	}
	pa := productionAvailable
	mat := material
	for {
		matNeed := shipMass - mat
		if matNeed < 0 {
			matNeed = 0
		}
		totalCost := ShipBuildCost(shipMass, mat, resources)
		if pa < totalCost {
			return ships, mat, pa, pa / totalCost
		}
		pa -= totalCost
		mat = mat - shipMass + matNeed
		ships++
	}
}
