// `Core` is the typed TypeScript view of the Galaxy compute boundary
// (`ui/core` Go module compiled to WASM/native). It only carries
// canonical-bytes serialization and signature verification — no
// network I/O, no key storage, no signing private keys. Real Ed25519
// signing happens in a platform-specific `Signer` (Phase 6 introduces
// WebCrypto for the web target).
//
// All byte fields are `Uint8Array`. Timestamps are `bigint` to keep
// nanosecond-resolution-friendly headroom and to mirror the v2
// Protobuf-ES `int64 → bigint` mapping used by the generated stubs.

export interface RequestSigningFields {
	protocolVersion: string;
	deviceSessionId: string;
	messageType: string;
	timestampMs: bigint;
	requestId: string;
	payloadHash: Uint8Array;
}

export interface ResponseSigningFields {
	protocolVersion: string;
	requestId: string;
	timestampMs: bigint;
	resultCode: string;
	payloadHash: Uint8Array;
}

export interface EventSigningFields {
	eventType: string;
	eventId: string;
	timestampMs: bigint;
	requestId: string;
	traceId: string;
	payloadHash: Uint8Array;
}

export interface DriveEffectiveInput {
	drive: number;
	driveTech: number;
}

export interface ShipBlocksInput {
	drive: number;
	weapons: number;
	armament: number;
	shields: number;
	cargo: number;
}

export interface WeaponsBlockInput {
	weapons: number;
	armament: number;
}

export interface FullMassInput {
	emptyMass: number;
	carryingMass: number;
}

export interface SpeedInput {
	driveEffective: number;
	fullMass: number;
}

export interface CargoCapacityInput {
	cargo: number;
	cargoTech: number;
}

export interface CarryingMassInput {
	load: number;
	cargoTech: number;
}

export interface BlockUpgradeCostInput {
	blockMass: number;
	currentTech: number;
	targetTech: number;
}

export interface EffectiveAttackInput {
	weapons: number;
	weaponsTech: number;
}

export interface EffectiveDefenceInput {
	shields: number;
	shieldsTech: number;
	fullMass: number;
}

export interface BombingPowerInput {
	weapons: number;
	weaponsTech: number;
	armament: number;
	number: number;
}

export interface ShipBuildCostInput {
	shipMass: number;
	material: number;
	resources: number;
}

export interface ProduceShipsInTurnInput {
	productionAvailable: number;
	material: number;
	resources: number;
	shipMass: number;
}

export interface ProduceShipsInTurnResult {
	ships: number;
	materialLeft: number;
	productionUsed: number;
	progress: number;
}

export interface WeaponsForAttackInput {
	targetAttack: number;
	weaponsTech: number;
}

export interface DriveForSpeedInput {
	targetSpeed: number;
	driveTech: number;
	restMass: number;
}

export interface ShieldsForDefenceInput {
	targetDefence: number;
	shieldsTech: number;
	restMass: number;
}

export interface CargoForEmptyMassInput {
	targetEmptyMass: number;
	restMass: number;
}

export interface LoadForFullMassInput {
	targetFullMass: number;
	emptyMass: number;
	cargoTech: number;
}

export interface Ceil3Input {
	value: number;
}

export interface Core {
	/**
	 * signRequest returns the canonical signing input bytes for a v1
	 * request envelope. Callers feed the result into a platform `Signer`
	 * (e.g. WebCrypto) to produce the actual Ed25519 signature.
	 */
	signRequest(fields: RequestSigningFields): Uint8Array;

	/**
	 * verifyResponse authenticates a server response signature against
	 * the canonical v1 response signing input.
	 */
	verifyResponse(
		publicKey: Uint8Array,
		signature: Uint8Array,
		fields: ResponseSigningFields,
	): boolean;

	/**
	 * verifyEvent authenticates a push-event signature against the
	 * canonical v1 event signing input.
	 */
	verifyEvent(
		publicKey: Uint8Array,
		signature: Uint8Array,
		fields: EventSigningFields,
	): boolean;

	/**
	 * verifyPayloadHash returns true when payloadHash is the raw 32-byte
	 * SHA-256 digest of payloadBytes.
	 */
	verifyPayloadHash(
		payloadBytes: Uint8Array,
		payloadHash: Uint8Array,
	): boolean;

	/**
	 * driveEffective wraps `pkg/calc/ship.go.DriveEffective`: effective
	 * drive power = ship drive block × player drive tech.
	 */
	driveEffective(input: DriveEffectiveInput): number;

	/**
	 * emptyMass wraps `pkg/calc/ship.go.EmptyMass`: mass of the ship
	 * with empty holds. Returns null when the upstream validator
	 * rejects the weapons/armament pair (one zero and the other
	 * non-zero).
	 */
	emptyMass(input: ShipBlocksInput): number | null;

	/**
	 * weaponsBlockMass wraps `pkg/calc/ship.go.WeaponsBlockMass`: mass
	 * of the weapons sub-block. Returns null on the same invalid
	 * pairing as emptyMass.
	 */
	weaponsBlockMass(input: WeaponsBlockInput): number | null;

	/**
	 * fullMass wraps `pkg/calc/ship.go.FullMass`: empty mass plus the
	 * mass of the carried cargo.
	 */
	fullMass(input: FullMassInput): number;

	/**
	 * speed wraps `pkg/calc/ship.go.Speed`: light-years per turn,
	 * driveEffective × 20 / fullMass; zero when fullMass ≤ 0.
	 */
	speed(input: SpeedInput): number;

	/**
	 * cargoCapacity wraps `pkg/calc/ship.go.CargoCapacity`: hold
	 * capacity of one ship in cargo units, scaled by the player's
	 * cargo tech.
	 */
	cargoCapacity(input: CargoCapacityInput): number;

	/**
	 * carryingMass wraps `pkg/calc/ship.go.CarryingMass`: mass of a
	 * payload of `load` cargo units at the player's cargo tech. Used
	 * by the ship-class designer to derive full-load mass from
	 * cargoCapacity.
	 */
	carryingMass(input: CarryingMassInput): number;

	/**
	 * blockUpgradeCost wraps `pkg/calc/ship.go.BlockUpgradeCost`:
	 * production cost of moving one ship block from currentTech to
	 * targetTech, scaled by the block mass and a constant 10. Returns
	 * 0 when blockMass is zero or targetTech is not above currentTech.
	 * Phase 20's ship-group inspector calls this once per block
	 * (drive, weapons, shields, cargo) to render the modernize cost
	 * preview.
	 */
	blockUpgradeCost(input: BlockUpgradeCostInput): number;

	/**
	 * effectiveAttack wraps `pkg/calc/ship.go.EffectiveAttack`: combat
	 * attack power = weapons block × weapons tech.
	 */
	effectiveAttack(input: EffectiveAttackInput): number;

	/**
	 * effectiveDefence wraps `pkg/calc/ship.go.EffectiveDefence`: combat
	 * defence power = shields × shields tech, normalised by the cube root
	 * of full mass; zero when fullMass ≤ 0.
	 */
	effectiveDefence(input: EffectiveDefenceInput): number;

	/**
	 * bombingPower wraps `pkg/calc/ship.go.BombingPower`: planet-bombing
	 * power of `number` ships. The calculator passes number = 1 for a
	 * per-ship reading.
	 */
	bombingPower(input: BombingPowerInput): number;

	/**
	 * shipBuildCost wraps `pkg/calc/planet.go.ShipBuildCost`: the per-turn
	 * production cost of one ship of empty mass shipMass on a planet
	 * holding `material` at the `resources` rating.
	 */
	shipBuildCost(input: ShipBuildCostInput): number;

	/**
	 * produceShipsInTurn wraps `pkg/calc/planet.go.ProduceShipsInTurn`:
	 * one turn of ship production, returning whole ships completed, the
	 * material left, the production spent on the next (incomplete) ship,
	 * and that ship's progress fraction. Matches the engine's per-turn
	 * build loop.
	 */
	produceShipsInTurn(input: ProduceShipsInTurnInput): ProduceShipsInTurnResult;

	/**
	 * weaponsForAttack wraps `pkg/calc/solve.go.WeaponsForAttack`: the
	 * weapons block that yields the target attack power, or null when the
	 * request is infeasible.
	 */
	weaponsForAttack(input: WeaponsForAttackInput): number | null;

	/**
	 * driveForSpeed wraps `pkg/calc/solve.go.DriveForSpeed`: the drive
	 * block that yields the target speed given the rest of the ship's
	 * mass, or null when the target is at/above the stripped-hull ceiling.
	 */
	driveForSpeed(input: DriveForSpeedInput): number | null;

	/**
	 * shieldsForDefence wraps `pkg/calc/solve.go.ShieldsForDefence`: the
	 * shields block that yields the target defence given the rest of the
	 * ship's mass (found by bisection), or null when infeasible.
	 */
	shieldsForDefence(input: ShieldsForDefenceInput): number | null;

	/**
	 * cargoForEmptyMass wraps `pkg/calc/solve.go.CargoForEmptyMass`: the
	 * cargo block that brings empty mass to the target, or null when the
	 * target is below the fixed block mass.
	 */
	cargoForEmptyMass(input: CargoForEmptyMassInput): number | null;

	/**
	 * loadForFullMass wraps `pkg/calc/solve.go.LoadForFullMass`: the cargo
	 * load that brings full mass to the target, or null when the target is
	 * below the empty mass.
	 */
	loadForFullMass(input: LoadForFullMassInput): number | null;

	/**
	 * ceil3 wraps `pkg/calc/number.go.Ceil3`: round a value up to three
	 * decimal places, for display so a computed result is never shown
	 * lower than it is.
	 */
	ceil3(input: Ceil3Input): number;
}

export type CoreLoader = () => Promise<Core>;

import { loadWasmCore } from "./wasm";

/**
 * loadCore resolves the Core implementation appropriate for the current
 * build target. Phase 5 ships only the WASM adapter; later phases plug
 * `WailsCore` and `CapacitorCore` here behind a build-time selector.
 */
export const loadCore: CoreLoader = loadWasmCore;
