import {
  ChangeDetectionStrategy,
  Component,
  computed,
  effect,
  inject,
  input,
  signal,
  untracked,
  WritableSignal,
} from '@angular/core';
import {
  CanReturn,
  EligibleForReturnState,
  ReturnCanReturnService,
  ReturnProcessService,
  ReturnProcessStore,
} from '@isa/oms/data-access';
import { NgIconComponent, provideIcons } from '@ng-icons/core';
import { isaActionCheck, isaActionClose } from '@isa/icons';
import { ReturnProcessQuestionsComponent } from '../return-process-questions/return-process-questions.component';
import { ProgressBarComponent } from '@isa/ui/progress-bar';
import { ReturnProductInfoComponent } from '@isa/oms/shared/product-info';
import { logger, provideLoggerContext } from '@isa/core/logging';
import { IconButtonComponent } from '@isa/ui/buttons';

/**
 * Component that displays a single return process item with its associated questions and progress.
 * Integrates with ReturnProcessService and ReturnProcessStore for return process management.
 *
 * @example
 * ```html
 * <oms-feature-return-process-item
 *   [returnProcessId]="123">
 * </oms-feature-return-process-item>
 * ```
 */
@Component({
  selector: 'oms-feature-return-process-item',
  templateUrl: './return-process-item.component.html',
  styleUrls: ['./return-process-item.component.scss'],
  changeDetection: ChangeDetectionStrategy.OnPush,
  standalone: true,
  imports: [
    NgIconComponent,
    ReturnProcessQuestionsComponent,
    ProgressBarComponent,
    IconButtonComponent,
    ReturnProductInfoComponent,
  ],
  providers: [
    provideIcons({ isaActionCheck, isaActionClose }),
    provideLoggerContext({ component: 'ReturnProcessItemComponent' }),
  ],
})
export class ReturnProcessItemComponent {
  EligibleForReturnState = EligibleForReturnState;
  #returnProcessService = inject(ReturnProcessService);
  #returnCanReturnService = inject(ReturnCanReturnService);
  returnProcessStore = inject(ReturnProcessStore);

  /** Logger instance specific to this component context. */
  #logger = logger();

  /** The unique identifier for the return process */
  returnProcessId = input.required<number>();

  /** The current return process object derived from the store */
  returnProcess = computed(() => {
    return this.returnProcessStore.entityMap()[this.returnProcessId()];
  });

  /** The progress status of the return process questions */
  progress = computed(() => {
    return this.#returnProcessService.returnProcessQuestionsProgress(
      this.returnProcess(),
    );
  });

  /**
   * Signal holding the backend validation result for whether the current return process
   * can be returned. Initially undefined, it is asynchronously set after backend validation.
   *
   * @type {WritableSignal<CanReturn | undefined>}
   * @see ReturnCanReturnService.canReturn
   * @remarks
   * - This signal is reset to undefined before each backend check.
   * - The value is updated with the backend response for the current return process.
   */
  canReturn: WritableSignal<CanReturn | undefined> = signal(undefined);

  /**
   * Signal that evaluates if the current return process is eligible for return
   * based on frontend validation rules
   * @returns A signal containing the eligibility state and reason
   */
  eligibleForReturn = computed(() =>
    this.#returnProcessService.eligibleForReturn(this.returnProcess()),
  );

  /**
   * Computed signal that determines the final eligibility state by combining
   * backend validation results and frontend eligibility checks
   * @returns The final eligibility state (Eligible or NotEligible)
   */
  eligibleForReturnState = computed(() => {
    const eligibleForReturnState = this.eligibleForReturn()?.state;
    const canReturnResult = this.canReturn()?.result;

    if (canReturnResult === undefined) {
      return EligibleForReturnState.Unknown;
    }

    if (
      canReturnResult === true &&
      eligibleForReturnState === EligibleForReturnState.Eligible
    ) {
      return EligibleForReturnState.Eligible;
    }

    return EligibleForReturnState.NotEligible;
  });

  /**
   * Computed signal that provides the appropriate message explaining why a return process
   * is eligible or not eligible for return
   * @returns The explanation message from backend validation or frontend eligibility check
   */
  eligibleForReturnMessage = computed(() => {
    const eligibleForReturnReason = this.eligibleForReturn()?.reason;
    const canReturnMessage = this.canReturn()?.message;

    return canReturnMessage ?? eligibleForReturnReason; // Fallback to eligibleForReturnReason if canReturnMessage is not available
  });

  /**
   * Initializes the component and sets up a reactive effect to validate
   * the return process eligibility with the backend whenever the process changes.
   *
   * - Resets the `canReturn` signal to `undefined` before each backend check.
   * - Asynchronously updates `canReturn` with the backend response.
   * - Ensures backend validation is always in sync with the current return process.
   *
   * @remarks
   * This approach leverages Angular signals and effects for local state management,
   * following workspace guidelines for clean, reactive, and maintainable code.
   */
  constructor() {
    effect(() => {
      const returnProcess = this.returnProcess();

      untracked(async () => {
        if (returnProcess) {
          this.canReturn.set(undefined);
          try {
            const canReturnResponse =
              await this.#returnCanReturnService.canReturn(returnProcess);
            this.canReturn.set(canReturnResponse);
          } catch (error) {
            this.#logger.error(
              'Failed to validate return process',
              error as Error,
              () => ({
                returnProcessId: returnProcess.id,
              }),
            );
            this.canReturn.set(undefined);
          }
        } else {
          this.canReturn.set(undefined);
        }
      });
    });
  }
}
