/* eslint-disable @typescript-eslint/member-ordering */
import {
  Component,
  HostListener,
  computed,
  inject,
  output
} from '@angular/core';
import { CommonModule } from '@angular/common';
import { NgIcon, provideIcons } from '@ng-icons/core';
import { lucideX } from '@ng-icons/lucide';
import type { PluginApiActionContribution } from '../../domain/models/plugin-api.models';
import { PluginClientApiService } from '../../application/services/plugin-client-api.service';
import { PluginLoggerService } from '../../application/services/plugin-logger.service';
import { PluginRegistryService } from '../../application/services/plugin-registry.service';
import type { PluginUiContributionRecord } from '../../application/services/plugin-ui-registry.service';
import { PluginUiRegistryService } from '../../application/services/plugin-ui-registry.service';
import { ThemeNodeDirective } from '../../../theme';
import { APP_TRANSLATE_IMPORTS } from '../../../../core/i18n';

@Component({
  selector: 'app-plugin-action-menu',
  standalone: true,
  imports: [
    CommonModule,
    NgIcon,
    ThemeNodeDirective,
    ...APP_TRANSLATE_IMPORTS
  ],
  viewProviders: [provideIcons({ lucideX })],
  templateUrl: './plugin-action-menu.component.html'
})
export class PluginActionMenuComponent {
  readonly closed = output<undefined>();

  private readonly logger = inject(PluginLoggerService);
  private readonly pluginApi = inject(PluginClientApiService);
  private readonly pluginRegistry = inject(PluginRegistryService);
  private readonly pluginUi = inject(PluginUiRegistryService);

  readonly actions = computed(() => [...this.pluginUi.toolbarActionRecords()]
    .sort((left, right) => this.sortActionRecords(left, right)));

  @HostListener('document:keydown.escape')
  close(): void {
    this.closed.emit(undefined);
  }

  runAction(record: PluginUiContributionRecord<PluginApiActionContribution>): void {
    this.closed.emit(undefined);

    void Promise.resolve()
      .then(() => record.contribution.run(this.pluginApi.createActionContext('toolbarAction')))
      .catch((error: unknown) => this.logger.error(record.pluginId, 'Toolbar action failed', error));
  }

  pluginName(pluginId: string): string {
    return this.pluginRegistry.find(pluginId)?.manifest.title ?? pluginId;
  }

  actionTitle(record: PluginUiContributionRecord<PluginApiActionContribution>): string {
    return `${this.pluginName(record.pluginId)}: ${record.contribution.label}`;
  }

  iconText(record: PluginUiContributionRecord<PluginApiActionContribution>): string {
    const icon = record.contribution.icon?.trim();

    if (icon) {
      return icon;
    }

    return createInitials(this.pluginName(record.pluginId), record.contribution.label);
  }

  isImageIcon(record: PluginUiContributionRecord<PluginApiActionContribution>): boolean {
    const icon = record.contribution.icon?.trim() ?? '';

    return icon.startsWith('http://')
      || icon.startsWith('https://')
      || icon.startsWith('data:image/')
      || icon.startsWith('blob:');
  }

  private sortActionRecords(
    left: PluginUiContributionRecord<PluginApiActionContribution>,
    right: PluginUiContributionRecord<PluginApiActionContribution>
  ): number {
    const leftPlugin = this.pluginName(left.pluginId);
    const rightPlugin = this.pluginName(right.pluginId);
    const pluginCompare = leftPlugin.localeCompare(rightPlugin);

    if (pluginCompare !== 0) {
      return pluginCompare;
    }

    return left.contribution.label.localeCompare(right.contribution.label);
  }
}

function createInitials(pluginName: string, actionLabel: string): string {
  const words = `${pluginName} ${actionLabel}`
    .split(/[^a-zA-Z0-9]+/)
    .filter((word) => word.length > 0);

  if (words.length === 0) {
    return 'PL';
  }

  return words
    .slice(0, 2)
    .map((word) => word.charAt(0).toUpperCase())
    .join('');
}
