package cloud.nstart.terravault.ordinis.restapi.web;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.info.BuildProperties;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.time.Instant;
import java.util.Optional;

/**
 * {@code GET /api/v1/version} — экспонирует server build identity для UI
 * update-detection banner.
 *
 * <p>Frontend (admin-ui) bundle'ит свой commit SHA в build-time через Vite
 * {@code define.__APP_COMMIT__}. Periodic poll этого endpoint'а сравнивает
 * server commit vs client commit. Mismatch → "Доступна новая версия" banner с
 * CTA {@code Обновить} (window.location.reload).
 *
 * <p>Source данных:
 * <ul>
 *   <li>{@code BuildProperties} bean создаётся Spring Boot когда есть
 *       {@code META-INF/build-info.properties} (генерируется
 *       spring-boot-maven-plugin {@code build-info} goal в ordinis-app pom).</li>
 *   <li>Дополнительные {@code commit}, {@code branch}, {@code tag}
 *       resolved из CI env vars (см. additionalProperties в plugin config).</li>
 * </ul>
 *
 * <p>Если build-info.properties отсутствует (e.g., запуск в IDE без mvn package)
 * — возвращает sensible defaults чтобы UI не падал.
 *
 * <p>Public endpoint — auth НЕ required (нужен на login screen чтобы клиент
 * сразу знал stale ли его bundle).
 */
@RestController
@RequestMapping("/api/v1/version")
public class VersionController {

  private final Optional<BuildProperties> buildProps;

  // BuildProperties может отсутствовать в dev — оптимально через Optional.
  public VersionController(@Autowired(required = false) BuildProperties buildProps) {
    this.buildProps = Optional.ofNullable(buildProps);
  }

  @GetMapping(produces = MediaType.APPLICATION_JSON_VALUE)
  public VersionInfo current() {
    return buildProps.map(b -> new VersionInfo(
        b.getVersion(),
        Optional.ofNullable(b.get("commit")).orElse("unknown"),
        Optional.ofNullable(b.get("branch")).orElse(""),
        Optional.ofNullable(b.get("tag")).orElse(""),
        b.getTime() != null ? b.getTime().toString() : ""
    )).orElseGet(() -> new VersionInfo(
        "0.0.0-dev",
        "unknown",
        "",
        "",
        Instant.now().toString()
    ));
  }

  /**
   * Stable JSON shape для UI client.
   *
   * @param version Maven {@code project.version} (e.g. "0.1.0-SNAPSHOT" или "1.1.0")
   * @param commit short git SHA (e.g. "07c5ca0") — primary update detection key
   * @param branch git branch (e.g. "main"), empty в tag builds
   * @param tag git tag if applicable (e.g. "v1.1.0"), empty в branch builds
   * @param builtAt ISO-8601 instant
   */
  public record VersionInfo(
      String version,
      String commit,
      String branch,
      String tag,
      String builtAt
  ) {}
}
