package cloud.nstart.terravault.ordinis.readapi.spatial;

/**
 * Bounding box (west-south-east-north) для spatial filtering. Парсится
 * из query param {@code ?bbox=west,south,east,north} (4 floats).
 *
 * <p>Координаты в SRID 4326 (WGS84): longitude, latitude. Альтум-задача
 * (заказ съёмки) использует именно этот формат.
 *
 * <p>Validation:
 * <ul>
 *   <li>4 числа, через запятую</li>
 *   <li>longitude ∈ [-180, 180]</li>
 *   <li>latitude ∈ [-90, 90]</li>
 *   <li>west ≤ east, south ≤ north (no anti-meridian crossing в v1)</li>
 * </ul>
 */
public record BoundingBox(double west, double south, double east, double north) {

  /**
   * Парсит {@code "west,south,east,north"}. На любую ошибку формата
   * бросает {@link IllegalArgumentException} с понятным message.
   */
  public static BoundingBox parse(String csv) {
    if (csv == null || csv.isBlank()) {
      throw new IllegalArgumentException("bbox is empty");
    }
    String[] parts = csv.split(",");
    if (parts.length != 4) {
      throw new IllegalArgumentException(
          "bbox must be 4 comma-separated numbers (west,south,east,north), got " + parts.length);
    }
    double[] coords = new double[4];
    for (int i = 0; i < 4; i++) {
      try {
        coords[i] = Double.parseDouble(parts[i].trim());
      } catch (NumberFormatException e) {
        throw new IllegalArgumentException("bbox component #" + (i + 1) + " is not a number: " + parts[i]);
      }
    }
    BoundingBox bbox = new BoundingBox(coords[0], coords[1], coords[2], coords[3]);
    bbox.validate();
    return bbox;
  }

  public void validate() {
    if (west < -180 || west > 180) {
      throw new IllegalArgumentException("west longitude " + west + " out of range [-180, 180]");
    }
    if (east < -180 || east > 180) {
      throw new IllegalArgumentException("east longitude " + east + " out of range [-180, 180]");
    }
    if (south < -90 || south > 90) {
      throw new IllegalArgumentException("south latitude " + south + " out of range [-90, 90]");
    }
    if (north < -90 || north > 90) {
      throw new IllegalArgumentException("north latitude " + north + " out of range [-90, 90]");
    }
    if (west > east) {
      throw new IllegalArgumentException(
          "west " + west + " > east " + east + " (anti-meridian crossing not supported in v1)");
    }
    if (south > north) {
      throw new IllegalArgumentException("south " + south + " > north " + north);
    }
  }

  /** Площадь в квадратных градусах (грубая, не sphere). Для UI rendering / debugging. */
  public double areaInDegreesSquared() {
    return (east - west) * (north - south);
  }
}
