import { mockGetAirplaneParams } from './AircraftService';
import { getWeatherData } from './WeatherService';
import type { ThrustWattEntry } from '../types';

export const calculateBatteryPercentUsed = async (
  groundSpeed: number,
  time: number,
  position: { lat: number; lon: number },
): Promise<number> => {
  const airplaneParams = await mockGetAirplaneParams();
  const weatherData = await getWeatherData(position.lat, position.lon);

  const airDensity = 1.05;
  const groundSpeedInMs = groundSpeed / 3.6;

  const headwind = (weatherData?.windSpeed ?? 0) * Math.cos(Math.PI / 180 * (weatherData?.windAngle ?? 0));
  const effectiveAirspeed = groundSpeedInMs + headwind;

  const drag = dragForce(effectiveAirspeed, airDensity, airplaneParams.dragCoefficient, airplaneParams.frontalArea);

  const effectivePowerConsumption = calcThrust(drag, airplaneParams.thrustWatts, airplaneParams.propellerEfficiency, airplaneParams.weight);

  const energyUsed = effectivePowerConsumption * time;
  const batteryPercentUsed = (energyUsed / airplaneParams.batteryCapacity) * 100;

  return Math.min(batteryPercentUsed, 100);
};

function dragForce(airspeed: number, airDensity: number, dragCoefficient: number, frontalArea: number): number {
  return 0.5 * airDensity * (airspeed ** 2) * dragCoefficient * frontalArea;
}

function calcThrust(
  drag: number,
  thrustWatts: ThrustWattEntry[],
  propellerEfficiency: number,
  weight: number,
): number {
  let closest: ThrustWattEntry | null = null;
  const adjustedDrag = drag + (weight * 9.8 * 0.05);
  for (const item of thrustWatts) {
    const thrustInNewtons = (item.thrust / 1000) * 9.8;
    if (thrustInNewtons > adjustedDrag) {
      if (!closest || thrustInNewtons < (closest.thrust / 1000) * 9.8) {
        closest = item;
      }
    }
  }
  const watts = closest ? closest.watts : thrustWatts[thrustWatts.length - 1].watts;
  return watts / propellerEfficiency;
}
