<?php
/**
 * Organization with Locations schema type
 *
 * Outputs schema.org/Organization with multiple branch offices/locations.
 * Used when displaying multiple locations under a single organization.
 *
 * @package BW_Schema
 * @since 3.0.0-babel
 */

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

class BW_Schema_Schema_Organization_Locations extends BW_Schema_Schema_Base {

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

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

		// Get organization data
		$org = BW_Schema_Service_Organization::get();
		$locations = BW_Schema_Service_Locations::get_locations();

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

		// Set basic organization info
		$this->set( 'name', $org['org_name'] ?? '' );
		$this->set( 'url', $this->get_site_url() );

		// Logo
		if ( ! empty( $org['logo_id'] ) ) {
			$logo_url = wp_get_attachment_url( $org['logo_id'] );
			if ( $logo_url ) {
				$this->set_nested( 'logo', array(
					'@type' => 'ImageObject',
					'url'   => esc_url_raw( $logo_url ),
				));
			}
		}

		// Set multiple locations as branch offices
		$this->set_locations( $locations );

		// Description
		if ( ! empty( $org['description'] ) ) {
			$this->set( 'description', $org['description'] );
		}
	}

	/**
	 * Set location branches
	 *
	 * @param array $locations Array of location data
	 * @return void
	 */
	private function set_locations( $locations ) {
		if ( empty( $locations ) ) {
			return;
		}

		$branches = array();

		foreach ( $locations as $location ) {
			$branch = array(
				'@type' => 'LocalBusiness',
				'name'  => $location['name'] ?? '',
			);

			// Address
			if ( ! empty( $location['street'] ) || ! empty( $location['city'] ) ) {
				$address = array(
					'@type' => 'PostalAddress',
				);

				if ( ! empty( $location['street'] ) ) {
					$address['streetAddress'] = $location['street'];
				}
				if ( ! empty( $location['city'] ) ) {
					$address['addressLocality'] = $location['city'];
				}
				if ( ! empty( $location['state'] ) ) {
					$address['addressRegion'] = $location['state'];
				}
				if ( ! empty( $location['postal_code'] ) ) {
					$address['postalCode'] = $location['postal_code'];
				}
				if ( ! empty( $location['country'] ) ) {
					$address['addressCountry'] = $location['country'];
				}

				if ( count( $address ) > 1 ) {
					$branch['address'] = $address;
				}
			}

			// Contact info
			if ( ! empty( $location['telephone'] ) ) {
				$branch['telephone'] = $location['telephone'];
			}

			if ( ! empty( $location['email'] ) ) {
				$branch['email'] = $location['email'];
			}

			// URL
			if ( ! empty( $location['website'] ) ) {
				$branch['url'] = esc_url_raw( $location['website'] );
			}

			// Hours
			if ( ! empty( $location['opening_hours'] ) ) {
				$hours = $this->build_opening_hours( $location['opening_hours'] );
				if ( ! empty( $hours ) ) {
					$branch['openingHoursSpecification'] = $hours;
				}
			}

			$branches[] = $branch;
		}

		if ( ! empty( $branches ) ) {
			$this->set_nested( 'branchOf', $branches );
		}
	}

	/**
	 * Build opening hours specification
	 *
	 * @param array $hours Opening hours data
	 * @return array Opening hours specification
	 */
	private function build_opening_hours( $hours ) {
		if ( empty( $hours ) || ! is_array( $hours ) ) {
			return array();
		}

		$day_map = array(
			'monday'    => 'Monday',
			'tuesday'   => 'Tuesday',
			'wednesday' => 'Wednesday',
			'thursday'  => 'Thursday',
			'friday'    => 'Friday',
			'saturday'  => 'Saturday',
			'sunday'    => 'Sunday',
		);

		$opening_hours = array();

		foreach ( $hours as $day => $time ) {
			if ( empty( $time ) || 'closed' === strtolower( $time ) ) {
				continue;
			}

			$day_label = $day_map[ strtolower( $day ) ] ?? '';
			if ( ! $day_label ) {
				continue;
			}

			if ( strpos( $time, '-' ) ) {
				list( $open, $close ) = explode( '-', $time );

				$opening_hours[] = array(
					'@type'         => 'OpeningHoursSpecification',
					'dayOfWeek'     => $day_label,
					'opens'         => trim( $open ),
					'closes'        => trim( $close ),
				);
			}
		}

		return $opening_hours;
	}

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

		if ( ! $this->has_required( array( 'name' ) ) ) {
			$errors[] = 'Organization schema requires a name';
		}

		// Check if we have locations
		if ( ! isset( $this->schema['branchOf'] ) || empty( $this->schema['branchOf'] ) ) {
			$errors[] = 'Organization Locations schema requires at least one location';
		}

		return $errors;
	}
}
