<?php

namespace Simplyin\Simplyin_W_Plugin\Lib\Session;

use WC_Session;

class Simplyin_Session {

	private static ?WC_Session $wc_session = null;

	private const COOKIE_NAME = 'simplyin_session';

	private const COOKIE_PATH = '/';

	private static ?array $cached_data = null;

	private static ?string $cookie_value_cache = null;


	private function init_once() {
		if ( is_admin() && ! wp_doing_ajax() && ! defined( 'REST_REQUEST' ) ) {
			if ( self::$cached_data === null ) {
				self::$cached_data = [];
			}

			return;
		}

		if ( self::$cached_data ) {
			return;
		}

		$session_id_from_cookie = $this->get_session_id_from_cookie();

		if ( empty( $session_id_from_cookie ) ) {
			if ( ! headers_sent() ) {
				$this->install();
			}

			return;
		}

		$session_id = $this->get_simplyin_session_id();

		if ( ! $session_id || ( $session_id_from_cookie !== $session_id ) ) {
			$this->install();
		}

	}

	private function get_wc_session() {
		if ( self::$wc_session instanceof \WC_Session ) {
			return self::$wc_session;
		}

		if ( function_exists( 'WC' ) && isset( WC()->session ) && WC()->session instanceof \WC_Session ) {
			self::$wc_session = WC()->session;

			return self::$wc_session;
		}

		return null;
	}


	public function set( string $key, $value ) {
		$this->init_once();
		$simplyin_data         = $this->get_simplyin_data();
		$simplyin_data[ $key ] = $value;
		$this->save_simplyin_data( $simplyin_data );

	}

	public function get( string $key, $default = null ) {
		$this->init_once();
		$simplyin_data = $this->get_simplyin_data();

		if ( isset( $simplyin_data[ $key ] ) ) {
			$return = $simplyin_data[ $key ];
		} else {
			$return = $default;
		}

		simplyin()->get_simplyin_logger()->log_if_wpdebug_on(
			sprintf( "[Simplyin_Session] [get] %s",
				wp_json_encode( [
					'session_id'     => $this->get_simplyin_session_id(),
					'key'            => $key,
					'returned value' => $return,
				] ),
			),
			'session' );

		return $return;
	}

	private function get_simplyin_session_id(): ?string {
		$session_data = $this->get_simplyin_data();

		if ( ! isset( $session_data['id'] ) ) {
			return null;
		}

		return $session_data['id'];
	}


	private function get_simplyin_data(): array {
		if ( self::$cached_data !== null ) {
			return self::$cached_data;
		}

		$wc_session = $this->get_wc_session();

		if ( ! $wc_session ) {
			return self::$cached_data = [];
		}

		if ( ! is_array( $wc_session->get( 'simplyin' ) ) ) {

			$this->install();

			return [];
		}

		return $wc_session->get( 'simplyin' );
	}

	private function save_simplyin_data( array $simplyin_data ) {
		$wc_session = $this->get_wc_session();

		if ( ! $wc_session ) {
			return;
		}

		$wc_session->set( 'simplyin', $simplyin_data );
		$wc_session->save_data();
		self::$cached_data = $simplyin_data;
	}

	private function install() {
		$new_id        = bin2hex( random_bytes( 32 ) );
		$wc_session    = $this->get_wc_session();
		$simplyin_data = [
			'id' => $new_id,
		];

		if ( ! $wc_session ) {
			return;
		}

		$wc_session->set( 'simplyin', $simplyin_data );
		$wc_session->save_data();
		self::$cached_data = $simplyin_data;
		$this->create_simplyin_session_cookie( $new_id );
	}

	public function clear() {
		$this->install();

		$logger = simplyin()->get_simplyin_logger();
		$logger->log_if_wpdebug_on(
			"[Simplyin_Session] clear()"
		);

	}

	private function create_simplyin_session_cookie( string $id ) {
		$value   = $id;
		$secure  = function_exists( 'is_ssl' ) ? is_ssl() : false;
		$domain  = defined( 'COOKIE_DOMAIN' ) && COOKIE_DOMAIN ? COOKIE_DOMAIN : '';
		$options = [
			'path'     => self::COOKIE_PATH,
			'domain'   => $domain,
			'secure'   => $secure,
			'httponly' => true,
			'samesite' => 'Lax',
		];

		setcookie( self::COOKIE_NAME, $value, $options );
	}

	private function get_session_id_from_cookie(): ?string {
		self::$cookie_value_cache = isset( $_COOKIE[ self::COOKIE_NAME ] ) ? sanitize_text_field( wp_unslash( (string) $_COOKIE[ self::COOKIE_NAME ] ) ) : null;

		return self::$cookie_value_cache;
	}
}
