<?php

/*
Plugin Name:       Nextlevel Delivery
Description:       Add the Nextlevel delivery shipping options
Author:            Dan Goriaynov
Version:           1.0.25
WC tested up to:   6.7
Author URI:        https://nextlevel.delivery/
Plugin URI:        https://github.com/dele/wp-nextlevel
License:           GNU General Public License, version 2
License URI:       https://www.gnu.org/licenses/gpl-2.0.en.html
Domain Path:       /languages/
Text Domain:       nextlevel_delivery
*/


if ( ! defined( 'ABSPATH' ) ) {
	exit; // Exit if accessed directly....
}

if ( ! in_array( 'woocommerce/woocommerce.php', apply_filters( 'active_plugins', get_option( 'active_plugins' ) ) ) ) {
//    wc_add_notice(__( 'Please enable WooCommerce for this plug-in to work properly.', 'nextlevel_delivery' ), 'error');
	return false;
}

if ( ! defined('NELE_PLUGIN_VERSION'))
	define('NELE_PLUGIN_VERSION', '1.0');

if ( ! defined('NELE_PLUGIN_NAME'))
    define('NELE_PLUGIN_NAME', basename(dirname(__FILE__)));

if ( ! defined('NELE_PLUGIN_URL'))
	define( 'NELE_PLUGIN_URL', plugin_dir_url( __FILE__ ) );

if ( ! defined('NELE_PLUGIN_ROOT_DIR'))
    define( 'NELE_PLUGIN_ROOT_DIR', plugin_dir_path( __FILE__ ) );

add_action( 'before_woocommerce_init', function() {
	if ( class_exists( \Automattic\WooCommerce\Utilities\FeaturesUtil::class ) ) {
		\Automattic\WooCommerce\Utilities\FeaturesUtil::declare_compatibility( 'custom_order_tables', __FILE__, true );
	}
    if ( class_exists( '\Automattic\WooCommerce\Utilities\FeaturesUtil' ) ) {
        \Automattic\WooCommerce\Utilities\FeaturesUtil::declare_compatibility( 'cart_checkout_blocks', __FILE__, false );
    }
} );

require_once NELE_PLUGIN_ROOT_DIR . 'admin/shipping_method.php';
require_once NELE_PLUGIN_ROOT_DIR . 'admin/checkout.php';
require_once NELE_PLUGIN_ROOT_DIR . 'admin/orders.php';
require_once NELE_PLUGIN_ROOT_DIR . 'admin/db.php';
//require_once NELE_PLUGIN_ROOT_DIR . 'admin/data/export.php';

function neleDbInsertTableData($forceUpdate = false): bool {
	write_log("neleDbInsertTableData started");
	$parent_obj = nele_parent_obj();
	if ($parent_obj->is_disabled()) {
		write_log("neleDbInsertTableData nele is disabled");
		return false;
	}
	$inserted_countries = 0;
	$inserted_places = 0;
	$inserted_offices = 0;
	$inserted_streets = 0;
	$creds = $parent_obj->creds;
	$countries = nele_api_countries($creds);
	write_log("got countries");
	foreach ($countries as $country) {
		write_log($country);
        $couriers = array();
        foreach ($country->couriers_in_detail as $courier_details) {
			write_log($courier_details);
            if ($courier_details->to_address === true || $courier_details->to_office === true) {
                $couriers[] = $courier_details->name;
            }
        }
        if (empty($couriers)) {
			write_log("no couriers configured for " . $country);
            continue;  // skip countries which do not have any couriers configured for them
        }
		nele_db_insert_country($country->id, $country->name, $country->code, $country->currency);
		$inserted_countries += 1;
		$country_code = $country->code;
        $streets = nele_api_streets($creds, $country_code);
        foreach ($streets as $street) {
            nele_db_insert_street($street->id, $street->place->country_id, $street->place->id, $street->name, $street->post_code);
            $inserted_streets += 1;
        }
        $places = nele_api_places($creds, $country->id);
        foreach ($places as $place) {
            nele_db_insert_place($place->id, $place->country_id, $place->name, $place->name_en ?? '', $place->region ?? $place->name, $place->municipality ?? '', $place->post_code, (array) $place->couriers ?? array());
            $inserted_places += 1;
        }
        $offices = nele_api_offices($creds, $country->id);
        foreach ($offices as $office) {
            $courier = $office->subcontractor;
            if (in_array($courier, $couriers)) {
                nele_db_insert_office($office->id, $office->country_id, $office->place_id, $office->office_id, $office->name, $office->address, $office->post_code, $courier, $office->is_machine);
                $inserted_offices += 1;
            }
        }
	}
	write_log("neleDbInsertTableData inserted_countries=$inserted_countries, inserted_places=$inserted_places, inserted_offices=$inserted_offices, inserted_streets=$inserted_streets");
	return $forceUpdate || neleDbIsPermitUpgrade($inserted_countries, $inserted_places, $inserted_offices, $inserted_streets);
}

function neleDbIsPermitUpgrade($inserted_countries, $inserted_places, $inserted_offices, $inserted_streets): bool {
	return $inserted_countries > 0 && $inserted_places > 0 && $inserted_offices > 0 && $inserted_streets > 0;
}

function neleDbRefreshTableDataForce() {
	neleDbRefreshTableData( true );
}

function neleDbRefreshTableData($forceUpdate = false) {
	if (get_transient('nele_upgrade_running')) {
		write_log("neleRefreshTableData: cancelling new upgrade since old one has not finished yet");
		return;
	}
	write_log("neleDbRefreshTableData: started");
	nele_clear_db_errors();
	try {
		update_option("nele_setup_completed", false);
		set_transient( 'nele_upgrade_running', true, 10 * MINUTE_IN_SECONDS );
		nele_db_truncate_tables();
		write_log("tables truncated");
		if ( ! neleDbInsertTableData( $forceUpdate ) ) {
			write_log( "neleRefreshTableData: Didn't insert any data" );
			return;
		}
		nele_db_truncate_tables( true );
		write_log("tables truncated: prod");
		nele_db_mark_as_prod();
		// do the actual DB operations for each delivery method we have enabled
		nele_db_execute_queries();
		write_log("finished running db queries");
	} catch (Throwable $e1) {
		$msg = __('Error doing initial setup of the NextLevel delivery plugin', 'nextlevel_delivery') . '<br/>Caught exception: ' .  $e1->getMessage();
		nele_add_db_error($msg);
	} finally {
		write_log("neleDbRefreshTableData: finally");
		// rollback all the pending DB operations
		nele_db_clear_queries();
		set_transient('nele_upgrade_running', true, MINUTE_IN_SECONDS);

		global $nele_places_table, $nele_offices_table;
		try {
			$countries_inserted = nele_db_countries();
			$places_inserted = nele_db_amount($nele_places_table);
			$offices_inserted = nele_db_amount($nele_offices_table);
		} catch (Exception $e) {
			$msg = __('Error getting data from the NextLevel tables', 'nextlevel_delivery') . '<br/>Caught exception: ' . $e->getMessage();
			nele_add_db_error($msg);
			set_transient('nele_upgrade_running', false);
			return;
		}
		if (empty($countries_inserted) || $places_inserted == 0 || $offices_inserted == 0) {
			$contact = "";
			$msg = __('NextLevel delivery method is not working.', 'nextlevel_delivery') . '<br/>' .
			       __('Please contact us to place your order and get this fixed', 'nextlevel_delivery') . (empty($contact) ? '' : ': <b>' . $contact . '</b>');
			nele_add_db_error($msg);
			set_transient('nele_upgrade_running', false);
			return;
		}
		update_option("nele_setup_completed", true);
		set_transient('nele_upgrade_running', false);
	}
}

add_action( 'neleUpdateDbHook', 'neleDbRefreshTableDataForce' );

function neleScheduleImmediateDataRefresh() {
	nele_shipping_method_init();

	$nele_shipping = new WC_NextLevel_Shipping_Method;
	$hook_name = 'neleUpdateDbHook';
	if ($nele_shipping->is_disabled() || wp_next_scheduled( $hook_name ) ) {
		return;
	}
	wp_schedule_single_event(time(), $hook_name);
	write_log($hook_name." scheduled");
}

add_action('wp_ajax_nele_refresh_table_data', 'neleScheduleImmediateDataRefresh');

function neleSetupDailyRun() {
	if (wp_next_scheduled( 'neleDailyDbHook' ) ) {
		return;
	}
    $hours = str_pad(rand(1, 6), 2, '0', STR_PAD_LEFT);
    $minutes = str_pad(rand(0, 59), 2, '0', STR_PAD_LEFT);
	wp_schedule_event( strtotime($hours . ':' . $minutes . ':00'), 'daily', 'neleDailyDbHook');
	write_log("neleDailyDbHook scheduled");
}

add_action( 'neleDailyDbHook', 'neleSetupDailyRun' );

function neleFillInitialData() {
	write_log("neleFillInitialData started");
	global $nele_db_version;
	if (get_site_option( 'nele_db_version' ) != $nele_db_version) {
		nele_db_drop_tables();
	}
	nele_db_create_tables();
	neleScheduleImmediateDataRefresh();
	neleSetupDailyRun();  // do the tables re-population every day
}
register_activation_hook( __FILE__, 'neleFillInitialData' );

function neleDeactivateDailyDataRefresh() {
	try {
		wp_clear_scheduled_hook( 'neleUpdateDbHook' );
		wp_clear_scheduled_hook( 'neleDailyDbHook' );
	} catch (Exception $e) {
		write_log("Deactivate: Error clearing scheduled DB hooks");
	}
	nele_db_drop_tables();
	write_log("neleDeactivateDailyDataRefresh finished");
}
register_deactivation_hook( __FILE__, 'neleDeactivateDailyDataRefresh' );

/* Add a link to the settings page on the plugins.php page. */
function neleAddPluginPageSettingsLink( $links ): array
{
	array_unshift($links, '<a href="admin.php?page=wc-settings&tab=shipping&section=nele_shipping_method">' . __('Settings', 'nextlevel_delivery') . '</a>');
	return $links;
}
add_filter('plugin_action_links_'.plugin_basename(__FILE__), 'neleAddPluginPageSettingsLink' );

add_action( 'plugins_loaded', 'neleI10nLoad', 0 );
function neleI10nLoad() {
    load_plugin_textdomain( 'nextlevel_delivery', false, NELE_PLUGIN_NAME . '/languages/' );
}