import { ReactiveCache } from '/imports/reactiveCache';
import { TAPi18n } from '/imports/i18n';
import Cards from '../../models/cards';
import SessionData from '../../models/usersessiondata';
import {QueryDebug} from "../../config/query-classes";
import {OPERATOR_DEBUG} from "../../config/search-const";

export class CardSearchPagedComponent extends BlazeComponent {
  onCreated() {
    this.searching = new ReactiveVar(false);
    this.hasResults = new ReactiveVar(false);
    this.hasQueryErrors = new ReactiveVar(false);
    this.query = new ReactiveVar('');
    this.resultsHeading = new ReactiveVar('');
    this.searchLink = new ReactiveVar(null);
    this.results = new ReactiveVar([]);
    this.hasNextPage = new ReactiveVar(false);
    this.hasPreviousPage = new ReactiveVar(false);
    this.resultsCount = 0;
    this.totalHits = 0;
    this.queryErrors = null;
    this.resultsPerPage = 25;
    this.sessionId = SessionData.getSessionId();
    this.subscriptionHandle = null;
    this.serverError = new ReactiveVar(false);
    this.sessionData = null;
    this.debug = new ReactiveVar(new QueryDebug());

    const that = this;
    this.subscriptionCallbacks = {
      onReady() {
        if (process.env.DEBUG === 'true') {
          console.log('Subscription ready, getting results...');
          console.log('Subscription ready - sessionId:', that.sessionId);
        }
        
        // Wait for session data to be available (with timeout)
        let waitCount = 0;
        const maxWaitCount = 50; // 10 seconds max wait
        
        const waitForSessionData = () => {
          waitCount++;
          const sessionData = that.getSessionData();
          if (process.env.DEBUG === 'true') {
            console.log('waitForSessionData - attempt', waitCount, 'session data:', sessionData);
          }
          
          if (sessionData) {
            const results = that.getResults();
            if (process.env.DEBUG === 'true') {
              console.log('Search results count:', results ? results.length : 0);
            }
            
            // If no results and this is a due cards search, try to retry
            if ((!results || results.length === 0) && that.searchRetryCount !== undefined && that.searchRetryCount < that.maxRetries) {
              if (process.env.DEBUG === 'true') {
                console.log('No results found, retrying search...');
              }
              that.searchRetryCount++;
              Meteor.setTimeout(() => {
                if (that.performSearch) {
                  that.performSearch();
                }
              }, 500);
              return;
            }
            
            that.searching.set(false);
            that.hasResults.set(true);
            that.serverError.set(false);
             } else if (waitCount < maxWaitCount) {
               // Session data not available yet, wait a bit more
               if (process.env.DEBUG === 'true') {
                 console.log('Session data not available yet, waiting... (attempt', waitCount, 'of', maxWaitCount, ')');
               }
               Meteor.setTimeout(waitForSessionData, 200);
             } else {
               // Timeout reached, try fallback search
               if (process.env.DEBUG === 'true') {
                 console.log('Timeout reached waiting for session data, trying fallback search');
               }
               const results = that.getResults();
               if (process.env.DEBUG === 'true') {
                 console.log('Fallback search results count:', results ? results.length : 0);
               }
               
               if (results && results.length > 0) {
                 that.searching.set(false);
                 that.hasResults.set(true);
                 that.serverError.set(false);
               } else {
                 that.searching.set(false);
                 that.hasResults.set(false);
                 that.serverError.set(true);
               }
             }
        };
        
        // Start waiting for session data
        Meteor.setTimeout(waitForSessionData, 100);
      },
      onError(error) {
        if (process.env.DEBUG === 'true') {
          console.log('Subscription error:', error);
          console.log('Error.reason:', error.reason);
          console.log('Error.message:', error.message);
          console.log('Error.stack:', error.stack);
        }
        that.searching.set(false);
        that.hasResults.set(false);
        that.serverError.set(true);
      },
    };
  }

  resetSearch() {
    this.searching.set(false);
    this.results.set([]);
    this.hasResults.set(false);
    this.hasQueryErrors.set(false);
    this.resultsHeading.set('');
    this.serverError.set(false);
    this.resultsCount = 0;
    this.totalHits = 0;
    this.queryErrors = null;
    this.debug.set(new QueryDebug());
  }

  getSessionData(sessionId) {
    const sessionIdToUse = sessionId || SessionData.getSessionId();
    if (process.env.DEBUG === 'true') {
      console.log('getSessionData - looking for sessionId:', sessionIdToUse);
    }
    
    // Try using the raw SessionData collection instead of ReactiveCache
    const sessionData = SessionData.findOne({
      sessionId: sessionIdToUse,
    });
    if (process.env.DEBUG === 'true') {
      console.log('getSessionData - found session data (raw):', sessionData);
    }
    
    // Also try ReactiveCache for comparison
    const reactiveSessionData = ReactiveCache.getSessionData({
      sessionId: sessionIdToUse,
    });
    if (process.env.DEBUG === 'true') {
      console.log('getSessionData - found session data (reactive):', reactiveSessionData);
    }
    
    return sessionData || reactiveSessionData;
  }

  getResults() {
    // eslint-disable-next-line no-console
    // console.log('getting results');
    this.sessionData = this.getSessionData();
    // eslint-disable-next-line no-console
    if (process.env.DEBUG === 'true') {
      console.log('getResults - sessionId:', this.sessionId);
      console.log('getResults - session data:', this.sessionData);
    }
    const cards = [];
    
    if (this.sessionData && this.sessionData.cards) {
      if (process.env.DEBUG === 'true') {
        console.log('getResults - cards array length:', this.sessionData.cards.length);
      }
      this.sessionData.cards.forEach(cardId => {
        const card = ReactiveCache.getCard(cardId);
        if (process.env.DEBUG === 'true') {
          console.log('getResults - card:', cardId, card);
        }
        cards.push(card);
      });
      this.queryErrors = this.sessionData.errors || [];
    } else {
      if (process.env.DEBUG === 'true') {
        console.log('getResults - no sessionData or no cards array, trying direct card search');
      }
      // Fallback: try to get cards directly from the client-side collection
      // Use a more efficient query with limit and sort
      const selector = {
        type: 'cardType-card',
        dueAt: { $exists: true, $nin: [null, ''] }
      };
      const options = {
        sort: { dueAt: 1 }, // Sort by due date ascending (oldest first)
        limit: 100 // Limit to 100 cards for performance
      };
      const allCards = Cards.find(selector, options).fetch();
      if (process.env.DEBUG === 'true') {
        console.log('getResults - direct card search found:', allCards ? allCards.length : 0, 'cards');
      }
      
      if (allCards && allCards.length > 0) {
        allCards.forEach(card => {
          if (card && card._id) {
            cards.push(card);
          }
        });
      }
      
      this.queryErrors = [];
    }
    if (this.queryErrors.length) {
      // console.log('queryErrors:', this.queryErrorMessages());
      this.hasQueryErrors.set(true);
      // return null;
    }
    this.debug.set(new QueryDebug(this.sessionData ? this.sessionData.debug : null));
    if (process.env.DEBUG === 'true') {
      console.log('debug:', this.debug.get().get());
      console.log('debug.show():', this.debug.get().show());
      console.log('debug.showSelector():', this.debug.get().showSelector());
    }

    if (cards) {
      if (this.sessionData) {
        this.totalHits = this.sessionData.totalHits || 0;
        this.resultsCount = cards.length;
        this.resultsStart = this.sessionData.lastHit - this.resultsCount + 1;
        this.resultsEnd = this.sessionData.lastHit;
        this.resultsHeading.set(this.getResultsHeading());
        this.results.set(cards);
        this.hasNextPage.set(this.sessionData.lastHit < this.sessionData.totalHits);
        this.hasPreviousPage.set(
          this.sessionData.lastHit - this.sessionData.resultsCount > 0,
        );
      } else {
        this.totalHits = cards.length;
        this.resultsCount = cards.length;
        this.resultsStart = 1;
        this.resultsEnd = cards.length;
        this.resultsHeading.set(this.getResultsHeading());
        this.results.set(cards);
        this.hasNextPage.set(false);
        this.hasPreviousPage.set(false);
      }
      return cards;
    }

    this.resultsCount = 0;
    return null;
  }

  stopSubscription() {
    if (this.subscriptionHandle) {
      this.subscriptionHandle.stop();
    }
  }

  getSubscription(queryParams) {
    if (process.env.DEBUG === 'true') {
      console.log('Subscribing to globalSearch with:', {
        sessionId: this.sessionId,
        params: queryParams.params,
        text: queryParams.text
      });
    }

    // Subscribe to both globalSearch and sessionData
    const globalSearchHandle = Meteor.subscribe(
      'globalSearch',
      this.sessionId,
      queryParams.params,
      queryParams.text,
      this.subscriptionCallbacks,
    );
    
    const sessionDataHandle = Meteor.subscribe('sessionData', this.sessionId);
    if (process.env.DEBUG === 'true') {
      console.log('Subscribed to sessionData with sessionId:', this.sessionId);
    }

    return globalSearchHandle;
  }

  runGlobalSearch(queryParams) {
    this.searching.set(true);
    this.debug.set(new QueryDebug());
    this.stopSubscription();
    this.subscriptionHandle = this.getSubscription(queryParams);
  }

  queryErrorMessages() {
    const messages = [];

    this.queryErrors.forEach(err => {
      let value = err.color ? TAPi18n.__(`color-${err.value}`) : err.value;
      if (!value) {
        value = err.value;
      }
      messages.push(TAPi18n.__(err.tag, value));
    });

    return messages;
  }

  nextPage() {
    this.searching.set(true);
    this.stopSubscription();
    this.subscriptionHandle = Meteor.subscribe(
      'nextPage',
      this.sessionId,
      this.subscriptionCallbacks,
    );
  }

  previousPage() {
    this.searching.set(true);
    this.stopSubscription();
    this.subscriptionHandle = Meteor.subscribe(
      'previousPage',
      this.sessionId,
      this.subscriptionCallbacks,
    );
  }

  getResultsHeading() {
    if (this.resultsCount === 0) {
      return TAPi18n.__('no-cards-found');
    } else if (this.resultsCount === 1) {
      return TAPi18n.__('one-card-found');
    } else if (this.resultsCount === this.totalHits) {
      return TAPi18n.__('n-cards-found', {sprintf: [this.resultsCount]});
    }

    return TAPi18n.__('n-n-of-n-cards-found', {
      start: this.resultsStart,
      end: this.resultsEnd,
      total: this.totalHits,
    });
  }

  getSearchHref() {
    const baseUrl = window.location.href.replace(/([?#].*$|\s*$)/, '');
    return `${baseUrl}?q=${encodeURIComponent(this.query.get())}`;
  }

  events() {
    return [
      {
        'click .js-next-page'(evt) {
          evt.preventDefault();
          this.nextPage();
        },
        'click .js-previous-page'(evt) {
          evt.preventDefault();
          this.previousPage();
        },
      },
    ];
  }
}
