import { Injectable } from '@angular/core';
import { Observable, map, shareReplay } from 'rxjs';
import { WidgetConfig, SectionConfig } from '../../shared/models/config';
import { ConfigService } from '../../core/config/config.service';
import { RuntimeDiagnosticsService } from '../../core/runtime/runtime-diagnostics.service';
import { UnknownWidgetComponent } from '../../widgets/ui/unknown-widget.component';
import { ResolvedWidget } from '../../widgets/contracts/widget-component.contract';
import { DataSourceResolverService } from '../../widgets/resolvers/data-source-resolver.service';
import { WidgetRegistryService } from '../../widgets/registry/widget-registry.service';

@Injectable({ providedIn: 'root' })
export class WidgetHostService {
  private readonly resolvedWidgets = new Map<string, Observable<ResolvedWidget>>();
  private readonly loggedUnknownWidgets = new Set<string>();

  constructor(
    private readonly registry: WidgetRegistryService,
    private readonly dataSourceResolver: DataSourceResolverService,
    private readonly diagnostics: RuntimeDiagnosticsService,
    private readonly configService: ConfigService
  ) {}

  resolveWidget(widget: WidgetConfig, section: SectionConfig, pageId: string): Observable<ResolvedWidget> {
    const cacheKey = `${pageId}:${section.id}:${widget.id}`;
    const cached = this.resolvedWidgets.get(cacheKey);
    if (cached) {
      return cached;
    }

    const registered = this.registry.resolve(widget.type, widget.version);
    const resolved$ = this.dataSourceResolver.resolve(widget, section).pipe(
      map((data) => {
        if (!registered) {
          this.logUnknownWidget(pageId, section.id, widget);

          return {
            type: widget.type,
            version: widget.version,
            component: UnknownWidgetComponent,
            section,
            data
          };
        }

        return {
          type: registered.type,
          version: registered.version,
          component: registered.component,
          section,
          data
        };
      }),
      shareReplay({ bufferSize: 1, refCount: true })
    );

    this.resolvedWidgets.set(cacheKey, resolved$);
    return resolved$;
  }

  private logUnknownWidget(pageId: string, sectionId: string, widget: WidgetConfig): void {
    const diagnosticKey = `${pageId}:${sectionId}:${widget.id}`;
    if (this.loggedUnknownWidgets.has(diagnosticKey)) {
      return;
    }

    this.loggedUnknownWidgets.add(diagnosticKey);

    const tenantId = this.configService.getBootstrapSnapshot()?.tenant.id ?? 'unknown';
    this.diagnostics.logUnknownWidget({
      tenant: tenantId,
      page: pageId,
      section: sectionId,
      widget: `${widget.type}@${widget.version}`,
      reason: 'not_registered_in_widget_registry'
    });
  }
}
