import {
  ChangeDetectionStrategy,
  Component,
  computed,
  effect,
  inject,
  input,
  untracked,
  ViewEncapsulation,
} from '@angular/core';
import { ReturnTaskListItemComponent } from './return-task-list-item/return-task-list-item.component';
import {
  PrintTolinoReturnReceiptService,
  QueryTokenInput,
  ReceiptItemTaskListItem,
  ReturnTaskListService,
  ReturnTaskListStore,
  TaskActionType,
  TaskActionTypeType,
} from '@isa/oms/data-access';
import { IconButtonComponent } from '@isa/ui/buttons';
import { firstValueFrom } from 'rxjs';
import { injectTabId } from '@isa/core/tabs';
import { logger, provideLoggerContext } from '@isa/core/logging';

// TODO: Komponente und logik benötigt review

@Component({
  selector: 'oms-shared-return-task-list',
  templateUrl: './return-task-list.component.html',
  styleUrl: './return-task-list.component.scss',
  changeDetection: ChangeDetectionStrategy.OnPush,
  standalone: true,
  imports: [ReturnTaskListItemComponent, IconButtonComponent],
  providers: [provideLoggerContext({ component: 'ReturnTaskListComponent' })],
  host: {
    '[class]': "['oms-shared-return-task-list', appearanceClass()]",
  },
  encapsulation: ViewEncapsulation.None,
})
export class ReturnTaskListComponent {
  appearance = input<'main' | 'review'>('main');
  #returnTaskListService = inject(ReturnTaskListService);
  #printTolinoReturnReceiptService = inject(PrintTolinoReturnReceiptService);
  #returnTaskListStore = inject(ReturnTaskListStore);
  #logger = logger();

  processId = injectTabId();

  appearanceClass = computed(
    () => `oms-shared-return-task-list__${this.appearance()}`,
  );

  taskListItems = computed(() => {
    const processId = this.processId();
    const appearance = this.appearance();

    if (!processId) {
      return [];
    }

    const taskListItems = this.#returnTaskListStore.entityMap()[processId].data;

    if (!taskListItems || taskListItems?.length === 0) {
      return [];
    }

    const filteredItems = taskListItems.filter((item) => {
      // Filter out completed tasks if the appearance is 'main'
      if (appearance === 'main' && item.completed) {
        return false;
      }

      return true;
    });

    // OrderBy: Show open tasks first
    return filteredItems.sort(
      (a, b) => Number(!!a.completed) - Number(!!b.completed),
    );
  });

  constructor() {
    effect(() => {
      const processId = this.processId();
      const appearance = this.appearance();
      if (processId) {
        const filter: Record<string, unknown> =
          appearance === 'review' ? { eob: true } : { completed: false };
        const queryToken: QueryTokenInput = {
          filter,
        };

        untracked(() =>
          this.#returnTaskListStore.fetchTaskListItems({
            processId,
            queryToken,
          }),
        );
      }
    });
  }

  async handleAction(action: TaskActionType) {
    if (
      action?.actions?.some(
        (keyValue) => keyValue.key === 'PRINT_TOLINO_RETURN_RECEIPT',
      ) &&
      action.receiptItemId
    ) {
      return await this.#printTolinoReturnReceiptService.printTolinoReturnReceipt(
        { returnReceiptId: action.receiptItemId },
      );
    }

    if (action.type === 'UNKNOWN' && !!action.updateTo) {
      return await this.updateTask({
        taskId: action.taskId,
        updateTo: action.updateTo,
      });
    }

    return await this.completeTask(action.taskId);
  }

  async completeTask(taskId: number) {
    try {
      const processId = this.processId();
      const result = await firstValueFrom(
        this.#returnTaskListService.completeTask(taskId),
      );

      // Update Store - List View
      if (result && processId) {
        this.#returnTaskListStore.updateTaskListItem({
          processId,
          taskListItem: result,
        });
      }
    } catch (error) {
      this.#logger.error('Error completing task', error, () => ({
        function: 'completeTask',
      }));
    }
  }

  async updateTask({
    taskId,
    updateTo,
  }: {
    taskId: number;
    updateTo: Exclude<TaskActionTypeType, 'UNKNOWN'>;
  }) {
    try {
      const processId = this.processId();
      const result = await firstValueFrom(
        this.#returnTaskListService.updateTaskType({
          type: updateTo,
          taskId,
        }),
      );

      // Update Store - List View
      if (result && processId) {
        this.#returnTaskListStore.updateTaskListItem({
          processId,
          taskListItem: result,
        });
      }
    } catch (error) {
      this.#logger.error('Error updating task', error, () => ({
        taskId,
        function: 'updateTask',
      }));
    }
  }
}
