/**
 * Flow Screen Component Template
 *
 * Demonstrates complete Flow integration patterns:
 * - @api properties with inputOnly/outputOnly roles
 * - FlowAttributeChangeEvent for output binding
 * - FlowNavigationFinishEvent for programmatic navigation
 * - availableActions for navigation state awareness
 * - @AuraEnabled Apex integration for data operations
 *
 * @see https://developer.salesforce.com/docs/component-library/bundle/lightning-flow-support
 */
import { LightningElement, api, wire } from 'lwc';
import { FlowAttributeChangeEvent, FlowNavigationFinishEvent } from 'lightning/flowSupport';

// Apex imports (uncomment and modify as needed)
// import getRecords from '@salesforce/apex/FlowScreenController.getRecords';
// import processRecord from '@salesforce/apex/FlowScreenController.processRecord';

export default class FlowScreenComponent extends LightningElement {
  // ═══════════════════════════════════════════════════════════════════════
  // FLOW INPUT PROPERTIES (inputOnly - Flow → Component)
  // These receive values FROM the Flow. Changes in Flow update the component.
  // ═══════════════════════════════════════════════════════════════════════

  /**
   * Record ID from Flow context (e.g., from Record-Triggered Flow)
   * Maps to: Flow variable or $Record.Id
   */
  @api recordId;

  /**
   * Object API Name for context-aware behavior
   * Maps to: Flow variable or $Record.Object
   */
  @api objectApiName;

  /**
   * Custom label configurable in Flow Builder
   * Maps to: Flow constant, variable, or direct text
   */
  @api inputLabel = 'Select a Record';

  /**
   * Available navigation actions - automatically populated by Flow runtime
   * Possible values: ['NEXT', 'BACK', 'FINISH', 'PAUSE']
   * Use this to conditionally show/hide navigation buttons
   */
  @api availableActions = [];

  // ═══════════════════════════════════════════════════════════════════════
  // FLOW OUTPUT PROPERTIES (outputOnly - Component → Flow)
  // These send values BACK to the Flow. Use FlowAttributeChangeEvent to update.
  // ═══════════════════════════════════════════════════════════════════════

  /**
   * Selected record ID - output to Flow
   * IMPORTANT: Use FlowAttributeChangeEvent to notify Flow of changes
   */
  @api selectedRecordId;

  /**
   * Selected record name - output to Flow
   */
  @api selectedRecordName;

  /**
   * Boolean flag indicating completion - useful for Flow decisions
   */
  @api isComplete = false;

  /**
   * Error message if validation fails - Flow can use in fault path
   */
  @api errorMessage;

  // ═══════════════════════════════════════════════════════════════════════
  // PRIVATE REACTIVE PROPERTIES
  // ═══════════════════════════════════════════════════════════════════════

  records = [];
  error;
  isLoading = true;
  _selectedId;

  // ═══════════════════════════════════════════════════════════════════════
  // LIFECYCLE HOOKS
  // ═══════════════════════════════════════════════════════════════════════

  connectedCallback() {
    // Initialize component when added to DOM
    this.loadData();
  }

  // ═══════════════════════════════════════════════════════════════════════
  // DATA LOADING
  // ═══════════════════════════════════════════════════════════════════════

  /**
   * Load data - replace with @wire or imperative Apex call
   */
  async loadData() {
    this.isLoading = true;
    try {
      // Example: Load records from Apex
      // this.records = await getRecords({ parentId: this.recordId });

      // Placeholder data for template
      this.records = [
        { id: '001xx000000001', name: 'Sample Record 1', description: 'Description 1' },
        { id: '001xx000000002', name: 'Sample Record 2', description: 'Description 2' },
        { id: '001xx000000003', name: 'Sample Record 3', description: 'Description 3' },
      ];
      this.error = undefined;
    } catch (err) {
      this.error = this.reduceErrors(err);
      this.records = [];
    } finally {
      this.isLoading = false;
    }
  }

  // ═══════════════════════════════════════════════════════════════════════
  // FLOW OUTPUT - FlowAttributeChangeEvent
  // CRITICAL: This is how you send values back to Flow variables
  // ═══════════════════════════════════════════════════════════════════════

  /**
   * Handle record selection and notify Flow
   * @param {Event} event - Click event from record tile
   */
  handleRecordSelect(event) {
    const recordId = event.currentTarget.dataset.id;
    const recordName = event.currentTarget.dataset.name;

    // Update local state
    this._selectedId = recordId;
    this.selectedRecordId = recordId;
    this.selectedRecordName = recordName;

    // ─────────────────────────────────────────────────────────────────
    // CRITICAL: Dispatch FlowAttributeChangeEvent for EACH output
    // This notifies the Flow runtime that output values have changed
    // The first parameter is the @api property name (case-sensitive)
    // The second parameter is the new value
    // ─────────────────────────────────────────────────────────────────
    this.dispatchEvent(new FlowAttributeChangeEvent('selectedRecordId', this.selectedRecordId));

    this.dispatchEvent(new FlowAttributeChangeEvent('selectedRecordName', this.selectedRecordName));
  }

  /**
   * Update completion status and notify Flow
   * @param {Boolean} complete - Whether the screen is complete
   */
  setComplete(complete) {
    this.isComplete = complete;
    this.dispatchEvent(new FlowAttributeChangeEvent('isComplete', complete));
  }

  /**
   * Set error message and notify Flow
   * @param {String} message - Error message
   */
  setError(message) {
    this.errorMessage = message;
    this.dispatchEvent(new FlowAttributeChangeEvent('errorMessage', message));
  }

  // ═══════════════════════════════════════════════════════════════════════
  // FLOW NAVIGATION - FlowNavigationFinishEvent
  // Programmatically trigger Flow navigation (Next, Back, Finish, Pause)
  // ═══════════════════════════════════════════════════════════════════════

  /**
   * Navigate to next screen
   * Only works if 'NEXT' is in availableActions
   */
  handleNext() {
    // Validate before navigation
    if (!this.selectedRecordId) {
      this.setError('Please select a record before proceeding.');
      return;
    }

    // Clear any previous errors
    this.setError(null);

    // Mark as complete
    this.setComplete(true);

    // Check if NEXT action is available
    if (this.canGoNext) {
      // Dispatch navigation event - Flow will handle the rest
      this.dispatchEvent(new FlowNavigationFinishEvent('NEXT'));
    }
  }

  /**
   * Navigate to previous screen
   * Only works if 'BACK' is in availableActions
   */
  handleBack() {
    if (this.canGoBack) {
      this.dispatchEvent(new FlowNavigationFinishEvent('BACK'));
    }
  }

  /**
   * Finish the flow (for final screens)
   * Only works if 'FINISH' is in availableActions
   */
  handleFinish() {
    // Validate before finishing
    if (!this.selectedRecordId) {
      this.setError('Please select a record before finishing.');
      return;
    }

    this.setComplete(true);

    if (this.canFinish) {
      this.dispatchEvent(new FlowNavigationFinishEvent('FINISH'));
    }
  }

  /**
   * Pause the flow (for pausable flows)
   * Only works if 'PAUSE' is in availableActions
   */
  handlePause() {
    if (this.canPause) {
      this.dispatchEvent(new FlowNavigationFinishEvent('PAUSE'));
    }
  }

  // ═══════════════════════════════════════════════════════════════════════
  // APEX INTEGRATION (Optional)
  // Use @AuraEnabled methods for complex operations
  // ═══════════════════════════════════════════════════════════════════════

  /**
   * Example: Process selection with Apex before navigation
   */
  async handleProcessAndContinue() {
    this.isLoading = true;
    try {
      // Call Apex to process the selection
      // const result = await processRecord({
      //     recordId: this.selectedRecordId,
      //     operation: 'validate'
      // });

      // Simulate successful processing
      const result = { success: true, message: 'Validated successfully' };

      if (result.success) {
        this.setComplete(true);
        this.handleNext();
      } else {
        this.setError(result.message);
      }
    } catch (err) {
      this.setError(this.reduceErrors(err));
    } finally {
      this.isLoading = false;
    }
  }

  // ═══════════════════════════════════════════════════════════════════════
  // COMPUTED PROPERTIES
  // ═══════════════════════════════════════════════════════════════════════

  get hasRecords() {
    return this.records && this.records.length > 0;
  }

  get hasSelection() {
    return !!this._selectedId;
  }

  get canGoBack() {
    return this.availableActions.includes('BACK');
  }

  get canGoNext() {
    return this.availableActions.includes('NEXT');
  }

  get canFinish() {
    return this.availableActions.includes('FINISH');
  }

  get canPause() {
    return this.availableActions.includes('PAUSE');
  }

  get showBackButton() {
    return this.canGoBack;
  }

  get showNextButton() {
    return this.canGoNext;
  }

  get showFinishButton() {
    return this.canFinish && !this.canGoNext;
  }

  /**
   * Compute selected class for record tiles
   */
  getRecordClass(recordId) {
    return this._selectedId === recordId
      ? 'slds-box slds-box_link slds-theme_shade slds-is-selected'
      : 'slds-box slds-box_link';
  }

  // ═══════════════════════════════════════════════════════════════════════
  // UTILITIES
  // ═══════════════════════════════════════════════════════════════════════

  /**
   * Reduce various error formats to a string
   * @param {*} errors - Error object(s)
   * @returns {String} - Formatted error message
   */
  reduceErrors(errors) {
    if (!Array.isArray(errors)) {
      errors = [errors];
    }

    return errors
      .filter((error) => !!error)
      .map((error) => {
        if (error.body?.message) return error.body.message;
        if (error.message) return error.message;
        return JSON.stringify(error);
      })
      .join('; ');
  }
}
