import { CdkPortalOutlet, TemplatePortal } from '@angular/cdk/portal';
import { ChangeDetectionStrategy, Component, computed, inject, signal, TemplateRef, ViewContainerRef, output, } from '@angular/core';

@Component({
  selector: 'fast-tip-container',
  host: {
    '[class]': 'this.position()',
    '(mouseenter)': 'containerMouseEnter.emit()',
    '(mouseleave)': 'containerMouseLeave.emit()',
  },
  imports: [CdkPortalOutlet],
  template: `
<div role="tooltip" [class]="classes()" [id]="id()">
  @if (contentPortal()) {
  <ng-container [cdkPortalOutlet]="contentPortal()"></ng-container>
  } @else {
  {{ message() }}
  }
</div>
  `,
  styles: `
.tooltip {
  padding: 4px 6px;
  border-radius: 4px;
  font-size: 14px;
  transition: opacity 0.3s ease;
  position: relative;
  -webkit-touch-callout: none;    /* avoid iOS callout on long-press */
  touch-action: manipulation;     /* hint to reduce delays/gestures */
  max-height: min(600px, calc(100vh - 40px));
  overflow-y: auto;
}

/* Invisible padding on host to bridge the gap between trigger and tooltip */
:host {
  display: block;
  position: relative;
}

:host.top {
  padding-bottom: 6px;
  margin-bottom: -6px;
}

:host.bottom {
  padding-top: 6px;
  margin-top: -6px;
}

:host.left {
  padding-right: 6px;
  margin-right: -6px;
}

:host.right {
  padding-left: 6px;
  margin-left: -6px;
}

:host::after {
  content: '';
  position: absolute;
  width: 0;
  height: 0;
  border-style: solid;
  z-index: 1;
}

:host.top::after {
  top: calc(100% - 8px);
  left: 50%;
  transform: translateX(-50%);
  border-width: 8px 6px 0 6px;
  border-color: var(--color-inverse) transparent transparent transparent;
}

:host.right::after {
  top: 50%;
  left: 0;
  transform: translateY(-50%);
  border-width: 6px 8px 6px 0;
  border-color: transparent var(--color-inverse) transparent transparent;
}

:host.bottom::after {
  bottom: calc(100% - 8px);
  left: 50%;
  transform: translateX(-50%);
  border-width: 0 6px 8px 6px;
  border-color: transparent transparent var(--color-inverse) transparent;
}

:host.left::after {
  top: 50%;
  right: 0;
  transform: translateY(-50%);
  border-width: 6px 0 6px 8px;
  border-color: transparent transparent transparent var(--color-inverse);
}

.dark :host.top::after {
  border-color: var(--color-dark-inverse) transparent transparent transparent;
}

.dark :host.right::after {
  border-color: transparent var(--color-dark-inverse) transparent transparent;
}

.dark :host.bottom::after {
  border-color: transparent transparent var(--color-dark-inverse) transparent;
}

.dark :host.left::after {
  border-color: transparent transparent transparent var(--color-dark-inverse);
}
  `,
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class FastTipContainerComponent {
  message = signal<string>('');

  position = signal<string>('top');

  bg = signal<string>('opaque');

  pushTooltip = signal<boolean>(true);

  content = signal<TemplateRef<unknown> | undefined>(undefined);

  context = signal<unknown>(undefined);

  maxWidth = signal<number>(500);

  vf = inject(ViewContainerRef);

  id = signal<string>('');

  containerMouseEnter = output<void>();
  containerMouseLeave = output<void>();

  contentPortal = computed(() => {
    const content = this.content();
    const context = this.context();
    if (content) {
      // Spread the context if it's an object to make properties directly accessible
      const templateContext = context && typeof context === 'object'
        ? { $implicit: context, ...context as Record<string, unknown> }
        : { $implicit: context };
      return new TemplatePortal(content, this.vf, templateContext);
    }
    return;
  });

  classes = computed(() => {
    const classes = [] as string[];

    classes.push(
      'tooltip',
      this.position());

    switch (this.bg()) {
      case ('opaque'):
        classes.push('bg-inverse', 'text-inverse-foreground', 'dark:bg-dark-inverse', 'dark:text-dark-inverse-foreground');
        break;
      case ('standard'):
        classes.push('bg-base-white-1000', 'dark:bg-alt-gray-1000');
        break;
    }

    if (this.pushTooltip()) {
      const convertedWidth = Math.floor(this.maxWidth() / 4);
      const formattedWidth = 'max-w-' + convertedWidth;
      classes.push(formattedWidth);
    }

    return classes;
  });
}
