import {
  ChangeDetectionStrategy,
  Component,
  computed,
  signal,
  TemplateRef,
} from '@angular/core';
import { NgTemplateOutlet } from '@angular/common';

/**
 * Component to display a tooltip.
 * The tooltip can display a simple string title, a string content, or a complex TemplateRef content.
 */
@Component({
  selector: 'ui-tooltip',
  templateUrl: './tooltip.component.html',
  changeDetection: ChangeDetectionStrategy.OnPush,
  host: {
    '[class]': 'tooltipClasses()',
  },
  standalone: true,
  imports: [NgTemplateOutlet],
})
export class TooltipComponent {
  /**
   * The title of the tooltip. Can be a simple string.
   */
  title = signal<string | undefined>(undefined);

  /**
   * The content of the tooltip.
   * This can be a simple string or a TemplateRef for more complex content.
   */
  content = signal<string | TemplateRef<unknown> | undefined>(undefined);

  /**
   * The visual variant of the tooltip.
   */
  variant = signal<'default' | 'warning' | 'success'>('default');

  /**
   * Whether the tooltip is in the leaving state (playing exit animation).
   */
  leaving = signal(false);

  /**
   * Computed classes for the tooltip based on variant and leaving state.
   */
  tooltipClasses = computed(() => {
    const classes = ['ui-tooltip'];
    const v = this.variant();
    if (v === 'warning') {
      classes.push('ui-tooltip--warning');
    } else if (v === 'success') {
      classes.push('ui-tooltip--success');
    }
    if (this.leaving()) {
      classes.push('ui-tooltip--leaving');
    }
    return classes.join(' ');
  });

  /**
   * Returns the content as a TemplateRef if it is one.
   * Used to render template content in the tooltip.
   * @returns The TemplateRef if content is a TemplateRef, otherwise undefined.
   */
  template() {
    const content = this.content();
    if (this.isTemplateRef(content)) {
      return content;
    }
    return undefined;
  }

  /**
   * Returns the content as a string if it is one.
   * Used to render simple text content in the tooltip.
   * @returns The string content if content is a string, otherwise undefined.
   */
  text() {
    const content = this.content();
    if (typeof content === 'string') {
      return content;
    }
    return undefined;
  }

  /**
   * Type guard to check if the provided content is a TemplateRef.
   * @param content The content to check, which can be a string, TemplateRef, or undefined.
   * @returns True if the content is an instance of TemplateRef, false otherwise.
   */
  isTemplateRef(
    content: string | TemplateRef<unknown> | undefined,
  ): content is TemplateRef<unknown> {
    return content instanceof TemplateRef;
  }
}
