/**
 * Copyright (c) 2025 SoftCorporation LLC. All rights reserved.
 *
 * The Software License, Version 1.0
 *
 * SoftCorporation LLC. grants you ("Licensee") a non-exclusive, royalty free,
 * license to use, modify and redistribute this software in source and binary
 * code form, provided that the following conditions are met:
 *
 * 1. The end-user documentation included with the redistribution,
 *    if any, must include the following acknowledgment:
 *       "This product includes software developed by the
 *        SoftCorporation LLC. (http://www.softcorporation.com)."
 *    Alternately, this acknowledgment may appear in the software itself,
 *    if and wherever such third-party acknowledgments normally appear.
 *
 * 2. This software and SoftCorporation name must not be used to
 *    promote products derived from the software without prior
 *    written permission. For written permission, please contact
 *    info@softcorporation.com.
 *
 * This software is provided "AS IS," without a warranty of any kind.
 * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
 * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
 * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
 * IN NO EVENT SHALL THE SOFTCORPORATION BE LIABLE FOR ANY DIRECT,
 * INDIRECT, INCIDENTAL OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION).
 *
 */
package com.softcorporation.sandi.search.service.solr;

import java.util.Arrays;
import java.util.Collections;
import java.util.List;

import org.apache.solr.client.solrj.SolrQuery;
import org.apache.solr.client.solrj.SolrRequest.METHOD;
import org.apache.solr.client.solrj.response.QueryResponse;
import org.apache.solr.common.SolrDocument;
import org.apache.solr.common.SolrDocumentList;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.softcorporation.sandi.base.model.Client;
import com.softcorporation.sandi.base.service.solr.SolrService;
import com.softcorporation.sandi.base.util.ClientException;
import com.softcorporation.sandi.base.util.Constants;
import com.softcorporation.sandi.base.util.Utils;
import com.softcorporation.sandi.search.model.TypeAheadRequest;
import com.softcorporation.sandi.search.model.TypeAheadResponse;
import com.softcorporation.sandi.search.service.TypeAheadService;
import com.softcorporation.sandi.search.util.SearchException;
import com.softcorporation.util.StringUtil;

@Service
public class SolrTypeAheadService extends TypeAheadService {

    private static final Logger LOGGER = LoggerFactory.getLogger(SolrTypeAheadService.class);
    
    @Autowired
    private SolrService solrService;

    public TypeAheadResponse search(TypeAheadRequest request) throws SearchException {
    	long timeStart = System.currentTimeMillis();
    	String requestId = request.getRequestId();
    	String clientId = request.getClientId();
        String query = request.getQuery();
        
	    if (request.isDebug())
	    {
            LOGGER.debug("[{}] Type ahead request: '{}' for client: {}", requestId, query, clientId);
	    }

	    try {
        	String searchCollections = getCollections(request, clientId);
            
            TypeAheadResponse typeAheadResponse = new TypeAheadResponse();

            String cleanQuery = clean(query);
            List<String> queryWords = Arrays.asList(cleanQuery.split(cleanQuery, ' '));
    	    if (cleanQuery.length() > 0)
    	    {

    	    	
    	    	
    	    	
    	    	
                typeAheadResponse.setResults(results);
    	    } else {
    	    	typeAheadResponse.setResults(Collections.EMPTY_LIST);
    	    }        
        	long timeFinish = System.currentTimeMillis();
        	typeAheadResponse.setTook((int) (timeFinish - timeStart));
            return typeAheadResponse;
        } catch (Exception e) {
            LOGGER.error("[{}] Type Ahead search failed for query '{}': {}", requestId, query, e.getMessage());
            throw new SearchException(e.getMessage());
        }
    }

    public TypeAheadResponse search0(TypeAheadRequest request) throws SearchException {
    	long timeStart = System.currentTimeMillis();
    	String requestId = request.getRequestId();
    	String clientId = request.getClientId();
        String query = request.getQuery();
        
	    if (request.isDebug())
	    {
            LOGGER.debug("[{}] Type ahead request: '{}' for client: {}", requestId, query, clientId);
	    }

	    try {
        	String searchCollections = getCollections(request, clientId);
            
            TypeAheadResponse typeAheadResponse = new TypeAheadResponse();

            String cleanQuery = clean(query);
            List<String> queryWords = Arrays.asList(cleanQuery.split(cleanQuery, ' '));
    	    if (cleanQuery.length() > 0)
    	    {
                SolrQuery solrQuery = new SolrQuery();

        	    solrQuery.setQuery(makeQuery(queryWords, 4));
                QueryResponse response = solrService.getSolrClient().query(searchCollections, solrQuery, METHOD.GET);
//                LOGGER.debug("[{}] Searching typeahead collection(s): {} took {} ms", requestId, searchCollections, response.getQTime());

                ArrayList<SolrDocument> typeAheadSuggestions = new ArrayList<>();
                SolrDocumentList results = response.getResults();
                for (SolrDocument result : results) {
                	
                }
                if (results.size() < 5) {
                    solrQuery = new SolrQuery();
            	    solrQuery.setQuery(makeQuery(cleanQuery, 3));
            	    response = solrService.getSolrClient().query(searchCollections, solrQuery, METHOD.GET);
                    results = response.getResults();
//                  LOGGER.debug("[{}] Searching typeahead collection(s): {} took {} ms", requestId, searchCollections, response.getQTime());
                }
                
                
                
                
                typeAheadResponse.setResults(results);
    	    } else {
    	    	typeAheadResponse.setResults(Collections.EMPTY_LIST);
    	    }        
        	long timeFinish = System.currentTimeMillis();
        	typeAheadResponse.setTook((int) (timeFinish - timeStart));
            return typeAheadResponse;
        } catch (Exception e) {
            LOGGER.error("[{}] Type Ahead search failed for query '{}': {}", requestId, query, e.getMessage());
            throw new SearchException(e.getMessage());
        }
    }

    public String makeQuery(String cleanQuery, int maxNgram) throws ClientException {
    	StringBuilder sb = new StringBuilder();
        sb.append("text_edge:");
        sb.append(cleanQuery);
        if (cleanQuery.length() > 10) {
        	sb.append("~2");
        } else if (cleanQuery.length() > 5) {
        	sb.append("~1");
        }
      	sb.append(" AND _val_:count");
  	    return sb.toString();
    }
    
    public String getCollections(TypeAheadRequest request, String clientId) throws ClientException {
    	StringBuilder sb = new StringBuilder();
    	List<String> collections = Utils.stringToList(request.getSearchCollections(), false);
    	if (collections == null) {
    		Client client = request.getClient();
    		if (client == null) {
                throw new ClientException("Unknown client " + clientId);
    		}
    		sb.append(Constants.TA_PREFIX);
    		sb.append(client.getCollection());
    	} else {
    		for (String collection : collections) {
    			if (sb.length() > 0) {
    				sb.append(",");
    			}
    			sb.append(Constants.TA_PREFIX);
    			sb.append(collection);
    		}
    	}
		return sb.toString();
    }

}