/**
 * Copyright IBM Corp. 2016, 2025
 * SPDX-License-Identifier: BUSL-1.1
 */

import Component from '@glimmer/component';
import { action } from '@ember/object';
import { service } from '@ember/service';
import { tracked } from '@glimmer/tracking';
import sortedVersions from 'kv/helpers/sorted-versions';
import getCurrentSecret from 'kv/helpers/current-secret';
import isDeleted from 'kv/helpers/is-deleted';

/**
 * @module KvSecretMetadataVersionDiff renders the version diff comparison
 * <Page::Secret::Metadata::VersionDiff
 *  @metadata={{this.model.metadata}}
 *  @path={{this.model.path}}
 *  @backend={{this.model.backend}}
 *  @breadcrumbs={{this.breadcrumbs}}
 * />
 *
 * @param {object} metadata - secret metadata
 * @param {string} path - path to request secret data for selected version
 * @param {string} backend - kv secret mount to make network request
 * @param {array} breadcrumbs - Array to generate breadcrumbs, passed to the page header component
 */

/* eslint-disable no-undef */
export default class KvSecretMetadataVersionDiff extends Component {
  @service api;

  @tracked leftVersion;
  @tracked rightVersion;
  @tracked visualDiff;
  @tracked statesMatch = false;

  constructor() {
    super(...arguments);

    // initialize with most recently (before current), active version on left
    const olderVersions = this.sortedVersions.slice(1);
    const recentlyActive = olderVersions.find((v) => !v.destroyed && !isDeleted(v.deletion_time));
    this.leftVersion = Number(recentlyActive?.version);
    this.rightVersion = this.args.metadata.current_version;

    // this diff is from older to newer (current) secret data
    this.createVisualDiff();
  }

  get sortedVersions() {
    return sortedVersions(this.args.metadata.versions);
  }

  // this can only be true on initialization if the current version is inactive
  // selecting a deleted/destroyed version is otherwise disabled
  get deactivatedState() {
    const { current_version } = this.args.metadata;
    const currentSecret = getCurrentSecret(this.args.metadata);
    return this.rightVersion === current_version && currentSecret.isDeactivated ? currentSecret.state : '';
  }

  @action
  handleSelect(side, version, actions) {
    this[side] = Number(version);
    actions.close();
    this.createVisualDiff();
  }

  async createVisualDiff() {
    const leftSecretData = await this.fetchSecretData(this.leftVersion);
    const rightSecretData = await this.fetchSecretData(this.rightVersion);
    const diffpatcher = jsondiffpatch.create({});
    const delta = diffpatcher.diff(leftSecretData, rightSecretData);

    this.statesMatch = !delta;
    this.visualDiff = delta
      ? htmlformatter.format(delta, leftSecretData)
      : JSON.stringify(rightSecretData, undefined, 2);
  }

  async fetchSecretData(version) {
    const { backend, path } = this.args;
    const initOverride = version ? (context) => this.api.addQueryParams(context, { version }) : undefined;
    try {
      const { data } = await this.api.secrets.kvV2Read(path, backend, initOverride);
      return data;
    } catch (e) {
      // capabilities checks are higher up the tree so this request should not fail
    }
  }
}
