import {
  ChangeDetectionStrategy,
  Component,
  effect,
  input,
  output,
  untracked,
} from '@angular/core';
import { FormControl, ReactiveFormsModule, Validators } from '@angular/forms';

import { ButtonComponent, TextButtonComponent } from '@isa/ui/buttons';
import {
  InputControlDirective,
  TextFieldClearComponent,
  TextFieldComponent,
  TextFieldContainerComponent,
  TextFieldErrorsComponent,
} from '@isa/ui/input-controls';
import { ScannerButtonComponent } from '@isa/shared/scanner';
import {
  RequestStatus,
  ReturnReceiptResult,
  ReturnReceiptResultType,
} from './remission-start-dialog.component';

/**
 * Component for creating a return receipt in the remission process.
 *
 * This component provides the first step of the remission workflow, allowing users to:
 * - Generate a receipt number automatically
 * - Manually input a custom receipt number
 * - Scan a receipt number using the integrated scanner
 * - Validate receipt number format (18-digit requirement)
 *
 * The component uses reactive forms for input validation and handles server-side
 * validation errors through the RequestStatus input. It emits different result types
 * based on user interaction (generate, input with value, or close).
 *
 * @example
 * ```html
 * <remi-create-return-receipt
 *   [createRemissionLoading]="requestStatus"
 *   (createReturnReceipt)="onCreateReturnReceipt($event)"
 * />
 * ```
 *
 * @example
 * ```typescript
 * // Handling the output event
 * onCreateReturnReceipt(result: ReturnReceiptResult): void {
 *   if (result?.type === ReturnReceiptResultType.Generate) {
 *     // User chose to auto-generate
 *   } else if (result?.type === ReturnReceiptResultType.Input) {
 *     // User provided custom value: result.value
 *   } else {
 *     // User closed/cancelled
 *   }
 * }
 * ```
 */
@Component({
  selector: 'remi-create-return-receipt',
  templateUrl: './create-return-receipt.component.html',
  styleUrl: './create-return-receipt.component.scss',
  changeDetection: ChangeDetectionStrategy.OnPush,
  imports: [
    ReactiveFormsModule,
    ButtonComponent,
    InputControlDirective,
    TextFieldClearComponent,
    TextFieldComponent,
    TextFieldContainerComponent,
    TextFieldErrorsComponent,
    TextButtonComponent,
    ScannerButtonComponent,
  ],
})
export class CreateReturnReceiptComponent {
  /**
   * Expose ReturnReceiptResultType enum to template for type checking and comparisons.
   */
  ReturnReceiptResultType = ReturnReceiptResultType;

  /**
   * Input signal containing the current request status for the create remission operation.
   * Used to display loading states and handle server-side validation errors.
   * When invalidProperties contains 'receiptNumber', the form control is updated with the error.
   */
  createRemissionLoading = input<RequestStatus>({ loading: false });

  /**
   * Output signal emitted when user completes the return receipt creation step.
   * Emits different result types based on user action:
   * - Generate: User chose automatic generation
   * - Input: User provided a custom receipt number
   * - Close: User cancelled or provided invalid input
   */
  createReturnReceipt = output<ReturnReceiptResult>();

  /**
   * Form control for the receipt number input field.
   *
   * Validation rules:
   * - Required: Receipt number must be provided when using manual input
   * - Pattern: Must be exactly 18 digits (/^\d{18}$/)
   *
   * The control also handles server-side validation errors received through
   * the createRemissionLoading input signal.
   */
  control = new FormControl<string | undefined>(undefined, {
    validators: [Validators.required, Validators.pattern(/^\d{18}$/)],
  });

  /**
   * Constructor sets up reactive error handling for server-side validation.
   *
   * Uses an effect to monitor the createRemissionLoading signal and automatically
   * update the form control's error state when server validation fails for the
   * receiptNumber field. The untracked wrapper prevents infinite loops while
   * allowing the effect to respond to signal changes.
   */
  constructor() {
    effect(() => {
      const status = this.createRemissionLoading();
      untracked(() => {
        if (status?.invalidProperties?.['receiptNumber']) {
          this.control.setErrors({
            invalidProperties: status?.invalidProperties?.['receiptNumber'],
          });
        } else {
          this.control.setErrors(null);
        }
      });
    });
  }

  /**
   * Handles scanned receipt number input from the scanner component.
   *
   * When a valid value is scanned, it automatically populates the form control.
   * This provides a convenient way for users to input receipt numbers without
   * manual typing, reducing input errors.
   *
   * @param value - The scanned receipt number, or null if scan failed/was cancelled
   *
   * @example
   * ```html
   * <isa-scanner-button (scanned)="onScan($event)" />
   * ```
   */
  onScan(value: string | null): void {
    if (!value) {
      return;
    }
    this.control.setValue(value);
  }

  /**
   * Handles the generate receipt number action.
   *
   * Emits a Generate result type, indicating the user wants the system
   * to automatically generate a receipt number rather than providing one manually.
   * This is typically the preferred option for most users as it eliminates
   * input errors and ensures uniqueness.
   *
   * @example
   * ```html
   * <button (click)="onGenerate()">Generate Receipt Number</button>
   * ```
   */
  onGenerate(): void {
    return this.createReturnReceipt.emit({
      type: ReturnReceiptResultType.Generate,
    });
  }

  /**
   * Handles form submission and validation for manual receipt number input.
   *
   * This method performs comprehensive validation before emitting the result:
   * 1. Checks if a request is currently in progress (prevents double submission)
   * 2. Triggers form validation to ensure receipt number meets requirements
   * 3. Validates that a value was actually provided
   * 4. Emits the appropriate result based on validation outcome
   *
   * If validation fails or no value is provided, emits a Close result.
   * If validation passes, emits the provided value for processing.
   *
   * @param value - The return receipt result to process (typically contains user input)
   *
   * @example
   * ```html
   * <form (ngSubmit)="onSave({ type: ReturnReceiptResultType.Input, value: control.value })">
   *   <input [formControl]="control" />
   *   <button type="submit">Save Receipt Number</button>
   * </form>
   * ```
   */
  onSave(value: ReturnReceiptResult): void {
    if (this.createRemissionLoading().loading) {
      return;
    }

    this.control.updateValueAndValidity();

    if (
      value === undefined ||
      this.control.invalid ||
      this.control?.value === null ||
      this.control?.value === undefined
    ) {
      return this.createReturnReceipt.emit({
        type: ReturnReceiptResultType.Close,
      });
    }

    return this.createReturnReceipt.emit(value);
  }
}
