/* eslint-disable @typescript-eslint/no-namespace */
import { IssueUrlEnhancer } from '@app/event-emitter/issue-enhancers/issue-url-enhancer';
import { TagStyledEnhancerNs } from '@app/event-emitter/issue-enhancers/tag-styled-enhancer';
import { TimePassedHighlightEnhancer } from '@app/event-emitter/issue-enhancers/time-passed-highlight-enhancer';
import {
  IssuesService,
  IssuesServiceNs,
} from '@app/event-emitter/issues/issues.service';
import {
  TreeIssuesStore,
  TreeIssuesStoreNs,
} from '@app/event-emitter/utils/tree-issues-store';
import { Injectable } from '@nestjs/common';
import * as PriorityStylesEnhancerNs from '@app/event-emitter/issue-enhancers/priority-styles-enhancer';
import { WidgetDataLoaderInterface } from '../widget-data-loader-interface';
import { AppError, Result, success } from '@app/event-emitter/utils/result';

export namespace RootIssueSubTreesWidgetNs {
  export namespace Models {
    export type Params = {
      rootIssueId: number;
      parentsAsGroups?: boolean;
      groups?: GroupCfg;
      statuses: string[];
    } & TagStyledEnhancerNs.ConfigWithTagsStyles;

    export type GroupCfg = {
      fromIssues: Group[];
      fromIssuesIncluded: boolean;
      showOthers: boolean;
    };

    export type Group = {
      name: string;
      issueId: number;
    };
  }
}

type Params = RootIssueSubTreesWidgetNs.Models.Params;

@Injectable()
export class RootIssueSubTreesWidgetDataLoaderService
  implements WidgetDataLoaderInterface<Params, any, any>
{
  private issuesLoader: IssuesServiceNs.IssuesLoader;

  constructor(
    private issuesService: IssuesService,
    private timePassedHighlightEnhancer: TimePassedHighlightEnhancer,
    private issueUrlEnhancer: IssueUrlEnhancer,
  ) {
    this.issuesLoader = this.issuesService.createDynamicIssuesLoader();
  }

  isMyConfig(): boolean {
    return true;
  }

  async load(widgetParams: Params): Promise<Result<any, AppError>> {
    const treeStore = new TreeIssuesStore();
    const rootIssue = await this.issuesService.getIssue(
      widgetParams.rootIssueId,
    );
    treeStore.setRootIssue(rootIssue);
    await treeStore.fillData(this.issuesLoader);
    await treeStore.enhanceIssues([
      this.timePassedHighlightEnhancer,
      this.issueUrlEnhancer,
      TagStyledEnhancerNs.CreateTagStyledEnhancerForConfig(widgetParams),
      PriorityStylesEnhancerNs.CreatePriorityStylesEnhancer(widgetParams),
    ]);
    let stories: TreeIssuesStoreNs.Models.GetFlatStories.Result;
    if (widgetParams.parentsAsGroups) {
      stories = treeStore.getFlatStoriesByParents();
    } else if (widgetParams.groups) {
      const fromIssues = widgetParams.groups.fromIssues.map((g) => g.issueId);
      stories = treeStore.getFlatStories(
        fromIssues,
        widgetParams.groups.fromIssuesIncluded,
        widgetParams.groups.showOthers,
      );
      for (let i = 0; i < stories.length; i++) {
        const store = stories[i];
        const fromIssueInfo = widgetParams.groups.fromIssues.find((i) => {
          return i.issueId == store.metainfo?.rootIssue?.id;
        });
        if (fromIssueInfo) {
          store.metainfo.title = `${fromIssueInfo.name}: ${store.metainfo.title}`;
        }
      }
    }
    const res = stories.map((s) => {
      return {
        data: s.store.groupByStatus(widgetParams.statuses),
        metainfo: s.metainfo,
      };
    });
    return success(res);
  }
}
