import { Injectable, Logger } from '@nestjs/common';
import { DashboardsService } from './dashboards.service';
import * as DashboardModel from '../models/dashboard';
import { AppError, Result, createAppError, fail } from '../utils/result';
import { WidgetsCollectionService } from './widgets-collection.service';

export type WidgetWithData = {
  widgetId: string;
  data: any;
};

@Injectable()
export class DashboardsDataService {
  private logger = new Logger(DashboardsDataService.name);

  constructor(
    private dashboardsService: DashboardsService,
    private widgetsCollectionService: WidgetsCollectionService,
  ) {}

  async loadData(id: string): Promise<WidgetWithData[]> {
    const cfg = await this.dashboardsService.load(id);
    const results: WidgetWithData[] = [];
    let isSuccess = false;
    let counter = 0;
    if (!cfg?.widgets || cfg?.widgets?.length <= 0) {
      return results;
    }
    for (let i = 0; i < cfg.widgets.length; i++) {
      const widget = cfg.widgets[i];
      if (widget.collapsed) continue;
      const loadRes = await this.loadWidgetData(
        widget.type,
        widget.widgetParams,
        widget.dataLoaderParams,
        cfg,
        id,
        widget.id,
      );
      if (loadRes.result) {
        counter++;
        isSuccess = true;
        loadRes.result.widgetId = widget.id;
        results.push({ data: loadRes.result, widgetId: widget.id });
      }
    }
    if (!isSuccess && counter > 0) throw createAppError('CANNOT_LOAD_DATA');
    return results;
  }

  async loadDataForWidget(id: string, widgetId: string): Promise<any> {
    const cfg = await this.dashboardsService.load(id);
    const widget = cfg.widgets.find((widget) => {
      return widget.id == widgetId;
    });
    if (!widget) throw createAppError('WIDGET_NOT_FOUND');
    const loadRes = await this.loadWidgetData(
      widget.type,
      widget.widgetParams,
      widget.dataLoaderParams,
      cfg,
      id,
      widgetId,
    );
    if (loadRes.result) return loadRes.result;
    throw createAppError('CANNOT_LOAD_DATA');
  }

  async loadWidgetData(
    type: string,
    widgetParams: DashboardModel.WidgetParams,
    dataLoaderParams: DashboardModel.DataLoaderParams,
    dashboardParams: DashboardModel.Data,
    dashboardId: string,
    widgetId: string,
  ): Promise<Result<any, AppError>> {
    const widgetResult = this.widgetsCollectionService.getWidgetByType(type);
    if (widgetResult.error) return fail(createAppError(widgetResult.error));
    const widget = widgetResult.result;
    const renderResult = await widget.render(
      widgetParams,
      dataLoaderParams,
      dashboardParams,
      dashboardId,
      widgetId,
    );
    return renderResult;
  }
}
