import { attr, customElement, GenesisElement, html, observable } from '@genesislcap/web-core';
import { agenticActivityBus } from '../../channel/ai-activity-bus';

const DEFAULT_MIN_SHOW_TIME = 600;

/**
 * Wrapper component that shows an `<ai-halo-overlay>` when the AI assistant
 * is executing one of the declared tool names.
 *
 * @example
 * ```html
 * <ai-activity-halo tools="search_trades">
 *   <trades-grid></trades-grid>
 * </ai-activity-halo>
 * ```
 *
 * @beta
 */
@customElement({
  name: 'ai-activity-halo',
  template: html`
    <div class="wrapper">
      <slot></slot>
      <ai-halo-overlay aria-hidden="true" ?active="${(x) => x.haloActive}"></ai-halo-overlay>
    </div>
  `,
  styles: `
    :host {
      display: contents;
    }
    .wrapper {
      position: relative;
      overflow: hidden;
      border-radius: inherit;
      height: 100%;
      width: 100%;
    }
  `,
})
export class AiActivityHalo extends GenesisElement {
  /** Comma-separated list of tool names this element reacts to. */
  @attr tools: string = '';

  /** Minimum time in ms the halo stays visible after activation. */
  @attr({ attribute: 'min-show-time', converter: { fromView: Number, toView: String } })
  minShowTime: number = DEFAULT_MIN_SHOW_TIME;

  /** @internal */
  @observable haloActive: boolean = false;

  private unsubBus?: () => void;
  private hideTimeout?: ReturnType<typeof setTimeout>;
  private startTime: number = 0;

  connectedCallback() {
    super.connectedCallback();
    const unsubStart = agenticActivityBus.subscribe('halo-start', ({ toolNames }) => {
      const myTools = this.tools
        .split(',')
        .map((t) => t.trim())
        .filter(Boolean);
      if (myTools.length === 0 || toolNames.some((name) => myTools.includes(name))) {
        this.activate();
      }
    });
    const unsubStop = agenticActivityBus.subscribe('halo-stop', () => {
      this.scheduleDeactivate();
    });
    this.unsubBus = () => {
      unsubStart();
      unsubStop();
    };
  }

  disconnectedCallback() {
    super.disconnectedCallback();
    this.unsubBus?.();
    this.unsubBus = undefined;
    if (this.hideTimeout !== undefined) {
      clearTimeout(this.hideTimeout);
      this.hideTimeout = undefined;
    }
  }

  private activate() {
    if (this.hideTimeout !== undefined) {
      clearTimeout(this.hideTimeout);
      this.hideTimeout = undefined;
    }
    this.startTime = Date.now();
    this.haloActive = true;
  }

  private scheduleDeactivate() {
    const elapsed = Date.now() - this.startTime;
    const remaining = this.minShowTime - elapsed;
    if (remaining <= 0) {
      this.haloActive = false;
    } else {
      this.hideTimeout = setTimeout(() => {
        this.haloActive = false;
        this.hideTimeout = undefined;
      }, remaining);
    }
  }
}
