/*
 * googleservice process/mod.rs
 * - route incoming nats requests to their specific functions
 *
 * Copyright (C) 2025 Real Microsoft, LLC
 *
 * This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, version 3.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
*/

use std::sync::Arc;
use asklyphe_common::nats::bingservice::{BingServiceQuery, BingServiceRequest, BingServiceResponse, SearchResponse};
use crate::google;
use crate::google::GoogleQueryError;

pub async fn process(query: BingServiceQuery) -> BingServiceResponse {
    // a future is used so that the whole program doesn't die if an algorithm panics
    let response = tokio::spawn(async move {
        match query.request {
            BingServiceRequest::SearchRequest(q) => {
                let res = google::query_google(q.query).await;
                if let Err(e) = res {
                    match e {
                        GoogleQueryError::CouldNotSendRequest => {
                            BingServiceResponse::OtherError("google failed".to_string())
                        }
                        GoogleQueryError::CouldNotDeserialize => {
                            BingServiceResponse::OtherError("google failed".to_string())
                        }
                    }
                } else {
                    BingServiceResponse::SearchResponse(SearchResponse {
                        results: res.unwrap(),
                        blocked: vec![],
                    })
                }
            }
            BingServiceRequest::ImageRequest(q) => {
                const IMAGE_PAGES: usize = 1;
                let mut all_results = vec![];
                let mut error = None;
                for page in 0..IMAGE_PAGES {
                    let res = google::query_google_images(q.query.clone(), page * 20).await;
                    if let Err(e) = res {
                        error = Some(match e {
                            GoogleQueryError::CouldNotSendRequest => {
                                BingServiceResponse::OtherError("bing failed".to_string())
                            }
                            GoogleQueryError::CouldNotDeserialize => {
                                BingServiceResponse::OtherError("bing failed".to_string())
                            }
                        });
                        break;
                    } else {
                        all_results.extend(res.unwrap());
                    }
                }
                if !all_results.is_empty() {
                    BingServiceResponse::ImageResponse(all_results)
                } else {
                    error.unwrap_or(BingServiceResponse::OtherError(
                        "bing failed".to_string()))
                }
            }
        }}).await;

    if let Ok(response) = response {
        response
    } else if let Err(e) = response {
        BingServiceResponse::OtherError(e.to_string())
    } else {
        unreachable!()
    }
}