<?php
/**
 * LocalBusiness Schema.org JSON-LD generator.
 *
 * @package SEOvaultSEO\LocalSEO
 */

namespace SEOvaultSEO\LocalSEO;

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

class SchemaGenerator {

	protected $options = array();

	public function __construct() {
		$this->options = get_option( 'seovaultseo_local_settings', array() );
		if ( ! is_array( $this->options ) ) {
			$this->options = array();
		}
	}

	public function has_multiple_locations() {
		$pt    = PostType::get_post_type();
		$locs  = wp_count_posts( $pt );
		$total = (int) ( $locs->publish ?? 0 ) + (int) ( $locs->draft ?? 0 );
		return $total > 1;
	}

	public function get_schema_for_location( $post_id ) {
		$location = LocationMeta::get_location_data_object( $post_id );
		if ( ! $location ) {
			return array();
		}

		return $this->build_schema( $location );
	}

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

		if ( is_singular( $pt ) ) {
			$post_id = get_queried_object_id();
			return $this->get_schema_for_location( $post_id );
		}

		$primary_id = LocationMeta::get_primary_location();
		if ( $primary_id ) {
			return $this->get_schema_for_location( $primary_id );
		}

		return $this->get_schema_from_options();
	}

	public function get_schema_from_options() {
		$data                               = new \stdClass();
		$data->post_id                      = 0;
		$data->post_title                   = $this->options['business_name'] ?? get_bloginfo( 'name' );
		$data->permalink                    = home_url( '/' );
		$data->business_type                = $this->options['business_type'] ?? 'LocalBusiness';
		$data->business_name                = $this->options['business_name'] ?? '';
		$data->business_address             = $this->options['business_address'] ?? '';
		$data->business_address_2           = $this->options['business_address_2'] ?? '';
		$data->business_city                = $this->options['business_city'] ?? '';
		$data->business_state               = $this->options['business_state'] ?? '';
		$data->business_zipcode             = $this->options['business_zipcode'] ?? '';
		$data->business_country             = $this->options['business_country'] ?? '';
		$data->business_phone               = $this->options['business_phone'] ?? '';
		$data->business_phone_2nd           = $this->options['business_phone_2nd'] ?? '';
		$data->business_fax                 = $this->options['business_fax'] ?? '';
		$data->business_email               = $this->options['business_email'] ?? '';
		$data->business_url                 = $this->options['business_url'] ?? '';
		$data->business_logo_id             = 0;
		$data->business_price_range         = $this->options['business_price_range'] ?? '';
		$data->business_currencies_accepted = $this->options['business_currencies_accepted'] ?? '';
		$data->business_payment_accepted    = $this->options['business_payment_accepted'] ?? '';
		$data->business_area_served         = $this->options['business_area_served'] ?? '';
		$data->business_vat                 = $this->options['business_vat'] ?? '';
		$data->business_tax                 = $this->options['business_tax'] ?? '';
		$data->business_contact_phone       = $this->options['business_contact_phone'] ?? '';
		$data->business_contact_email       = $this->options['business_contact_email'] ?? '';
		$data->coordinates_lat              = $this->options['coordinates_lat'] ?? '';
		$data->coordinates_long             = $this->options['coordinates_long'] ?? '';
		$data->coords                       = array(
			'lat'  => $data->coordinates_lat,
			'long' => $data->coordinates_long,
		);
		$data->logo_url                     = '';
		$data->opening_hours                = array();

		return $this->build_schema( $data );
	}

	protected function build_schema( $location ) {
		$schema = array(
			'@type' => array( 'LocalBusiness' ),
		);

		$business_type = $location->business_type ?? '';
		if ( '' !== $business_type && BusinessTypes::is_valid( $business_type ) ) {
			$schema['@type'][] = $business_type;
		}
		$schema['@type'] = array_values( array_unique( $schema['@type'] ) );

		$schema['@id']  = $location->permalink . '#localbusiness';
		$schema['name'] = $location->business_name ?: $location->post_title;
		$schema['url']  = $location->permalink;

		if ( LocationMeta::has_required_address( $location ) ) {
			$schema['address'] = $this->build_postal_address( $location );
		}

		if ( ! empty( $location->coords['lat'] ) && ! empty( $location->coords['long'] ) ) {
			$schema['geo'] = array(
				'@type'     => 'GeoCoordinates',
				'latitude'  => $location->coords['lat'],
				'longitude' => $location->coords['long'],
			);
		}

		$phones = array();
		if ( ! empty( $location->business_phone ) ) {
			$phones[] = $location->business_phone;
		}
		if ( ! empty( $location->business_phone_2nd ) ) {
			$phones[] = $location->business_phone_2nd;
		}
		if ( ! empty( $phones ) ) {
			$schema['telephone'] = $phones;
		}

		if ( ! empty( $location->business_email ) ) {
			$schema['email'] = $location->business_email;
		}
		if ( ! empty( $location->business_fax ) ) {
			$schema['faxNumber'] = $location->business_fax;
		}
		if ( ! empty( $location->business_url ) ) {
			$schema['url'] = $location->business_url;
		}

		if ( ! empty( $location->logo_url ) ) {
			$schema['image'] = $location->logo_url;
			$schema['logo']  = $location->logo_url;
		}

		if ( BusinessTypes::is_child_of( 'LocalBusiness', $business_type ) ) {
			if ( ! empty( $location->business_price_range ) ) {
				$schema['priceRange'] = $location->business_price_range;
			}
			if ( ! empty( $location->business_currencies_accepted ) ) {
				$schema['currenciesAccepted'] = $location->business_currencies_accepted;
			}
			if ( ! empty( $location->business_payment_accepted ) ) {
				$schema['paymentAccepted'] = $location->business_payment_accepted;
			}
		}

		if ( ! empty( $location->business_area_served ) ) {
			$schema['areaServed'] = $location->business_area_served;
		}
		if ( ! empty( $location->business_vat ) ) {
			$schema['vatID'] = $location->business_vat;
		}
		if ( ! empty( $location->business_tax ) ) {
			$schema['taxID'] = $location->business_tax;
		}

		if ( ! empty( $location->business_contact_phone ) || ! empty( $location->business_contact_email ) ) {
			$schema['contactPoint'] = array( '@type' => 'ContactPoint' );
			if ( ! empty( $location->business_contact_phone ) ) {
				$schema['contactPoint']['telephone'] = $location->business_contact_phone;
			}
			if ( ! empty( $location->business_contact_email ) ) {
				$schema['contactPoint']['email'] = $location->business_contact_email;
			}
		}

		$oh            = new OpeningHours( $location->post_id );
		$opening_hours = $oh->generate_schema();
		if ( ! empty( $opening_hours ) ) {
			$schema['openingHoursSpecification'] = $opening_hours;
		}

		return $schema;
	}

	protected function build_postal_address( $location ) {
		$address_lines = array();
		if ( ! empty( $location->business_address ) ) {
			$address_lines[] = $location->business_address;
		}
		if ( ! empty( $location->business_address_2 ) ) {
			$address_lines[] = $location->business_address_2;
		}

		$address = array(
			'@type'           => 'PostalAddress',
			'streetAddress'   => ! empty( $address_lines ) ? implode( ', ', $address_lines ) : '',
			'addressLocality' => $location->business_city ?? '',
			'postalCode'      => $location->business_zipcode ?? '',
			'addressRegion'   => $location->business_state ?? '',
			'addressCountry'  => $location->business_country ?? '',
		);

		return array_filter( $address );
	}

	public function get_all_location_schemas() {
		$pt    = PostType::get_post_type();
		$query = new \WP_Query(
			array(
				'post_type'      => $pt,
				'post_status'    => 'publish',
				'posts_per_page' => -1,
				'fields'         => 'ids',
			)
		);

		$schemas = array();
		if ( $query->have_posts() ) {
			foreach ( $query->posts as $post_id ) {
				$schema = $this->get_schema_for_location( $post_id );
				if ( ! empty( $schema ) ) {
					$schemas[] = $schema;
				}
			}
		}

		return $schemas;
	}
}
