// Copyright 2026 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import * as i18n from '../../core/i18n/i18n.js';
import type * as Platform from '../../core/platform/platform.js';
import type * as SDK from '../../core/sdk/sdk.js';
import type * as Protocol from '../../generated/protocol.js';
import * as Bindings from '../../models/bindings/bindings.js';
import type * as IssuesManager from '../../models/issues_manager/issues_manager.js';
import * as Components from '../../ui/legacy/components/utils/utils.js';
import * as UI from '../../ui/legacy/legacy.js';
import {Directives, html, type LitTemplate, nothing, render} from '../../ui/lit/lit.js';

import {AffectedResourcesView} from './AffectedResourcesView.js';

const UIStrings = {
  /**
   * @description Label for number of affected resources indication in issue view
   */
  nViolations: '{n, plural, =1 {# violation} other {# violations}}',
  /**
   * @description Title for the API column in the Selective Permissions Intervention affected resources list
   */
  api: 'API',
  /**
   * @description Title for the Script column in the Selective Permissions Intervention affected resources list
   */
  script: 'Script',
  /**
   * @description Title for the Ad Ancestry column in the Selective Permissions Intervention affected resources list
   */
  adAncestry: 'Ad Ancestry',
  /**
   * @description Text for unknown value
   */
  unknown: 'unknown',
  /**
   * @description Text for loading state
   */
  loading: 'loading…',
} as const;
const str_ = i18n.i18n.registerUIStrings('panels/issues/AffectedSelectivePermissionsInterventionView.ts', UIStrings);
const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
const {widget} = UI.Widget;

export class AffectedSelectivePermissionsInterventionView extends AffectedResourcesView {
  readonly #linkifier = new Components.Linkifier.Linkifier();

  protected getResourceNameWithCount(count: number): string {
    return i18nString(UIStrings.nViolations, {n: count});
  }

  #render(): void {
    const issues = Array.from(this.issue.getSelectivePermissionsInterventionIssues());
    // eslint-disable-next-line @devtools/no-lit-render-outside-of-view
    render(
        html`
      <tr>
        <td class="affected-resource-header">${i18nString(UIStrings.api)}</td>
        <td class="affected-resource-header">${i18nString(UIStrings.script)}</td>
        <td class="affected-resource-header">${i18nString(UIStrings.adAncestry)}</td>
      </tr>
      ${issues.map(issue => this.#renderDetail(issue))}
    `,
        this.affectedResources, {host: this});
    this.updateAffectedResourceCount(issues.length);
  }

  #renderDetail(issue: IssuesManager.SelectivePermissionsInterventionIssue.SelectivePermissionsInterventionIssue):
      LitTemplate {
    const details = issue.details();
    const issuesModel = issue.model();

    const stackTracePromise = (details.stackTrace && issuesModel) ?
        this.#resolveStackTrace(details.stackTrace, issuesModel) :
        Promise.resolve(html`<span>${i18nString(UIStrings.unknown)}</span>`);

    const target = issuesModel ? issuesModel.target() : null;

    return html`
      <tr class="affected-resource-directive">
        <td>${details.apiName}</td>
        <td>${Directives.until(stackTracePromise, html`<span>${i18nString(UIStrings.loading)}</span>`)}</td>
        <td class="affected-resource-cell">
          <div class="ad-ancestry-list">
            ${(details.adAncestry?.ancestryChain || []).map(script => {
      const link =
          this.#linkifier.linkifyScriptLocation(target, script.scriptId, '' as Platform.DevToolsPath.UrlString, 0);
      return html`<div>${link}</div>`;
    })}
            ${
        details.adAncestry?.rootScriptFilterlistRule ?
            html`<div>Rule: ${details.adAncestry.rootScriptFilterlistRule}</div>` :
            nothing}
          </div>
        </td>
      </tr>
    `;
  }

  async #resolveStackTrace(stackTrace: Protocol.Runtime.StackTrace, issuesModel: SDK.IssuesModel.IssuesModel):
      Promise<LitTemplate> {
    const debuggerWorkspaceBinding = Bindings.DebuggerWorkspaceBinding.DebuggerWorkspaceBinding.instance();
    const stackTraceTranslated =
        await debuggerWorkspaceBinding.createStackTraceFromProtocolRuntime(stackTrace, issuesModel.target());
    return html`${widget(Components.JSPresentationUtils.StackTracePreviewContent, {
      stackTrace: stackTraceTranslated,
      options: {expandable: true},
    })}`;
  }

  update(): void {
    this.requestResolver.clear();
    this.#linkifier.reset();
    this.#render();
  }
}
