import {Component, OnDestroy, OnInit} from '@angular/core';
import {CommonModule} from '@angular/common';
import {FormsModule} from '@angular/forms';
import {Store} from '@ngrx/store';
import {ActionTypes, StateInterface} from '../../reducers';
import {ChatbotMessage} from '../../services/chatbot.message.type';
import {ChatbotConversation} from '../../services/conversations.service';
import {ApiService, OpenMeteoResponse} from '../../services/api-service';
import {interval, Subscription} from 'rxjs';
import {OptionsDropdown} from '../options-dropdown/options-dropdown';

@Component({
  selector: 'app-prompt-input',
  imports: [CommonModule, FormsModule, OptionsDropdown],
  templateUrl: './prompt-input.html',
  styleUrl: './prompt-input.scss'
})
export class PromptInput implements OnInit, OnDestroy {
  // Static counter to track API calls
  static apiCallCounter: number = 0;

  userInput: string = '';
  activeConversation: ChatbotConversation | null = null;
  private appState: any = '';
  private ollamaCheckSubscription: Subscription | null = null;

  // Check interval in milliseconds (30 seconds)
  private readonly CHECK_INTERVAL = 30000;

  constructor(private store: Store<StateInterface>, private apiService: ApiService) {


    // Get the active conversation from the store
    this.store.select(state => state.activeConversation).subscribe(activeConv => {
      if (activeConv && Object.keys(activeConv).length > 0) {
        this.activeConversation = activeConv as ChatbotConversation;
      }
    })
    this.store.select(state => state.app).subscribe(app => {
      this.appState = app;
    });

    // Check if Ollama is available when the component is initialized
    this.checkOllamaAvailability();
  }

  /**
   * Check if the Ollama backend is available
   * This will update the Redux store with the result
   */
  checkOllamaAvailability(): void {
    this.apiService.checkOllamaAvailability().subscribe({
      next: (isAvailable) => {
        console.log('Ollama availability:', isAvailable);
        // The store is already updated in the ApiService
      },
      error: (error) => {
        console.error('Error checking Ollama availability:', error);
      }
    });
  }

  /**
   * Angular lifecycle hook that is called after the component is initialized
   * Sets up periodic checking for Ollama availability
   */
  ngOnInit(): void {
    // Set up periodic checking for Ollama availability
    this.ollamaCheckSubscription = interval(this.CHECK_INTERVAL).subscribe(() => {
      console.log('Performing periodic Ollama availability check');
      this.checkOllamaAvailability();
    });
  }

  /**
   * Angular lifecycle hook that is called when the component is destroyed
   * Cleans up subscriptions to prevent memory leaks
   */
  ngOnDestroy(): void {
    // Clean up the subscription when the component is destroyed
    if (this.ollamaCheckSubscription) {
      this.ollamaCheckSubscription.unsubscribe();
      this.ollamaCheckSubscription = null;
    }
  }

  submitMessage() {
    console.log(this.userInput);

    if (!this.userInput.trim() || !this.activeConversation) {
      console.info('no input to send')
      return;
    }

    // Store the user input in a local variable before clearing it
    const userInputText = this.userInput.trim();
    console.log('userInputText', userInputText)
    // Create a new message
    const newMessage = new ChatbotMessage({
      kind: 'user',
      user: {},
      content: userInputText,
      name: 'User Message'
    });
    // Update the active conversation in the store
    this.store.dispatch({
      type: ActionTypes.POST_MESSAGE_TO_ACTIVE_CONVERSATION,
      payload: newMessage
    });
    // Clear the input
    this.userInput = '';
    const elemFound: HTMLInputElement | null = document.querySelector('.prompt-input input') as HTMLInputElement
    if (elemFound) {
      elemFound.focus();
    }
    // Check if Ollama is available
    if (this.appState.ollamaAvailable) {
      // If Ollama is available, use it regardless of demo mode
      console.log('Using Ollama backend for response');

      // Query Ollama with the stored user input
      this.apiService.queryOllama(userInputText).subscribe({
        error: (error) => {
          console.error('Error querying Ollama:', error);
        }
      });
    } else if (this.appState.demoMode) {
      // If Ollama is not available and we're in demo mode, use the demo response
      console.log('Using demo response (Ollama not available)');

      // Static counter to track API calls
      if (!PromptInput.apiCallCounter) {
        PromptInput.apiCallCounter = 0;
      }
      PromptInput.apiCallCounter++;

      // Set loading state to true before API call
      this.store.dispatch({
        type: ActionTypes.UPDATE_APP,
        payload: {
          loading: true
        }
      });

      this.apiService.fetchDemoResponse().subscribe({
        next: (resp: OpenMeteoResponse) => {
          console.log('fetchDemoResponse', resp);

          // Set loading state to false after API call
          this.store.dispatch({
            type: ActionTypes.UPDATE_APP,
            payload: {
              loading: false
            }
          });

          // Every third call, show an error instead of the actual response
          if (PromptInput.apiCallCounter % 3 === 0) {
            // Set error state to true
            this.store.dispatch({
              type: ActionTypes.UPDATE_APP,
              payload: {
                displayErrorResponse: true
              }
            });

            // Send error message to chat
            const errorMessage = new ChatbotMessage({
              kind: 'llm',
              user: {},
              content: "System error - I couldn't process your request. Please try again in few moments",
              name: 'Assistant'
            });

            this.store.dispatch({
              type: ActionTypes.POST_MESSAGE_TO_ACTIVE_CONVERSATION,
              payload: errorMessage
            });

            // Reset error state after 3 seconds
            setTimeout(() => {
              this.store.dispatch({
                type: ActionTypes.UPDATE_APP,
                payload: {
                  displayErrorResponse: false
                }
              });
            }, 3000);

            return;
          }

          // Format the weather data in a readable way
          const currentTemp = resp.hourly.temperature_2m[new Date().getHours()];
          const minTemp = Math.min(...resp.hourly.temperature_2m);
          const maxTemp = Math.max(...resp.hourly.temperature_2m);

          const weatherApiDemoResult = `
<h2>

Météo pour aujourd'hui à Corbeil-Essonne
</h2>
<br>
- <strong>Température actuelle:</strong> ${currentTemp}${resp.hourly_units.temperature_2m}
<br>
<ul>
<li>

Élévation: ${resp.elevation}m<br>
</li>
</ul>
<br>

<table class="table is-striped">
  <thead>
    <th>label</th>
    <th>valeur</th>
  </thead>
  <tbody>
  <tr>
    <td>
        Température min
    </td>
    <td>
        ${minTemp}${resp.hourly_units.temperature_2m}
    </td>

  </tr>
  <tr>
    <td>
        Température max
    </td>
    <td>
        ${maxTemp}${resp.hourly_units.temperature_2m}
    </td>
  </tr>
</tbody>
</table>

 <a href="https://www.open-meteo.com">
*Données fournies par Open-Meteo API*
</a>
          `;

          const newMessage = new ChatbotMessage({
            kind: 'llm',
            user: {},
            content: `Voici les données météo que vous avez demandées:\n${weatherApiDemoResult}`,
            name: 'Assistant'
          });

          // Update the active conversation in the store
          this.store.dispatch({
            type: ActionTypes.POST_MESSAGE_TO_ACTIVE_CONVERSATION,
            payload: newMessage
          });
        },
        error: (error) => {
          console.error('Error fetching weather data:', error);

          // Set loading state to false after API call
          this.store.dispatch({
            type: ActionTypes.UPDATE_APP,
            payload: {
              loading: false
            }
          });

          // Send error message to chat
          const errorMessage = new ChatbotMessage({
            kind: 'llm',
            user: {},
            content: "Désolé, je n'ai pas pu récupérer les données météo. Veuillez réessayer plus tard.",
            name: 'Assistant'
          });

          this.store.dispatch({
            type: ActionTypes.POST_MESSAGE_TO_ACTIVE_CONVERSATION,
            payload: errorMessage
          });
        }
      });
    } else {
      // Not in demo mode and Ollama is not available
      console.error('Error: Ollama is not available and not in demo mode');

      // Send error message to chat
      const errorMessage = new ChatbotMessage({
        kind: 'llm',
        user: {},
        content: "Error: The AI backend is not available. Please check your configuration or try again later.",
        name: 'System'
      });

      this.store.dispatch({
        type: ActionTypes.POST_MESSAGE_TO_ACTIVE_CONVERSATION,
        payload: errorMessage
      });
    }

  }


// Handle key events for Ctrl+Enter
  handleKeyEvent(event: KeyboardEvent) {
    // Check if Ctrl key is pressed and Enter key is pressed
    if (event.ctrlKey && event.key === 'Enter') {
      this.submitMessage();
      event.preventDefault(); // Prevent default behavior
    }
  }

}
