import {
  ChangeDetectionStrategy,
  Component,
  computed,
  inject,
  OnInit,
  resource,
  signal,
} from '@angular/core';
import { isaActionSearch, isaOtherInfo } from '@isa/icons';
import { IconButtonComponent } from '@isa/ui/buttons';
import {
  UiSearchBarClearComponent,
  UiSearchBarComponent,
} from '@isa/ui/search-bar';
import { NgIcon, provideIcons } from '@ng-icons/core';
import { SearchItemToRemitComponent } from './search-item-to-remit.component';
import { FormsModule } from '@angular/forms';
import { DEFAULT_LIST_RESPONSE_ARGS_OF_ITEM } from './constants';
import {
  CatalougeSearchService,
  SearchByTermInput,
  Item,
} from '@isa/catalogue/data-access';
import {
  ListResponseArgs,
  createEscAbortControllerHelper,
} from '@isa/common/data-access';
import { SearchItemToRemitDialogComponent } from './search-item-to-remit-dialog.component';
import { CdkTrapFocus } from '@angular/cdk/a11y';
import { TooltipDirective } from '@isa/ui/tooltip';
import { createInStockResource } from './instock.resource';
import { calculateAvailableStock } from '@isa/remission/data-access';
import { EmptyStateComponent } from '@isa/ui/empty-state';
import { ScrollTopButtonComponent } from '@isa/utils/scroll-position';

@Component({
  selector: 'remi-search-item-to-remit-list',
  templateUrl: './search-item-to-remit-list.component.html',
  styleUrls: ['./search-item-to-remit-list.component.scss'],
  changeDetection: ChangeDetectionStrategy.OnPush,
  standalone: true,
  imports: [
    UiSearchBarClearComponent,
    UiSearchBarComponent,
    IconButtonComponent,
    FormsModule,
    SearchItemToRemitComponent,
    CdkTrapFocus,
    TooltipDirective,
    NgIcon,
    EmptyStateComponent,
    ScrollTopButtonComponent,
  ],
  providers: [provideIcons({ isaActionSearch, isaOtherInfo })],
})
export class SearchItemToRemitListComponent implements OnInit {
  host = inject(SearchItemToRemitDialogComponent);
  #catalougeSearchService = inject(CatalougeSearchService);

  searchParams = signal<SearchByTermInput | undefined>(undefined);

  availableSearchResults = computed(() => {
    return (
      this.searchResource.value()?.result?.filter((item) => {
        return this.getAvailableStockForItem(item) > 0;
      }) ?? []
    );
  });

  inStockResource = createInStockResource(() => {
    return {
      itemIds:
        this.searchResource
          .value()
          ?.result?.map((item) => item?.id)
          .filter((id) => !!id) ?? [],
    };
  });
  inStockResponseValue = computed(() => this.inStockResource.value());

  hasItems = computed(() => {
    return (this.availableSearchResults()?.length ?? 0) > 0;
  });

  stockInfoMap = computed(() => {
    const infos = this.inStockResponseValue() ?? [];
    return new Map(infos.map((info) => [info.itemId, info]));
  });

  getAvailableStockForItem(item: Item): number {
    const stockInfo = this.stockInfoMap().get(item.id);
    return calculateAvailableStock({
      stock: stockInfo?.inStock,
      removedFromStock: stockInfo?.removedFromStock,
    });
  }

  triggerSearch(): void {
    this.searchParams.set({
      searchTerm: this.host.searchTerm(),
    });
  }

  searchResource = resource({
    params: this.searchParams,
    loader: async ({ abortSignal, params }) => {
      if (params === undefined) {
        return DEFAULT_LIST_RESPONSE_ARGS_OF_ITEM;
      }
      let result: ListResponseArgs<Item> | undefined;

      const escAbortController = createEscAbortControllerHelper();

      try {
        result = await this.#catalougeSearchService.searchByTerm(
          params,
          AbortSignal.any([abortSignal, escAbortController.signal]),
        );
      } catch (error) {
        const message =
          error instanceof Error ? error.message : 'Unknown error';
        result = {
          ...DEFAULT_LIST_RESPONSE_ARGS_OF_ITEM,
          error: true,
          message,
        };
      } finally {
        escAbortController.abort();
      }

      return result;
    },
  });

  ngOnInit(): void {
    this.host.dialog.title.set('');
    if (this.host.searchTerm().length) {
      this.triggerSearch();
    }
  }
}
