<?php
/**
 * Schema.org JSON-LD Generator
 *
 * Generates proper schema.org markup based on business type and collected fields.
 *
 * @package BW_Schema
 * @since 3.0.0-babel
 */

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

class BW_Schema_Generator {

	/**
	 * Generate schema.org JSON-LD markup
	 *
	 * @return array Schema markup data
	 */
	public static function generate() {
		$category = get_option( 'bw_schema_business_category', '' );
		$type = get_option( 'bw_schema_business_type', '' );
		$org_data = BW_Schema_Service_Organization::get_for_schema();

		// Base schema with common properties
		$schema = self::get_base_schema( $org_data );

		if ( ! $schema ) {
			return array();
		}

		// Add type-specific properties based on business category
		if ( $category && $type ) {
			$schema = self::add_type_specific_properties( $schema, $category, $type, $org_data );
		}

		return $schema;
	}

	/**
	 * Build base schema with common properties
	 *
	 * @param array $org_data Organization data from database
	 * @return array Schema array
	 */
	private static function get_base_schema( $org_data ) {
		$category = get_option( 'bw_schema_business_category', '' );
		$type = get_option( 'bw_schema_business_type', '' );

		if ( ! $category || ! $type ) {
			return array();
		}

		// Get the schema.org type name
		$schema_type = BW_Schema_Service_Organization::get_schema_type( $category, $type );

		if ( ! $schema_type ) {
			return array();
		}

		$schema = array(
			'@context' => 'https://schema.org',
			'@type'    => $schema_type,
			'name'     => $org_data['name'] ?? get_bloginfo( 'name' ),
			'url'      => $org_data['url'] ?? get_bloginfo( 'url' ),
		);

		// Add logo if available
		if ( ! empty( $org_data['logo'] ) ) {
			$schema['logo'] = $org_data['logo'];
		}

		// Add contact information
		if ( ! empty( $org_data['telephone'] ) ) {
			$schema['telephone'] = $org_data['telephone'];
		}

		if ( ! empty( $org_data['email'] ) ) {
			$schema['email'] = $org_data['email'];
		}

		// Add social media profiles
		if ( ! empty( $org_data['sameAs'] ) && is_array( $org_data['sameAs'] ) ) {
			$schema['sameAs'] = array_filter( $org_data['sameAs'] );
		}

		// ===== PHASE 5: ADVANCED RICH DATA =====

		// Add structured address (PostalAddress)
		$address = BW_Schema_Location::format_for_schema( $org_data );
		if ( ! empty( $address ) ) {
			$schema['address'] = $address;
		}

		// Add area served
		if ( ! empty( $org_data['areaServed'] ) && is_array( $org_data['areaServed'] ) ) {
			$schema['areaServed'] = array_filter( $org_data['areaServed'] );
		}

		// Add aggregate rating (reviews)
		$rating = BW_Schema_Rating::format_for_schema( $org_data );
		if ( ! empty( $rating ) ) {
			$schema['aggregateRating'] = $rating;
		}

		// Add multiple contact points
		$contact_points = BW_Schema_Contact::format_for_schema( $org_data );
		if ( ! empty( $contact_points ) ) {
			$schema['contactPoint'] = $contact_points;
		}

		// Add images (logo, featured, gallery)
		$images = BW_Schema_Media::format_images_for_schema( $org_data );
		if ( ! empty( $images ) ) {
			// If only one image, use it directly; if multiple, use array
			$schema['image'] = count( $images ) === 1 ? reset( $images ) : $images;
		}

		// ===== PHASE 6: ADVANCED FEATURES =====

		// Add FAQ schema (as mainEntity if no article is present)
		$faq = BW_Schema_FAQ::format_for_schema( $org_data );
		if ( ! empty( $faq ) ) {
			// If we're not outputting an article, FAQ becomes mainEntity
			if ( empty( $org_data['article_type'] ) ) {
				$schema['mainEntity'] = $faq;
			}
		}

		// Add individual reviews
		$reviews = BW_Schema_Review::format_for_schema( $org_data );
		if ( ! empty( $reviews ) ) {
			$schema['review'] = count( $reviews ) === 1 ? reset( $reviews ) : $reviews;
		}

		// Add article/webpage schema (for content pages)
		// Note: Article schema is complex and usually output separately
		// This is available but not merged into the main organization schema by default
		// Developers can access it via BW_Schema_WebPage::format_for_schema() if needed

		return $schema;
	}

	/**
	 * Add type-specific properties based on business category
	 *
	 * @param array $schema Base schema array
	 * @param string $category Business category
	 * @param string $type Business type
	 * @param array $org_data Organization data
	 * @return array Updated schema
	 */
	private static function add_type_specific_properties( $schema, $category, $type, $org_data ) {
		switch ( $category ) {
			case 'accommodation':
				$schema = self::add_accommodation_properties( $schema, $type, $org_data );
				break;

			case 'food_beverage':
				$schema = self::add_food_beverage_properties( $schema, $type, $org_data );
				break;

			case 'medical':
				$schema = self::add_medical_properties( $schema, $type, $org_data );
				break;

			case 'retail':
				$schema = self::add_retail_properties( $schema, $type, $org_data );
				break;

			case 'professional':
				$schema = self::add_professional_properties( $schema, $type, $org_data );
				break;

			case 'automotive':
				$schema = self::add_automotive_properties( $schema, $type, $org_data );
				break;

			case 'entertainment':
				$schema = self::add_entertainment_properties( $schema, $type, $org_data );
				break;

			case 'beauty':
				$schema = self::add_beauty_properties( $schema, $type, $org_data );
				break;

			case 'education':
				$schema = self::add_education_properties( $schema, $type, $org_data );
				break;

			case 'finance':
				$schema = self::add_finance_properties( $schema, $type, $org_data );
				break;

			case 'realestate':
				$schema = self::add_realestate_properties( $schema, $type, $org_data );
				break;

			case 'services':
				$schema = self::add_services_properties( $schema, $type, $org_data );
				break;
		}

		return $schema;
	}

	/**
	 * Add accommodation-specific properties
	 */
	private static function add_accommodation_properties( $schema, $type, $org_data ) {
		if ( in_array( $type, array( 'hotel', 'resort' ) ) ) {
			// Chain name
			if ( ! empty( $org_data['accommodation_chain_name'] ) ) {
				$schema['chainName'] = $org_data['accommodation_chain_name'];
			}

			// Star rating
			if ( ! empty( $org_data['accommodation_star_rating'] ) ) {
				$schema['starRating'] = array(
					'@type'       => 'Rating',
					'ratingValue' => intval( $org_data['accommodation_star_rating'] ),
					'bestRating'  => 5,
					'worstRating' => 1,
				);
			}
		}

		// Number of rooms
		if ( ! empty( $org_data['accommodation_num_rooms'] ) ) {
			$schema['numberOfRooms'] = intval( $org_data['accommodation_num_rooms'] );
		}

		return $schema;
	}

	/**
	 * Add food & beverage properties
	 */
	private static function add_food_beverage_properties( $schema, $type, $org_data ) {
		// Cuisine type
		if ( ! empty( $org_data['food_beverage_cuisine_type'] ) ) {
			$cuisines = array_map( 'trim', explode( ',', $org_data['food_beverage_cuisine_type'] ) );
			$schema['servesCuisine'] = array_filter( $cuisines );
		}

		// Price range
		if ( ! empty( $org_data['food_beverage_price_range'] ) ) {
			$schema['priceRange'] = $org_data['food_beverage_price_range'];
		}

		// Delivery
		if ( ! empty( $org_data['food_beverage_delivery'] ) ) {
			$schema['deliveryMethod'] = $org_data['food_beverage_delivery'] === 'yes' ? array( 'DeliveryMethod' ) : array();
		}

		return $schema;
	}

	/**
	 * Add medical properties
	 */
	private static function add_medical_properties( $schema, $type, $org_data ) {
		// Medical specialization
		if ( ! empty( $org_data['medical_specialization'] ) ) {
			$schema['medicalSpecialty'] = $org_data['medical_specialization'];
		}

		return $schema;
	}

	/**
	 * Add retail properties
	 */
	private static function add_retail_properties( $schema, $type, $org_data ) {
		// Return policy
		if ( ! empty( $org_data['retail_accepts_returns'] ) ) {
			$returns_map = array(
				'yes'      => 'Full Refund',
				'exchange' => 'Exchange Only',
				'no'       => 'No Returns',
			);

			$policy = $returns_map[ $org_data['retail_accepts_returns'] ] ?? '';
			if ( $policy ) {
				$schema['returnPolicy'] = $policy;
			}
		}

		return $schema;
	}

	/**
	 * Add professional services properties
	 */
	private static function add_professional_properties( $schema, $type, $org_data ) {
		// Specialization maps to practice areas
		if ( ! empty( $org_data['professional_specialization'] ) ) {
			$schema['knowsAbout'] = array_map(
				'trim',
				explode( ',', $org_data['professional_specialization'] )
			);
		}

		// Years in business
		if ( ! empty( $org_data['professional_years_experience'] ) ) {
			$schema['yearsInBusiness'] = intval( $org_data['professional_years_experience'] );
		}

		return $schema;
	}

	/**
	 * Add automotive properties
	 */
	private static function add_automotive_properties( $schema, $type, $org_data ) {
		// Services offered
		if ( ! empty( $org_data['automotive_services'] ) ) {
			$services = array_map( 'trim', explode( ',', $org_data['automotive_services'] ) );
			$schema['knowsAbout'] = array_filter( $services );
		}

		return $schema;
	}

	/**
	 * Add entertainment properties
	 */
	private static function add_entertainment_properties( $schema, $type, $org_data ) {
		// Capacity
		if ( ! empty( $org_data['entertainment_capacity'] ) ) {
			$schema['maximumAttendeeCapacity'] = intval( $org_data['entertainment_capacity'] );
		}

		return $schema;
	}

	/**
	 * Add beauty properties
	 */
	private static function add_beauty_properties( $schema, $type, $org_data ) {
		// Services offered
		if ( ! empty( $org_data['beauty_services'] ) ) {
			$services = array_map( 'trim', explode( ',', $org_data['beauty_services'] ) );
			$schema['knowsAbout'] = array_filter( $services );
		}

		return $schema;
	}

	/**
	 * Add education properties
	 */
	private static function add_education_properties( $schema, $type, $org_data ) {
		// Accreditation
		if ( ! empty( $org_data['education_accreditation'] ) ) {
			$schema['accreditation'] = $org_data['education_accreditation'];
		}

		// Programs offered
		if ( ! empty( $org_data['education_programs'] ) ) {
			$programs = array_map( 'trim', explode( ',', $org_data['education_programs'] ) );
			$schema['educationalLevel'] = array_filter( $programs );
		}

		return $schema;
	}

	/**
	 * Add finance properties
	 */
	private static function add_finance_properties( $schema, $type, $org_data ) {
		// For banks, add routing number equivalent
		if ( ! empty( $org_data['finance_charter_number'] ) ) {
			$schema['identifier'] = $org_data['finance_charter_number'];
		}

		return $schema;
	}

	/**
	 * Add real estate properties
	 */
	private static function add_realestate_properties( $schema, $type, $org_data ) {
		// Specialization
		if ( ! empty( $org_data['realestate_specialization'] ) ) {
			$specializations = array_map( 'trim', explode( ',', $org_data['realestate_specialization'] ) );
			$schema['knowsAbout'] = array_filter( $specializations );
		}

		return $schema;
	}

	/**
	 * Add general services properties
	 */
	private static function add_services_properties( $schema, $type, $org_data ) {
		// Service area
		if ( ! empty( $org_data['services_area_coverage'] ) ) {
			$schema['areaServed'] = $org_data['services_area_coverage'];
		}

		return $schema;
	}

	/**
	 * Format address for schema.org
	 *
	 * @param array $address Address data
	 * @return array PostalAddress schema
	 */
	private static function format_address( $address ) {
		if ( ! is_array( $address ) || empty( $address ) ) {
			return array();
		}

		return array(
			'@type'           => 'PostalAddress',
			'streetAddress'   => $address['street'] ?? '',
			'addressLocality' => $address['city'] ?? '',
			'addressRegion'   => $address['state'] ?? '',
			'postalCode'      => $address['zip'] ?? '',
			'addressCountry'  => $address['country'] ?? 'US',
		);
	}

	/**
	 * Output schema markup to page head
	 *
	 * Called by wp_head hook
	 *
	 * @return void
	 */
	public static function output_schema() {
		$schema = self::generate();

		if ( empty( $schema ) ) {
			return;
		}

		?>
		<!-- Solomon Schema markup -->
		<script type="application/ld+json">
		<?php echo wp_json_encode( $schema, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
		</script>
		<?php
	}
}
