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

import cloud.nstart.terravault.ordinis.restapi.service.ChangelogService;
import cloud.nstart.terravault.ordinis.restapi.service.SnapshotsService;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

/**
 * Per-dictionary history / time-travel endpoints для admin-UI:
 * <ul>
 *   <li>{@code GET /dictionaries/{name}/changelog} — schema versions timeline</li>
 *   <li>{@code GET /dictionaries/{name}/snapshots} — record-change buckets для TimeTravel slider</li>
 * </ul>
 *
 * <p>Errors:
 * <ul>
 *   <li>404 {@code dictionary_not_found} — dict не существует или не виден
 *       caller'у (одинаковая ошибка чтобы не leak'ало existence).</li>
 *   <li>400 {@code invalid_granularity} — snapshots granularity не из
 *       {hour, day, week}.</li>
 *   <li>400 {@code invalid_window} — from >= to.</li>
 * </ul>
 */
@RestController
@RequestMapping("/api/v1/dictionaries")
public class DictionaryChangelogController {

  private final ChangelogService changelogService;
  private final SnapshotsService snapshotsService;

  public DictionaryChangelogController(
      ChangelogService changelogService,
      SnapshotsService snapshotsService) {
    this.changelogService = changelogService;
    this.snapshotsService = snapshotsService;
  }

  /**
   * @param name dict business name
   * @param limit max entries (1..200, default 50). Pagination через cursor
   *              сейчас не нужен — типичный dict 5-30 versions. Cursor
   *              может быть добавлен без breaking change позже.
   */
  @GetMapping("/{name}/changelog")
  public ChangelogService.ChangelogResponse changelog(
      @PathVariable String name,
      @RequestParam(defaultValue = "50") int limit) {
    return changelogService.findChangelog(name, limit);
  }

  /**
   * Full diff payload для конкретной changelog entry (для side-by-side
   * render'а в History tab / TimeTravel preview). Возвращает {@code before}
   * и {@code after} schema JsonNodes плюс summary diff.
   *
   * <p>404 {@code changelog_entry_not_found} если:
   * <ul>
   *   <li>id не существует в audit_log</li>
   *   <li>entry принадлежит другому dict'у (no leak existence)</li>
   *   <li>entry не schema timeline event (record-level / unrelated)</li>
   * </ul>
   *
   * @param entryId audit_log.id из {@link ChangelogService.ChangelogEntry#id()}
   */
  @GetMapping("/{name}/changelog/{entryId}/diff")
  public ChangelogService.ChangelogDiff changelogDiff(
      @PathVariable String name,
      @PathVariable Long entryId) {
    return changelogService.findEntryDiff(name, entryId);
  }

  /**
   * Snapshot points (record-change buckets) для TimeTravel slider.
   *
   * @param name dict business name
   * @param from ISO datetime window start. Default: now - 30d
   * @param to   ISO datetime window end. Default: now
   * @param granularity bucket size — {@code hour} / {@code day} / {@code week}.
   *                    Default: {@code day}.
   */
  @GetMapping("/{name}/snapshots")
  public SnapshotsService.SnapshotsResponse snapshots(
      @PathVariable String name,
      @RequestParam(required = false)
      @org.springframework.format.annotation.DateTimeFormat(iso = org.springframework.format.annotation.DateTimeFormat.ISO.DATE_TIME)
      java.time.OffsetDateTime from,
      @RequestParam(required = false)
      @org.springframework.format.annotation.DateTimeFormat(iso = org.springframework.format.annotation.DateTimeFormat.ISO.DATE_TIME)
      java.time.OffsetDateTime to,
      @RequestParam(defaultValue = "day") String granularity) {
    return snapshotsService.findSnapshots(name, from, to, granularity);
  }
}
