import React, { type JSX } from 'react';
import * as FluentUI from '@fluentui/react';
import ElixFormsComponentAbstract from '@common/src/ElixFormsComponentAbstract';
import type { IElixFormsComponentCustomFormFieldFactory } from '@common/src/IElixFormsComponentCustomFormFieldFactory';
import { ElixFormsElement } from '@common/src/ElixFormsElement';
import { QueryParamHelper } from '@common/src/QueryParamHelper';
import config from './config.json';

/** Singolo risultato restituito dall'API esterna */
interface ContrattoResult {
  idContratto: string;
  titoloContratto: string;
  idDomanda: string;
  idRicevuta: string;
}

/** State aggiuntivo per gestire l'autocomplete */
interface RecuperoPropostaState {
  searchText: string;
  searchResults: ContrattoResult[];
  isLoading: boolean;
  isDropdownOpen: boolean;
  selectedContract: ContrattoResult | null;
  highlightedIndex: number;
  errorMessage: string;
}

export default class RecuperoPropostaCctDaContrattiComponent extends ElixFormsComponentAbstract {
  /** Stato locale per l'autocomplete (separato dal formData gestito dall'abstract) */
  private autocompleteState: RecuperoPropostaState = {
    searchText: '',
    searchResults: [],
    isLoading: false,
    isDropdownOpen: false,
    selectedContract: null,
    highlightedIndex: -1,
    errorMessage: '',
  };

  /** Timer per il debounce della ricerca */
  private debounceTimer: ReturnType<typeof setTimeout> | null = null;

  /** Ref al container per gestire il click-outside */
  private autocompleteRef: React.RefObject<HTMLDivElement | null> = React.createRef();

  private static readonly formFieldKeys = {
    idContratto:     'COL0010',
    titoloContratto: 'COL0020',
    idDomanda:       'COL0030',
    idRicevuta:      'COL0040',
  } as const;

  /** Codice fiscale letto dalla query string (COL0009), usato solo per la chiamata API */
  private codiceFiscale: string;

  constructor(props: any) {
    super(props);
    this.codiceFiscale = QueryParamHelper.getDecodedTextFromQuery('COL0009') ?? '';
  }

  override componentDidMount(): void {
    // Listener per chiudere il dropdown al click fuori dall'autocomplete
    document.addEventListener('mousedown', this.handleClickOutside);
  }

  override componentWillUnmount(): void {
    document.removeEventListener('mousedown', this.handleClickOutside);
    if (this.debounceTimer) {
      clearTimeout(this.debounceTimer);
    }
  }

  private handleClickOutside = (event: MouseEvent): void => {
    if (
      this.autocompleteRef.current &&
      !this.autocompleteRef.current.contains(event.target as Node)
    ) {
      this.autocompleteState.isDropdownOpen = false;
      this.forceUpdate();
    }
  };

  /**
   * Chiama l'API esterna per ottenere i contratti corrispondenti al testo di ricerca.
   * Autenticazione: Basic Auth (username:password) + header X-Api-Key.
   */
  private async fetchContratti(searchTerm: string): Promise<void> {
    this.autocompleteState.isLoading = true;
    this.autocompleteState.errorMessage = '';
    this.forceUpdate();

    try {
      const url = new URL(config.apiUrl);
      url.searchParams.set('_where', `{ "or": [ { "idContratto": { "contains": "${searchTerm}" } }, { "titoloContratto": { "contains": "${searchTerm}" } } ] }` );
      //url.searchParams.set('cod_fis', this.codiceFiscale);
      //url.searchParams.set('term', searchTerm);

      const credentials = btoa(`${config.apiUsername}:${config.apiPassword}`);

      const response = await fetch(url.toString(), {
        method: 'GET',
        headers: {
          'Authorization': `Basic ${credentials}`,
          'X-Api-Key': config.apiKey,
          'Accept': 'application/json',
        },
      });

      if (!response.ok) {
        throw new Error(`Errore API: ${response.status} ${response.statusText}`);
      }

      const data: ContrattoResult[] = await response.json();

      this.autocompleteState.searchResults = data;
      this.autocompleteState.isDropdownOpen = data.length > 0;
      this.autocompleteState.highlightedIndex = -1;
      this.autocompleteState.isLoading = false;
      this.forceUpdate();
    } catch (error) {
      console.error('Errore durante la ricerca contratti:', error);
      this.autocompleteState.searchResults = [];
      this.autocompleteState.isDropdownOpen = false;
      this.autocompleteState.isLoading = false;
      this.autocompleteState.errorMessage =
        error instanceof Error ? error.message : 'Errore durante la ricerca';
      this.forceUpdate();
    }
  }

  /**
   * Gestisce il cambio testo nell'input di ricerca.
   * Applica debounce e chiama l'API al raggiungimento del minimo di caratteri.
   */
  private handleSearchChange = (_event: React.FormEvent<HTMLInputElement | HTMLTextAreaElement>, newValue?: string): void => {
    const text = newValue ?? '';
    this.autocompleteState.searchText = text;

    // Se l'utente cancella il testo, resetta anche la selezione
    if (text.length === 0) {
      this.autocompleteState.searchResults = [];
      this.autocompleteState.isDropdownOpen = false;
      this.autocompleteState.highlightedIndex = -1;
      this.autocompleteState.errorMessage = '';
      this.clearSelection();
      this.forceUpdate();
      return;
    }

    // Debounce della ricerca
    if (this.debounceTimer) {
      clearTimeout(this.debounceTimer);
    }

    if (text.length >= config.minCharsForSearch) {
      this.debounceTimer = setTimeout(() => {
        this.fetchContratti(text);
      }, 300);
    } else {
      this.autocompleteState.searchResults = [];
      this.autocompleteState.isDropdownOpen = false;
      this.autocompleteState.highlightedIndex = -1;
      this.forceUpdate();
    }
  };

  /**
   * Gestisce la navigazione da tastiera nel dropdown (frecce, Invio, Escape).
   */
  private handleKeyDown = (event: React.KeyboardEvent<HTMLInputElement | HTMLTextAreaElement>): void => {
    const { searchResults, isDropdownOpen, highlightedIndex } = this.autocompleteState;

    if (!isDropdownOpen || searchResults.length === 0) return;

    switch (event.key) {
      case 'ArrowDown':
        event.preventDefault();
        this.autocompleteState.highlightedIndex = Math.min(
          highlightedIndex + 1,
          searchResults.length - 1
        );
        this.forceUpdate();
        break;

      case 'ArrowUp':
        event.preventDefault();
        this.autocompleteState.highlightedIndex = Math.max(highlightedIndex - 1, 0);
        this.forceUpdate();
        break;

      case 'Enter':
        event.preventDefault();
        if (highlightedIndex >= 0 && highlightedIndex < searchResults.length) {
          this.selectContract(searchResults[highlightedIndex]);
        }
        break;

      case 'Escape':
        event.preventDefault();
        this.autocompleteState.isDropdownOpen = false;
        this.forceUpdate();
        break;
    }
  };

  /**
   * Seleziona un contratto dal dropdown e popola i campi hidden del form.
   */
  private selectContract(contract: ContrattoResult): void {
    this.autocompleteState.selectedContract = contract;
    this.autocompleteState.searchText = `[${contract.idContratto}] ${contract.titoloContratto}`;
    this.autocompleteState.isDropdownOpen = false;
    this.autocompleteState.searchResults = [];
    this.autocompleteState.highlightedIndex = -1;

    // Aggiorna il formData con i valori selezionati
    this.setState({
      formData: {
        ...this.state.formData,
        [RecuperoPropostaCctDaContrattiComponent.formFieldKeys.idContratto]: contract.idContratto,
        [RecuperoPropostaCctDaContrattiComponent.formFieldKeys.titoloContratto]: contract.titoloContratto,
        [RecuperoPropostaCctDaContrattiComponent.formFieldKeys.idDomanda]: contract.idDomanda,
        [RecuperoPropostaCctDaContrattiComponent.formFieldKeys.idRicevuta]: contract.idRicevuta,
      },
    }, () => {
      console.log('Contratto selezionato:', contract);
      console.log('Form data aggiornato:', this.state.formData);
    });
  }

  /**
   * Resetta la selezione e svuota i campi hidden.
   */
  private clearSelection(): void {
    this.autocompleteState.selectedContract = null;

    this.setState({
      formData: {
        ...this.state.formData,
        [RecuperoPropostaCctDaContrattiComponent.formFieldKeys.idContratto]: '',
        [RecuperoPropostaCctDaContrattiComponent.formFieldKeys.titoloContratto]: '',
        [RecuperoPropostaCctDaContrattiComponent.formFieldKeys.idDomanda]: '',
        [RecuperoPropostaCctDaContrattiComponent.formFieldKeys.idRicevuta]: '',
      },
    });
  }

  /**
   * Renderizza il componente autocomplete completo (label + input + dropdown).
   */
  private renderAutocomplete(): JSX.Element {
    const { searchResults, isLoading, isDropdownOpen, highlightedIndex, errorMessage, searchText } = this.autocompleteState;

    const autocompleteInput = (
      <div className="autocomplete-wrapper" ref={this.autocompleteRef}>
        <FluentUI.TextField
          id="autocomplete-search"
          name="autocomplete-search"
          placeholder="Digita almeno 3 caratteri per cercare..."
          value={searchText}
          onChange={this.handleSearchChange}
          onKeyDown={this.handleKeyDown}
          className="isiportalPartialAdminFormFieldSingleLineText"
          autoComplete="off"
        />

        {isLoading && (
          <div className="autocomplete-dropdown">
            <div className="autocomplete-loading">
              <FluentUI.Spinner size={FluentUI.SpinnerSize.small} label="Ricerca in corso..." />
            </div>
          </div>
        )}

        {!isLoading && isDropdownOpen && searchResults.length > 0 && (
          <div className="autocomplete-dropdown">
            {searchResults.map((contract, index) => (
              <div
                key={`${contract.idContratto}_${index}`}
                className={`autocomplete-dropdown-item${index === highlightedIndex ? ' highlighted' : ''}`}
                onMouseDown={(e) => {
                  e.preventDefault(); // Previene blur del TextField
                  this.selectContract(contract);
                }}
                onMouseEnter={() => {
                  this.autocompleteState.highlightedIndex = index;
                  this.forceUpdate();
                }}
              >
                <span className="contract-id">[{contract.idContratto}]</span>{' '}
                <span className="contract-title">{contract.titoloContratto}</span>
              </div>
            ))}
          </div>
        )}

        {!isLoading && isDropdownOpen && searchResults.length === 0 && (
          <div className="autocomplete-dropdown">
            <div className="autocomplete-no-results">Nessun risultato trovato</div>
          </div>
        )}

        {errorMessage && (
          <div className="autocomplete-error">{errorMessage}</div>
        )}

        {this.autocompleteState.selectedContract && (
          <div className="selected-contract-summary">
            <div className="summary-row">
              <span className="summary-label">ID Contratto:</span>
              <span className="summary-value">{this.autocompleteState.selectedContract.idContratto}</span>
            </div>
            <div className="summary-row">
              <span className="summary-label">Titolo:</span>
              <span className="summary-value">{this.autocompleteState.selectedContract.titoloContratto}</span>
            </div>
            <div className="summary-row">
              <span className="summary-label">ID Domanda:</span>
              <span className="summary-value">{this.autocompleteState.selectedContract.idDomanda}</span>
            </div>
            <div className="summary-row">
              <span className="summary-label">ID Ricevuta:</span>
              <span className="summary-value">{this.autocompleteState.selectedContract.idRicevuta}</span>
            </div>
          </div>
        )}
      </div>
    );

    return new ElixFormsElement(
      <FluentUI.Label htmlFor="autocomplete-search">Cerca Contratto</FluentUI.Label>,
      autocompleteInput
    ).render();
  }

  /**
   * Override del metodo factory per definire i campi custom del form.
   * - Autocomplete per la ricerca contratti
   * - 4 campi hidden (COL0010, COL0020, COL0030, COL0040) per i dati da rimandare a elixForms
   */
  protected override createCustomFormFields(formFieldFactory: IElixFormsComponentCustomFormFieldFactory): JSX.Element {
    const fieldKeys = RecuperoPropostaCctDaContrattiComponent.formFieldKeys;
    const idContratto = this.state.formData[fieldKeys.idContratto] ?? '';
    const titoloContratto = this.state.formData[fieldKeys.titoloContratto] ?? '';
    const idDomanda = this.state.formData[fieldKeys.idDomanda] ?? '';
    const idRicevuta = this.state.formData[fieldKeys.idRicevuta] ?? '';

    return (
      <>
        {this.renderAutocomplete()}

        {/* Campi hidden per i dati del contratto selezionato — verranno inviati nel POST a elixForms */}
        <input type="hidden" id="idContratto_hidden" name={fieldKeys.idContratto} value={idContratto} />
        <input type="hidden" id="titoloContratto_hidden" name={fieldKeys.titoloContratto} value={titoloContratto} />
        <input type="hidden" id="idDomanda_hidden" name={fieldKeys.idDomanda} value={idDomanda} />
        <input type="hidden" id="idRicevuta_hidden" name={fieldKeys.idRicevuta} value={idRicevuta} />
      </>
    );
  }
}
