<?php
/**
 * Service Area schema type
 *
 * Outputs geographical areas where a business provides services.
 * Can be used with LocalBusiness or Organization.
 *
 * @package BW_Schema
 * @since 3.0.0-babel
 */

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

class BW_Schema_Schema_Service_Area extends BW_Schema_Schema_Base {

	/**
	 * Schema type
	 *
	 * @var string
	 */
	protected $type = 'LocalBusiness';

	/**
	 * Service areas array
	 *
	 * @var array
	 */
	private $areas;

	/**
	 * Constructor
	 *
	 * @param array $areas Service areas data
	 */
	public function __construct( $areas = null ) {
		if ( is_null( $areas ) ) {
			// Load from service
			if ( class_exists( 'BW_Schema_Service_Locations' ) ) {
				$this->areas = BW_Schema_Service_Locations::get_service_areas();
			}
		} else {
			$this->areas = $areas;
		}

		parent::__construct();
	}

	/**
	 * Build the service area schema
	 *
	 * @return void
	 */
	protected function build() {
		// Check if service is available
		if ( ! class_exists( 'BW_Schema_Service_Organization' ) ) {
			return;
		}

		$areas = $this->areas ?? array();
		if ( empty( $areas ) ) {
			return;
		}

		// Get organization info as base
		$org = BW_Schema_Service_Organization::get();

		$this->set( 'name', $org['org_name'] ?? '' );
		$this->set( 'url', $this->get_site_url() );

		// Set service areas
		$this->set_areas( $areas );
	}

	/**
	 * Set areaServed property from service areas
	 *
	 * @param array $areas Service areas
	 * @return void
	 */
	private function set_areas( $areas ) {
		if ( empty( $areas ) ) {
			return;
		}

		$area_items = array();

		foreach ( $areas as $area ) {
			$area_name = $area['name'] ?? '';

			if ( ! $area_name ) {
				continue;
			}

			// Create GeoShape for more detailed service areas
			$geo_item = $this->build_geo_item( $area );

			if ( $geo_item ) {
				$area_items[] = $geo_item;
			} else {
				// Fallback to simple name
				$area_items[] = $area_name;
			}
		}

		if ( ! empty( $area_items ) ) {
			// If all simple names, use array. If mixed, flatten to names only
			$all_strings = array_filter( $area_items, 'is_string' );
			if ( count( $all_strings ) === count( $area_items ) ) {
				$this->set( 'areaServed', $area_items );
			} else {
				// Mixed types - output structured items
				$this->set( 'areaServed', array_filter( $area_items, function( $item ) {
					return is_array( $item );
				}));
			}
		}
	}

	/**
	 * Build geo shape for service area
	 *
	 * @param array $area Area data
	 * @return array|null GeoShape or null
	 */
	private function build_geo_item( $area ) {
		$name = $area['name'] ?? '';
		if ( ! $name ) {
			return null;
		}

		// Simple GeoShape with just name
		$geo = array(
			'@type' => 'City',
			'name'  => $name,
		);

		// Add postal code if available
		if ( ! empty( $area['postal_code'] ) ) {
			$geo['postalCode'] = $area['postal_code'];
		}

		// Add state/region if available
		if ( ! empty( $area['state'] ) ) {
			$geo['areaName'] = $area['state'];
		}

		return $geo;
	}

	/**
	 * Validate service area schema
	 *
	 * @return array Validation errors
	 */
	public function validate() {
		$errors = parent::validate();

		if ( ! isset( $this->schema['areaServed'] ) || empty( $this->schema['areaServed'] ) ) {
			$errors[] = 'Service Area schema requires at least one service area';
		}

		return $errors;
	}
}
