<?php
// inc/tide-loader.php
// Single file that tries extremes[], if empty uses heights[], else fallback.

defined( 'ABSPATH' ) || exit;

require_once plugin_dir_path( __FILE__ ) . '/pro-timezone.php';

if ( ! function_exists( 'mwpl_lookup_timezone_from_coords' ) ) {
	function mwpl_lookup_timezone_from_coords( $mwpl_lat, $mwpl_lon ) {
		$api_key      = 'YOUR_TIMEZONEDB_API_KEY'; // Replace this with your key.
		$mwpl_url     = "http://api.timezonedb.com/v2.1/get-time-zone?key={$api_key}&format=json&by=position&lat={$mwpl_lat}&lng={$mwpl_lon}";
		error_log( '🌊📡 WT FETCH (CREDIT) lat=' . $mwpl_lat . ' lon=' . $mwpl_lon . ' days=' . $mwpl_days ); // phpcs:ignore
		$mwpl_response = wp_remote_get( $mwpl_url );

		if ( ! is_wp_error( $mwpl_response ) ) {
			$mwpl_body = json_decode( wp_remote_retrieve_body( $mwpl_response ), true );
			if ( ! empty( $mwpl_body['zoneName'] ) ) {
				return $mwpl_body['zoneName'];
			}
		}

		// Final fallback.
		return 'UTC';
	}
}

if ( ! function_exists( 'mwpl_format_tide_time_local' ) ) {
	function mwpl_format_tide_time_local( $utcTime, $locationTz = 'UTC' ) {
		try {
			$tz = new DateTimeZone( $locationTz );
			$dt = new DateTime( $utcTime, new DateTimeZone( 'UTC' ) );
			$dt->setTimezone( $tz );
			return $dt->format( 'g:i A' );
		} catch ( Exception $e ) {
			return $utcTime;
		}
	}
}

// Initialize the tide data array.
$mwpl_tide_data = array(
	'current_tide'    => null,
	'next_high'       => null,
	'next_low'        => null,
	'trend'           => null,
	'percent_between' => null,
	'timezone'        => 'UTC',
);

// 🔒 PRO ONLY: never fetch tide data in the free version.
if ( ! function_exists( 'mwpl_is_pro' ) || ! mwpl_is_pro() ) {
	// Leave $mwpl_tide_data as empty/defaults.
	return;
}

// Pull user’s WorldTides API key + lat/lon.
$mwpl_lat        = $atts['lat'] ?? null;
$mwpl_lon        = $atts['lon'] ?? null;
$mwpl_wt_api_key = get_option( 'multiweather_worldtides_key' );

// Days range (default 7). For fullscreen board we may request a longer range.
$mwpl_days = 7;
if ( isset( $atts['_mwpl_tide_days'] ) ) {
    $mwpl_days = (int) $atts['_mwpl_tide_days'];
    if ( $mwpl_days < 1 ) {
        $mwpl_days = 1;
    }
    if ( $mwpl_days > 31 ) {
        $mwpl_days = 31;
    }
}


error_log( "🌊🌐 Tide check: lat={$mwpl_lat}, lon={$mwpl_lon}, key=" . ( $mwpl_wt_api_key ?: 'none' ) ); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log

if ( ! $mwpl_wt_api_key || ! $mwpl_lat || ! $mwpl_lon ) {
	error_log( '🌊❌ Missing WorldTides config: key/lat/lon → falling back to Open-Meteo' ); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log
	require plugin_dir_path( __FILE__ ) . '/tide-loader-fallback.php';
	return;
}

error_log( "🌊🌐 Tide check: lat={$mwpl_lat}, lon={$mwpl_lon}, key={$mwpl_wt_api_key}" ); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log

$mwpl_cache_key = 'mw15_wt_tides_' . md5( "{$mwpl_lat}_{$mwpl_lon}_{$mwpl_days}" );
$mwpl_cached    = get_transient( $mwpl_cache_key );

// ✅ Negative cache: if we already learned there are no tides here, don't hit WorldTides again.
if ( is_array( $mwpl_cached ) && ! empty( $mwpl_cached['_mwpl_no_tides'] ) ) {
	require plugin_dir_path( __FILE__ ) . '/tide-loader-fallback.php';
	return;
}

// Prevent cache stampede: big pages / user-location rerender can trigger many concurrent tide requests.
$mwpl_lock_key = $mwpl_cache_key . '_lock';

// If another request is already fetching, wait briefly for it to populate the cache.
if ( ! $mwpl_cached && get_transient( $mwpl_lock_key ) ) {
	for ( $mwpl_i = 0; $mwpl_i < 6; $mwpl_i++ ) { // ~1.2s max
		usleep( 200000 ); // 200ms
		$mwpl_cached = get_transient( $mwpl_cache_key );
		if ( $mwpl_cached ) {
			break;
		}
	}

	// Still nothing? Fall back (don't hit WorldTides again).
	if ( ! $mwpl_cached ) {
		require plugin_dir_path( __FILE__ ) . '/tide-loader-fallback.php';
		return;
	}
}

// If we still have no cache, take the lock before fetching from WorldTides.
if ( ! $mwpl_cached ) {
	set_transient( $mwpl_lock_key, 1, 60 ); // lock for 60s
}


// Fetch from WorldTides if not cached.
if ( ! $mwpl_cached ) {
	$mwpl_start    = mwpl_gmdate( 'Y-m-d' );
	$mwpl_url      = "https://www.worldtides.info/api/v3?extremes&heights&days={$mwpl_days}&datum=LAT&lat={$mwpl_lat}&lon={$mwpl_lon}&key={$mwpl_wt_api_key}";
	$mwpl_response = wp_remote_get( $mwpl_url );

	if ( is_wp_error( $mwpl_response ) ) {
		delete_transient( $mwpl_lock_key );
		error_log( '🌊❌ WorldTides API error: ' . $mwpl_response->get_error_message() ); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log
	} else {
		$mwpl_body   = wp_remote_retrieve_body( $mwpl_response );
		$mwpl_cached = json_decode( $mwpl_body, true );

		if ( empty( $mwpl_cached['extremes'] ) && empty( $mwpl_cached['heights'] ) ) {
			error_log( '🌊⚠️ WorldTides API returned no extremes or heights — falling back to Open-Meteo.' ); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log

			// Cache "no tides here" briefly so inland locations don't burn credits.
			set_transient(
				$mwpl_cache_key,
				array(
					'_mwpl_no_tides' => 1,
					'_checked_at'    => time(),
				),
				6 * HOUR_IN_SECONDS
			);

			delete_transient( $mwpl_lock_key );
			require plugin_dir_path( __FILE__ ) . '/tide-loader-fallback.php';
			return;
		}

		// Pull custom cache TTL from settings.
		$mwpl_hours = (int) get_option( 'multiweather_tides_cache_interval', 24 ); // fallback 24 hours.
		$mwpl_ttl   = ( $mwpl_hours > 0 ) ? $mwpl_hours * HOUR_IN_SECONDS : DAY_IN_SECONDS; // minimum fallback.

		set_transient( $mwpl_cache_key, $mwpl_cached, $mwpl_ttl );
		delete_transient( $mwpl_lock_key );

		$mwpl_expires = time() + $mwpl_ttl;
	}
}

// If still nothing after trying WorldTides, fall back.
if ( ! $mwpl_cached ) {
	delete_transient( $mwpl_lock_key );
	error_log( '🌊❌ No cached WorldTides data after fetch — falling back to Open-Meteo.' ); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log
	require plugin_dir_path( __FILE__ ) . '/tide-loader-fallback.php';
	return;
}

error_log( "🌊🔍 lat: {$mwpl_lat} | lon: {$mwpl_lon} | key=" . ( $mwpl_wt_api_key ?: 'none' ) ); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log

// Primary path: extremes[].
if ( ! empty( $mwpl_cached['extremes'] ) ) {
	$mwpl_tides  = $mwpl_cached['extremes'];
	$mwpl_tzInfo = mwpl_get_location_time( $mwpl_lat, $mwpl_lon );

	$mwpl_timezone = ( isset( $mwpl_tzInfo['name'] ) && in_array( $mwpl_tzInfo['name'], timezone_identifiers_list(), true ) )
		? $mwpl_tzInfo['name']
		: 'UTC';

	error_log( "📌 Final timezone via pro-timezone: {$mwpl_timezone}" ); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log
	error_log( "✅ Final timezone used for card: {$mwpl_timezone}" ); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log
	error_log( "📌 Using lat: {$mwpl_lat}, lon: {$mwpl_lon} for timezone lookup" ); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log

	$mwpl_currentTide = null;
	$mwpl_nextHigh    = null;
	$mwpl_nextLow     = null;

	foreach ( $mwpl_tides as $mwpl_i => $mwpl_tide ) {
		$mwpl_t = strtotime( $mwpl_tide['date'] );
		if ( $mwpl_t > time() ) {
			$mwpl_currentTide = $mwpl_tides[ max( 0, $mwpl_i - 1 ) ];
			for ( $mwpl_j = $mwpl_i; $mwpl_j < count( $mwpl_tides ); $mwpl_j++ ) {
				if ( 'High' === $mwpl_tides[ $mwpl_j ]['type'] && ! $mwpl_nextHigh ) {
					$mwpl_nextHigh = $mwpl_tides[ $mwpl_j ];
				}
				if ( 'Low' === $mwpl_tides[ $mwpl_j ]['type'] && ! $mwpl_nextLow ) {
					$mwpl_nextLow = $mwpl_tides[ $mwpl_j ];
				}
				if ( $mwpl_nextHigh && $mwpl_nextLow ) {
					break;
				}
			}
			break;
		}
	}

	if ( $mwpl_currentTide && $mwpl_nextHigh && $mwpl_nextLow ) {
		$mwpl_from  = strtotime( $mwpl_currentTide['date'] );
		$mwpl_to    = strtotime( ( 'Low' === $mwpl_currentTide['type'] ) ? $mwpl_nextHigh['date'] : $mwpl_nextLow['date'] );
		$mwpl_trend = ( 'Low' === $mwpl_currentTide['type'] ) ? 'Rising' : 'Falling';

		$mwpl_percent_between = ( $mwpl_to !== $mwpl_from )
			? ( time() - $mwpl_from ) / max( 1, ( $mwpl_to - $mwpl_from ) )
			: 0.5;

		$mwpl_tide_data = array(
			'current_tide'    => round( $mwpl_currentTide['height'], 2 ),
			'next_high'       => array(
				'time'  => $mwpl_nextHigh['date'],
				'local' => mwpl_format_tide_time_local( $mwpl_nextHigh['date'], $mwpl_timezone ),
				'value' => round( $mwpl_nextHigh['height'], 2 ),
			),
			'next_low'        => array(
				'time'  => $mwpl_nextLow['date'],
				'local' => mwpl_format_tide_time_local( $mwpl_nextLow['date'], $mwpl_timezone ),
				'value' => round( $mwpl_nextLow['height'], 2 ),
			),
			'trend'           => $mwpl_trend,
			'percent_between' => max(
				0,
				min(
					1,
					( 'Falling' === $mwpl_trend ) ? $mwpl_percent_between : 1 - $mwpl_percent_between
				)
			),
			'timezone'        => $mwpl_timezone,
			'tide_source'     => 'WorldTides',
		);
	}

	

// Keep raw series for month view / graphs (safe extra keys; older cards ignore them).
$mwpl_tide_data['extremes'] = $mwpl_cached['extremes'] ?? array();
$mwpl_tide_data['heights']  = $mwpl_cached['heights'] ?? array();
$mwpl_tide_data['raw']      = $mwpl_cached;
$mwpl_tide_data['days']     = $mwpl_days;

// Add station info if available from WorldTides.
	if ( ! empty( $mwpl_cached['station'] ) ) {
		$mwpl_tide_data['station'] = array(
			'name'     => $mwpl_cached['station']['name'] ?? null,
			'lat'      => $mwpl_cached['station']['lat'] ?? null,
			'lon'      => $mwpl_cached['station']['lon'] ?? null,
			'distance' => $mwpl_cached['station']['distance'] ?? null,
		);
	}

	if ( $mwpl_currentTide ) {
		$mwpl_tide_data['last_tide'] = array(
			'time'  => $mwpl_currentTide['date'],
			'type'  => $mwpl_currentTide['type'],
			'value' => round( $mwpl_currentTide['height'], 2 ),
		);

		$mwpl_tide_data['next_tide'] = array(
			'time'  => ( 'Low' === $mwpl_currentTide['type'] ) ? $mwpl_nextHigh['date'] : $mwpl_nextLow['date'],
			'type'  => ( 'Low' === $mwpl_currentTide['type'] ) ? 'High' : 'Low',
			'value' => round(
				( 'Low' === $mwpl_currentTide['type'] ) ? $mwpl_nextHigh['height'] : $mwpl_nextLow['height'],
				2
			),
		);
	}
}

// Fallback if no extremes, try heights.
if ( empty( $mwpl_tide_data['current_tide'] ) && ! empty( $mwpl_cached['heights'] ) ) {
	$mwpl_tzInfo = mwpl_get_location_time( $mwpl_lat, $mwpl_lon );

	$mwpl_timezone = ( isset( $mwpl_tzInfo['name'] ) && in_array( $mwpl_tzInfo['name'], timezone_identifiers_list(), true ) )
		? $mwpl_tzInfo['name']
		: 'UTC';

	$mwpl_latestHeight = null;
	$mwpl_latestTime   = null;

	foreach ( $mwpl_cached['heights'] as $mwpl_h ) {
		$mwpl_t = strtotime( $mwpl_h['date'] );
		if ( $mwpl_t <= time() ) {
			$mwpl_latestHeight = $mwpl_h['height'];
			$mwpl_latestTime   = $mwpl_h['date'];
		} else {
			break;
		}
	}

	if ( null !== $mwpl_latestHeight ) {
		$mwpl_tide_data = array(
			'current_tide'    => round( $mwpl_latestHeight, 2 ),
			'next_high'       => array(
				'time'  => null,
				'local' => null,
				'value' => null,
			),
			'next_low'        => array(
				'time'  => null,
				'local' => null,
				'value' => null,
			),
			'trend'           => null,
			'percent_between' => isset( $mwpl_percent_between )
				? max( 0, min( 1, $mwpl_percent_between ) )
				: 0.5,
			'timezone'        => $mwpl_timezone,
			'tide_source'     => 'WorldTides (heights fallback)',
		);
	}
}

// Final fallback to Open-Meteo if WorldTides gives nothing.
if ( empty( $mwpl_tide_data['current_tide'] ) ) {
	require_once plugin_dir_path( __FILE__ ) . '/tide-loader-fallback.php';
}
