<?php

use Typesense\Client;

require_once SUPAPRESS_PLUGIN_DIR . '/includes/book.php';

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

class TypeSense_SupaPress_Book extends SupaPress_Book {
    public function get_publication_date() {
		return $this->_get('publicationDate');
	}

    public function get_sales_date() {
		return $this->_get('saleDate');
	}

    public function get_publisher_text() {
		return $this->book?->publisher ?? "";
	}

    public function get_imprint_text() {
		return $this->book?->imprint ?? "";
	}

    public function get_seo_title() {
	    return preg_replace('/-+/', '-', preg_replace('/[^\w\-]+/u', '', preg_replace('/\s+/u', '-', strtolower($this->get_title()))));
	}

    public function the_publication_date( $before = '<p class="sp__the-publication-date">', $after = '</p>', $echo = true ) {
		$date = '';
		/** @type stdClass $publicationDate */
		$publicationDate = $this->get_publication_date();

		if ( isset( $this->properties['show_pubdate'] ) && $this->properties['show_pubdate'] !== 'on' ) {
			return '';
		}

		if( !isset( $publicationDate ) ) {
			return '';
		}

		$date = (new DateTime())->setTimestamp($publicationDate);

		if( empty( $date ) ) {
			return '';
		}
		
		if ( isset( $this->properties['pub_date_format'] ) && $this->properties['pub_date_format'] !== '' ) {
			$date = $date->format( $this->properties['pub_date_format'] );
		}

		$date = "{$before}{$date}{$after}";

		if ( $echo ) {
			echo $date;
		} else {
			return $date;
		}
	}

    public function the_sales_date( $before = '<p class="sp__the-sales-date">', $after = '</p>', $echo = true ) {
		$date = '';
		$salesDate = $this->get_sales_date();

		if ( isset( $this->properties['show_sales_date'] ) && $this->properties['show_sales_date'] !== 'on' ) {
			return '';
		}

		//Map TypeSense API
		$date = $salesDate !== 1 ? (new DateTime())->setTimestamp($salesDate) : "";

		if( empty( $date ) ) {
			return '';
		}

		if ( isset( $this->properties['sales_date_format'] ) && $this->properties['sales_date_format'] !== '' ) {
			$date = $date->format( $this->properties['sales_date_format'] );
		}

		/** @type object $salesDate */
		$date = "{$before}{$date}{$after}";

		if ( $echo ) {
			echo $date;
		} else {
			return $date;
		}
	}

    public function the_price( $before = '<p class="sp__the-price">', $after = '</p>', $echo = true ) {
		$price      = '';
		$prices     = array();
		$bookPrices = $this->get_price();

		if( isset( $this->properties['show_price'] ) && $this->properties['show_price'] !== 'on' && !isset( $this->properties['price'] ) ) {
			return '';
		}

		if( !empty( $bookPrices ) ) {
			foreach ( $this->properties['price'] as $p ) {
				$currency = $this->get_currency_symbol($p);
				if ( isset( $bookPrices[ $p ] ) ) {
					$price .= "{$before}{$currency}{$bookPrices[$p]}{$after}";
				}
			}
		}

		if( empty( $price ) ) {
			return '';
		}

		if ( $echo ) {
			echo $price;
		} else {
			return $price;
		}
	}

    public function the_author( $before = '<p class="sp__the-author">', $after = '</p>', $echo = true, $separator = ', ', $index = false ) {
		$authors      = array();
		$contributors = $this->get_author();

		if ( isset( $this->properties['show_author'] ) && $this->properties['show_author'] !== 'on' ) {
            return '';
        }
			
		if( !empty( $contributors ) ) {
			foreach ( $contributors as $i => $contributor ) {
				if ( is_int( $index ) && $index !== $i ) {
					continue;
				}
				if ( !empty( $contributor['name'] ) ) {
					$authors[] = $contributor['name'];
				}
			}
		}

		if ( empty( $authors ) ) {
			return '';
		}

        $authors = $before . implode( $separator, $authors ) . $after;
		
		if ( $echo ) {
			echo $authors;
		} else {
			return $authors;
		}
	}

    public function the_series( $before = '<p class="sp__the-series">', $after = '</p>', $echo = true ) {
		$series = $this->get_series();

        if ( empty( $series ) ) {
			return '';
		}
		
		$series = "{$before} {$series} {$after}";

		if ( $echo ) {
			echo $series;
		} else {
			return $series;
		}
	}
}


 function supapress_is_ts_api() {
	if( defined( 'TYPESENSE_API' ) && TYPESENSE_API === true ) {
		return true;
	}

	return false;
}

function supapress_set_typesense_client() {
	$apiKey = (string) get_option( 'typesense_api_key' );
	$host = (string) get_option( 'typesense_host' );

	if( empty( $apiKey ) && empty( $host ) ) {
		return;
	}

	$client = new Client([
		'nodes' => [
			[
				'host' => $host, 
				'port' => '',
				'protocol' => 'https'  
			]
		],
		'api_key' => $apiKey,
		'connection_timeout_seconds' => 2
	]);

	return $client;
}

function supapress_call_typesense( $searchParameters = array() ) {
	
	$client = supapress_set_typesense_client();

	if( empty( $client ) ) {
		return;
	}
	
	$catalogName = (string) get_option('typesense_catalog');

	if( empty( $catalogName ) ) {
		return;
	}

	try {
        // Search in the given catalog
        $results = $client->collections[$catalogName]->documents->search($searchParameters);

        // Return the facet counts for 'format'
        return $results ?? [];

    } catch (Exception $e) {
        return ['error' => $e->getMessage()];
    }
}

function supapress_ts_search_args($params, $properties, $args = []) {
    $priceProp = $properties['price'][0] ?? '';
    $order = $params['order'] ?? '';

    $sortByOptions = [
        'as-entered'        => '',
        'publishdate-desc'  => 'publicationDate:desc',
        'publishdate-asc'   => 'publicationDate:asc',
        'title-az'          => 'title:asc',
        'title-za'          => 'title:desc',
    ] + (!empty($priceProp) ? [
        'price-asc'  => "prices.{$priceProp}:asc",
        'price-desc' => "prices.{$priceProp}:desc"
    ] : []);

    if (!empty($sortByOptions[$order])) {
        $args['sort_by'] = $sortByOptions[$order];
    }

    foreach (['isbns' => 'isbn13:[%s]', 'collection' => "collections.list.name:='%s'", 'publisher' => "publisher:='%s'", 'imprint' => "imprint:='%s'"] as $key => $format) {
        if (!empty($params[$key])) {
            $args['filter_by'] = sprintf($format, $params[$key]);
            break;
        }
    }
	

    if (!empty($args['filter_by'])) {
        $args += ['q' => '*', 'per_page' => $params['amount'] ?? "250"];
    }

    return $args;
}


function supapress_call_typesense_search( $params, $properties ) {
	
	$args = supapress_ts_search_args( $params, $properties );
	
	$orderedIsbns = !empty( $params['isbns'] ) && $params["order"] === 'as-entered' ? explode(',', $params['isbns']) : "";
	
	$results = supapress_call_typesense( $args );

	return supapress_map_search_ts_data( $results, $orderedIsbns );
}

function supapress_map_search_ts_data($results, $orderedIsbns = array() ) {
	if( empty( $results["hits"] ) ) {
		return 'Something went wrong';
	}

	if (!empty($orderedIsbns)) {
		$results['hits'] = supapress_reorder_hits_by_isbn($results['hits'], $orderedIsbns);
	}
	
	$result = array();

	foreach ($results["hits"] as $item) {
		if (!isset($item['document'])) {
			continue;
		}
		
		$result[] = (object) $item['document'];
	}

	if( empty( $result ) ) {
		return;
	}
	//map folio API
	return (object) [
		"search" => $result
	];
}

function supapress_reorder_hits_by_isbn($hits, $orderedIsbns) {

	if( empty( $hits ) && empty( $orderedIsbns ) ) {
		return '';
	}

	$hitsByIsbn = [];

	foreach ($hits as $hit) {
		$isbn = $hit['document']['isbn13'] ?? null;
		if ($isbn) {
			$hitsByIsbn[$isbn] = $hit;
		}
	}

	$reorderedHits = [];
	foreach ($orderedIsbns as $isbn) {
		if (isset($hitsByIsbn[$isbn])) {
			$reorderedHits[] = $hitsByIsbn[$isbn];
		}
	}

	return $reorderedHits;
}

function supapress_transform_filter_ts_data($data, $filter) {
	$result = [];

	if( empty( $data ) ) {
		return '';
	}

	foreach ($data as &$item) {
		$item['seo_name'] = $item['highlighted'];
		unset($item['highlighted']);
		
		$item['name'] = $item['value'];
		unset($item['value']);

		if (isset($item['seo_name'])) {
			$result[$item['seo_name']] = $item; 
		} else {
			$result[] = $item;
		}
	}

	//map folio API
	$result = [
		"filters" => [
			$filter => [
				"values" => $result
			]
		]
	];
	
	return $result;
}

function supapress_api_call($endpoint, $params = []) {

    if ( supapress_is_ts_api() ) {
        switch ($endpoint) {
            case 'bulk_isbn_lookup':
                $queryParams = [
                    'q'         => '*',
                    'filter_by' => 'isbn13:[' . esc_html($params['ISBNs']) . ']'
                ];
                $results = supapress_call_typesense($queryParams);
                return supapress_map_search_ts_data($results);
            case 'predictive':
                $queryParams = [
                    'q'       => esc_html($params['term']),
                    'query_by' => 'isbn13'
                ];
                $results = supapress_call_typesense($queryParams);
                return ['predictive' => [$results["hits"][0]["document"] ?? ""]];
            case 'collections':
                $queryParams = [
                    'q'        => '*',
                    'facet_by' => 'collections.list.name'
                ];
                $results = supapress_call_typesense($queryParams);
                return supapress_transform_filter_ts_data($results["facet_counts"][0]["counts"] ?? "", 'collection');
        }
    } else {
        switch ($endpoint) {
            case 'bulk_isbn_lookup':
                return supapress_call_supafolio('search', [
                    'isbns'  => $params['ISBNs'],
                    'amount' => 100
                ], [], false);
            case 'predictive':
                return supapress_call_supafolio('predictive', [
                    'keyword' => esc_html($params['term']),
                    'amount'  => 10,
                    'type'    => 'Products'
                ], [], false);
            case 'collections':
                return supapress_call_supafolio('searchfilter', [
                    'filters' => 'collection'
                ]);
        }
    }

    return null;
}