<?php
/**
 * Location meta fields management — get, set, sanitize.
 *
 * @package SEOvaultSEO\LocalSEO
 */

namespace SEOvaultSEO\LocalSEO;

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

class LocationMeta {

	const META_PREFIX = '_seovault_location_';

	protected static $fields = array(
		'business_type'                => 'text',
		'business_name'                => 'text',
		'business_address'             => 'text',
		'business_address_2'           => 'text',
		'business_city'                => 'text',
		'business_state'               => 'text',
		'business_zipcode'             => 'text',
		'business_country'             => 'text',
		'business_phone'               => 'text',
		'business_phone_2nd'           => 'text',
		'business_fax'                 => 'text',
		'business_email'               => 'email',
		'business_url'                 => 'url',
		'business_logo_id'             => 'int',
		'business_price_range'         => 'text',
		'business_currencies_accepted' => 'text',
		'business_payment_accepted'    => 'text',
		'business_area_served'         => 'text',
		'business_vat'                 => 'text',
		'business_tax'                 => 'text',
		'business_contact_phone'       => 'text',
		'business_contact_email'       => 'email',
		'coordinates_lat'              => 'float',
		'coordinates_long'             => 'float',
		'is_primary_location'          => 'bool',
		'open_247'                     => 'bool',
		'multiple_opening_hours'       => 'bool',
		'format_24h'                   => 'bool',
		'hide_opening_hours'           => 'bool',
	);

	protected static $opening_hours_fields = array(
		'_from',
		'_to',
		'_second_from',
		'_second_to',
		'_24h',
	);

	protected static $days = array(
		'sunday',
		'monday',
		'tuesday',
		'wednesday',
		'thursday',
		'friday',
		'saturday',
	);

	public static function get_fields() {
		return self::$fields;
	}

	public static function get_days() {
		return self::$days;
	}

	public static function get_meta_key( $key ) {
		if ( '' === $key ) {
			return '';
		}
		return self::META_PREFIX . $key;
	}

	public static function get( $post_id, $key, $default = '' ) {
		$post_id = absint( $post_id );
		if ( ! $post_id ) {
			return $default;
		}

		$meta_key = self::get_meta_key( $key );
		if ( '' === $meta_key ) {
			return $default;
		}

		$value = get_post_meta( $post_id, $meta_key, true );
		return '' !== $value && null !== $value ? $value : $default;
	}

	public static function get_all( $post_id ) {
		$post_id = absint( $post_id );
		if ( ! $post_id ) {
			return array();
		}

		$data = array();
		foreach ( self::$fields as $key => $type ) {
			$data[ $key ] = self::get( $post_id, $key );
		}

		$data['opening_hours'] = self::get_opening_hours( $post_id );

		return $data;
	}

	public static function set( $post_id, $key, $value ) {
		$post_id = absint( $post_id );
		if ( ! $post_id ) {
			return false;
		}

		if ( ! isset( self::$fields[ $key ] ) ) {
			return false;
		}

		$meta_key = self::get_meta_key( $key );
		if ( '' === $meta_key ) {
			return false;
		}

		$sanitized = self::sanitize_field( $key, $value );
		return update_post_meta( $post_id, $meta_key, $sanitized );
	}

	public static function set_all( $post_id, $data ) {
		$post_id = absint( $post_id );
		if ( ! $post_id ) {
			return false;
		}

		$saved = true;
		foreach ( self::$fields as $key => $type ) {
			if ( isset( $data[ $key ] ) ) {
				$result = self::set( $post_id, $key, $data[ $key ] );
				if ( ! $result ) {
					$saved = false;
				}
			}
		}

		if ( isset( $data['opening_hours'] ) && is_array( $data['opening_hours'] ) ) {
			self::set_opening_hours( $post_id, $data['opening_hours'] );
		}

		return $saved;
	}

	public static function delete( $post_id, $key ) {
		$post_id = absint( $post_id );
		if ( ! $post_id ) {
			return false;
		}

		$meta_key = self::get_meta_key( $key );
		if ( '' === $meta_key ) {
			return false;
		}

		return delete_post_meta( $post_id, $meta_key );
	}

	public static function sanitize_field( $key, $value ) {
		if ( ! isset( self::$fields[ $key ] ) ) {
			return '';
		}

		$type = self::$fields[ $key ];

		switch ( $type ) {
			case 'text':
				return sanitize_text_field( $value );
			case 'email':
				return sanitize_email( $value );
			case 'url':
				if ( ! filter_var( $value, FILTER_VALIDATE_URL ) ) {
					return '';
				}
				return esc_url_raw( $value );
			case 'int':
				return absint( $value );
			case 'float':
				$val = filter_var( $value, FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_FRACTION );
				return '' !== $val ? (string) $val : '';
			case 'bool':
				return ( $value === 'on' || $value === '1' || $value === 1 || $value === true ) ? 'on' : '';
			default:
				return sanitize_text_field( $value );
		}
	}

	public static function get_opening_hours( $post_id ) {
		$post_id = absint( $post_id );
		if ( ! $post_id ) {
			return array();
		}

		$hours = array();
		foreach ( self::$days as $day ) {
			$day_data = array();
			foreach ( self::$opening_hours_fields as $field ) {
				$meta_key      = self::META_PREFIX . 'opening_hours_' . $day . $field;
				$day_data[ $field ] = get_post_meta( $post_id, $meta_key, true );
			}
			$hours[ $day ] = $day_data;
		}

		return $hours;
	}

	public static function set_opening_hours( $post_id, $hours ) {
		$post_id = absint( $post_id );
		if ( ! $post_id ) {
			return false;
		}

		if ( ! is_array( $hours ) ) {
			return false;
		}

		foreach ( self::$days as $day ) {
			if ( ! isset( $hours[ $day ] ) || ! is_array( $hours[ $day ] ) ) {
				continue;
			}

			foreach ( self::$opening_hours_fields as $field ) {
				$meta_key = self::META_PREFIX . 'opening_hours_' . $day . $field;
				$value    = $hours[ $day ][ $field ] ?? '';

				if ( '_24h' === $field ) {
					$value = ( 'on' === $value || '1' === $value ) ? 'on' : '';
				} elseif ( '_from' === $field || '_to' === $field || '_second_from' === $field || '_second_to' === $field ) {
					$value = self::sanitize_time( $value );
				}

				if ( '' === $value ) {
					delete_post_meta( $post_id, $meta_key );
				} else {
					update_post_meta( $post_id, $meta_key, $value );
				}
			}
		}

		return true;
	}

	public static function sanitize_time( $value ) {
		if ( '' === $value || null === $value || 'closed' === $value ) {
			return '';
		}

		$value = sanitize_text_field( $value );
		if ( preg_match( '/^([01]?[0-9]|2[0-3]):[0-5][0-9]$/', $value ) ) {
			return $value;
		}

		return '';
	}

	public static function get_primary_location() {
		$pt = PostType::get_post_type();

		$query = new \WP_Query(
			array(
				'post_type'      => $pt,
				'post_status'    => 'publish',
				'posts_per_page' => 1,
			// phpcs:disable WordPress.DB.SlowDBQuery.slow_db_query_meta_key, WordPress.DB.SlowDBQuery.slow_db_query_meta_value -- Primary location lookup by design.
			'meta_key'           => self::META_PREFIX . 'is_primary_location',
			'meta_value'         => 'on',
			'fields'             => 'ids',
			)
		);
	// phpcs:enable WordPress.DB.SlowDBQuery.slow_db_query_meta_key, WordPress.DB.SlowDBQuery.slow_db_query_meta_value

		if ( $query->have_posts() ) {
			return absint( $query->posts[0] );
		}

		$query = new \WP_Query(
			array(
				'post_type'      => $pt,
				'post_status'    => 'publish',
				'posts_per_page' => 1,
				'fields'         => 'ids',
				'orderby'        => 'date',
				'order'          => 'ASC',
			)
		);

		if ( $query->have_posts() ) {
			return absint( $query->posts[0] );
		}

		return 0;
	}

	public static function get_location_data_object( $post_id ) {
		$post_id = absint( $post_id );
		if ( ! $post_id ) {
			return null;
		}

		$meta = self::get_all( $post_id );
		$post = get_post( $post_id );

		if ( ! $post ) {
			return null;
		}

		$data              = new \stdClass();
		$data->post_id     = $post_id;
		$data->post_title  = $post->post_title;
		$data->permalink   = get_permalink( $post_id );

		foreach ( self::$fields as $key => $type ) {
			$data->$key = $meta[ $key ];
		}

		$data->coords = array(
			'lat'  => $meta['coordinates_lat'],
			'long' => $meta['coordinates_long'],
		);

		$data->opening_hours = $meta['opening_hours'];

		$logo_id = absint( $meta['business_logo_id'] );
		if ( $logo_id ) {
			$data->logo_url = wp_get_attachment_url( $logo_id );
		} else {
			$data->logo_url = '';
		}

		return $data;
	}

	public static function has_required_address( $location ) {
		if ( ! is_object( $location ) && ! is_array( $location ) ) {
			return false;
		}

		$address  = is_object( $location ) ? ( $location->business_address ?? '' ) : ( $location['business_address'] ?? '' );
		$zipcode  = is_object( $location ) ? ( $location->business_zipcode ?? '' ) : ( $location['business_zipcode'] ?? '' );
		$country  = is_object( $location ) ? ( $location->business_country ?? '' ) : ( $location['business_country'] ?? '' );

		return ! empty( $address ) && ! empty( $zipcode ) && ! empty( $country );
	}
}
