<?php
/**
 * Google Map widget.
 *
 * @package IMPACT_WIDGETS_ELEMENTOR
 */

namespace ImpactAddons\ImpactWidgetsForElementor\Widgets;

use Elementor\Controls_Manager;
use Elementor\Group_Control_Border;
use Elementor\Group_Control_Box_Shadow;
use Elementor\Group_Control_Typography;
use Elementor\Repeater;
use Elementor\Widget_Base;

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

class Google_Map extends Widget_Base {
	public function get_name(): string {
		return 'impact_widgets_elementor_google-map';
	}

	public function get_title(): string {
		return esc_html__( 'Google Map', 'impact-widgets-for-elementor' );
	}

	public function get_icon(): string {
		return 'eicon-google-maps';
	}

	public function get_categories(): array {
		return array( 'impact-widgets-elementor' );
	}

	public function get_style_depends(): array {
		return array( 'impact_widgets_elementor_google-map' );
	}

	public function get_script_depends(): array {
		return array( 'impact_widgets_elementor_google-map' );
	}

	protected function register_controls(): void {
		$this->register_content_controls();
		$this->register_style_controls();
	}

	private function register_content_controls(): void {
		$this->start_controls_section(
			'section_map_settings',
			array(
				'label' => esc_html__( 'Map Settings', 'impact-widgets-for-elementor' ),
			)
		);

		$this->add_control(
			'google_maps_api_key',
			array(
				'label'       => esc_html__( 'Google Maps API Key', 'impact-widgets-for-elementor' ),
				'type'        => Controls_Manager::TEXT,
				'label_block' => true,
				'description' => esc_html__( 'Required for loading Google Maps JavaScript API on the frontend.', 'impact-widgets-for-elementor' ),
			)
		);

		$this->add_control(
			'map_variant',
			array(
				'label'   => esc_html__( 'Map Type', 'impact-widgets-for-elementor' ),
				'type'    => Controls_Manager::SELECT,
				'default' => 'basic-marker',
				'options' => array(
					'basic-marker'    => esc_html__( 'Basic Map With Marker', 'impact-widgets-for-elementor' ),
					'with-routes'     => esc_html__( 'With Routes', 'impact-widgets-for-elementor' ),
					'multiple-markers' => esc_html__( 'Multiple Markers', 'impact-widgets-for-elementor' ),
				),
			)
		);

		$this->add_control(
			'map_theme',
			array(
				'label'   => esc_html__( 'Theme', 'impact-widgets-for-elementor' ),
				'type'    => Controls_Manager::SELECT,
				'default' => 'standard',
				'options' => array(
					'standard'   => esc_html__( 'Standard', 'impact-widgets-for-elementor' ),
					'silver'     => esc_html__( 'Silver', 'impact-widgets-for-elementor' ),
					'retro'      => esc_html__( 'Retro', 'impact-widgets-for-elementor' ),
					'dark'       => esc_html__( 'Dark', 'impact-widgets-for-elementor' ),
					'night'      => esc_html__( 'Night', 'impact-widgets-for-elementor' ),
					'aubergine'  => esc_html__( 'Aubergine', 'impact-widgets-for-elementor' ),
				),
			)
		);

		$this->add_control(
			'map_zoom',
			array(
				'label'   => esc_html__( 'Zoom Level', 'impact-widgets-for-elementor' ),
				'type'    => Controls_Manager::NUMBER,
				'default' => 12,
				'min'     => 1,
				'max'     => 20,
			)
		);

		$this->add_responsive_control(
			'map_height',
			array(
				'label'      => esc_html__( 'Map Height', 'impact-widgets-for-elementor' ),
				'type'       => Controls_Manager::SLIDER,
				'size_units' => array( 'px', 'vh' ),
				'range'      => array(
					'px' => array(
						'min' => 240,
						'max' => 900,
					),
					'vh' => array(
						'min' => 30,
						'max' => 100,
					),
				),
				'default'    => array(
					'size' => 460,
					'unit' => 'px',
				),
				'selectors'  => array(
					'{{WRAPPER}} .iaew-google-map' => '--iaew-google-map-height: {{SIZE}}{{UNIT}};',
				),
			)
		);

		$this->add_control(
			'show_marker_list',
			array(
				'label'        => esc_html__( 'Show Marker List', 'impact-widgets-for-elementor' ),
				'type'         => Controls_Manager::SWITCHER,
				'label_on'     => esc_html__( 'Yes', 'impact-widgets-for-elementor' ),
				'label_off'    => esc_html__( 'No', 'impact-widgets-for-elementor' ),
				'return_value' => 'yes',
				'default'      => 'yes',
				'condition'    => array(
					'map_variant' => 'multiple-markers',
				),
			)
		);

		$this->end_controls_section();

		$this->start_controls_section(
			'section_basic_marker',
			array(
				'label'     => esc_html__( 'Basic Marker', 'impact-widgets-for-elementor' ),
				'condition' => array(
					'map_variant' => 'basic-marker',
				),
			)
		);

		$this->add_control(
			'basic_marker_title',
			array(
				'label'       => esc_html__( 'Marker Title', 'impact-widgets-for-elementor' ),
				'type'        => Controls_Manager::TEXT,
				'default'     => esc_html__( 'ImpactAddons Studio', 'impact-widgets-for-elementor' ),
				'label_block' => true,
			)
		);

		$this->add_control(
			'basic_marker_address',
			array(
				'label'       => esc_html__( 'Address', 'impact-widgets-for-elementor' ),
				'type'        => Controls_Manager::TEXTAREA,
				'default'     => '1600 Amphitheatre Parkway, Mountain View, CA',
				'rows'        => 3,
				'description' => esc_html__( 'Enter an address. Latitude and longitude below are optional fallbacks.', 'impact-widgets-for-elementor' ),
			)
		);

		$this->add_control(
			'basic_marker_lat',
			array(
				'label'   => esc_html__( 'Latitude', 'impact-widgets-for-elementor' ),
				'type'    => Controls_Manager::TEXT,
				'default' => '37.4220',
			)
		);

		$this->add_control(
			'basic_marker_lng',
			array(
				'label'   => esc_html__( 'Longitude', 'impact-widgets-for-elementor' ),
				'type'    => Controls_Manager::TEXT,
				'default' => '-122.0841',
			)
		);

		$this->add_control(
			'basic_marker_info',
			array(
				'label'   => esc_html__( 'Info Window Text', 'impact-widgets-for-elementor' ),
				'type'    => Controls_Manager::TEXTAREA,
				'default' => esc_html__( 'Use this for one location highlight, office pin, or store visit prompt.', 'impact-widgets-for-elementor' ),
				'rows'    => 3,
			)
		);

		$this->end_controls_section();

		$this->start_controls_section(
			'section_routes',
			array(
				'label'     => esc_html__( 'Routes', 'impact-widgets-for-elementor' ),
				'condition' => array(
					'map_variant' => 'with-routes',
				),
			)
		);

		$this->add_control(
			'route_origin',
			array(
				'label'       => esc_html__( 'Origin', 'impact-widgets-for-elementor' ),
				'type'        => Controls_Manager::TEXTAREA,
				'default'     => 'Times Square, Manhattan, NY',
				'rows'        => 2,
				'label_block' => true,
			)
		);

		$this->add_control(
			'route_destination',
			array(
				'label'       => esc_html__( 'Destination', 'impact-widgets-for-elementor' ),
				'type'        => Controls_Manager::TEXTAREA,
				'default'     => 'Central Park, New York, NY',
				'rows'        => 2,
				'label_block' => true,
			)
		);

		$this->add_control(
			'route_travel_mode',
			array(
				'label'   => esc_html__( 'Travel Mode', 'impact-widgets-for-elementor' ),
				'type'    => Controls_Manager::SELECT,
				'default' => 'DRIVING',
				'options' => array(
					'DRIVING'   => esc_html__( 'Driving', 'impact-widgets-for-elementor' ),
					'WALKING'   => esc_html__( 'Walking', 'impact-widgets-for-elementor' ),
					'BICYCLING' => esc_html__( 'Bicycling', 'impact-widgets-for-elementor' ),
					'TRANSIT'   => esc_html__( 'Transit', 'impact-widgets-for-elementor' ),
				),
			)
		);

		$this->end_controls_section();

		$this->start_controls_section(
			'section_multiple_markers',
			array(
				'label'     => esc_html__( 'Multiple Markers', 'impact-widgets-for-elementor' ),
				'condition' => array(
					'map_variant' => 'multiple-markers',
				),
			)
		);

		$repeater = new Repeater();

		$repeater->add_control(
			'marker_title',
			array(
				'label'       => esc_html__( 'Title', 'impact-widgets-for-elementor' ),
				'type'        => Controls_Manager::TEXT,
				'default'     => esc_html__( 'Location', 'impact-widgets-for-elementor' ),
				'label_block' => true,
			)
		);

		$repeater->add_control(
			'marker_address',
			array(
				'label'       => esc_html__( 'Address', 'impact-widgets-for-elementor' ),
				'type'        => Controls_Manager::TEXTAREA,
				'default'     => '1600 Amphitheatre Parkway, Mountain View, CA',
				'rows'        => 2,
				'label_block' => true,
			)
		);

		$repeater->add_control(
			'marker_lat',
			array(
				'label'   => esc_html__( 'Latitude', 'impact-widgets-for-elementor' ),
				'type'    => Controls_Manager::TEXT,
				'default' => '37.4220',
			)
		);

		$repeater->add_control(
			'marker_lng',
			array(
				'label'   => esc_html__( 'Longitude', 'impact-widgets-for-elementor' ),
				'type'    => Controls_Manager::TEXT,
				'default' => '-122.0841',
			)
		);

		$repeater->add_control(
			'marker_info',
			array(
				'label'   => esc_html__( 'Info Window Text', 'impact-widgets-for-elementor' ),
				'type'    => Controls_Manager::TEXTAREA,
				'default' => esc_html__( 'Helpful context for this location.', 'impact-widgets-for-elementor' ),
				'rows'    => 3,
			)
		);

		$this->add_control(
			'multiple_markers',
			array(
				'label'       => esc_html__( 'Markers', 'impact-widgets-for-elementor' ),
				'type'        => Controls_Manager::REPEATER,
				'fields'      => $repeater->get_controls(),
				'title_field' => '{{{ marker_title }}}',
				'default'     => $this->get_default_markers(),
			)
		);

		$this->end_controls_section();
	}

	private function register_style_controls(): void {
		$this->start_controls_section(
			'section_style_map',
			array(
				'label' => esc_html__( 'Map Wrapper', 'impact-widgets-for-elementor' ),
				'tab'   => Controls_Manager::TAB_STYLE,
			)
		);

		$this->add_control(
			'panel_background',
			array(
				'label'     => esc_html__( 'Background Color', 'impact-widgets-for-elementor' ),
				'type'      => Controls_Manager::COLOR,
				'selectors' => array(
					'{{WRAPPER}} .iaew-google-map' => 'background-color: {{VALUE}};',
				),
			)
		);

		$this->add_responsive_control(
			'wrapper_padding',
			array(
				'label'      => esc_html__( 'Padding', 'impact-widgets-for-elementor' ),
				'type'       => Controls_Manager::DIMENSIONS,
				'size_units' => array( 'px', '%' ),
				'selectors'  => array(
					'{{WRAPPER}} .iaew-google-map' => 'padding: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
				),
			)
		);

		$this->add_responsive_control(
			'wrapper_border_radius',
			array(
				'label'      => esc_html__( 'Border Radius', 'impact-widgets-for-elementor' ),
				'type'       => Controls_Manager::DIMENSIONS,
				'size_units' => array( 'px', '%' ),
				'selectors'  => array(
					'{{WRAPPER}} .iaew-google-map' => 'border-radius: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
				),
			)
		);

		$this->add_group_control(
			Group_Control_Border::get_type(),
			array(
				'name'     => 'wrapper_border',
				'selector' => '{{WRAPPER}} .iaew-google-map',
			)
		);

		$this->add_group_control(
			Group_Control_Box_Shadow::get_type(),
			array(
				'name'     => 'wrapper_shadow',
				'selector' => '{{WRAPPER}} .iaew-google-map',
			)
		);

		$this->end_controls_section();

		$this->start_controls_section(
			'section_style_list',
			array(
				'label'     => esc_html__( 'Marker List', 'impact-widgets-for-elementor' ),
				'tab'       => Controls_Manager::TAB_STYLE,
				'condition' => array(
					'map_variant' => 'multiple-markers',
				),
			)
		);

		$this->add_control(
			'list_title_color',
			array(
				'label'     => esc_html__( 'Title Color', 'impact-widgets-for-elementor' ),
				'type'      => Controls_Manager::COLOR,
				'selectors' => array(
					'{{WRAPPER}} .iaew-google-map__marker-title' => 'color: {{VALUE}};',
				),
			)
		);

		$this->add_group_control(
			Group_Control_Typography::get_type(),
			array(
				'name'     => 'list_title_typography',
				'selector' => '{{WRAPPER}} .iaew-google-map__marker-title',
			)
		);

		$this->add_control(
			'list_address_color',
			array(
				'label'     => esc_html__( 'Address Color', 'impact-widgets-for-elementor' ),
				'type'      => Controls_Manager::COLOR,
				'selectors' => array(
					'{{WRAPPER}} .iaew-google-map__marker-address' => 'color: {{VALUE}};',
				),
			)
		);

		$this->add_group_control(
			Group_Control_Typography::get_type(),
			array(
				'name'     => 'list_address_typography',
				'selector' => '{{WRAPPER}} .iaew-google-map__marker-address',
			)
		);

		$this->end_controls_section();
	}

	protected function render(): void {
		$settings  = $this->get_settings_for_display();
		$variant   = isset( $settings['map_variant'] ) ? sanitize_key( $settings['map_variant'] ) : 'basic-marker';
		$variants  = array( 'basic-marker', 'with-routes', 'multiple-markers' );
		$api_key   = isset( $settings['google_maps_api_key'] ) ? trim( (string) $settings['google_maps_api_key'] ) : '';
		$theme     = isset( $settings['map_theme'] ) ? sanitize_key( $settings['map_theme'] ) : 'standard';
		$zoom      = isset( $settings['map_zoom'] ) ? (int) $settings['map_zoom'] : 12;
		$zoom      = max( 1, min( 20, $zoom ) );

		if ( ! in_array( $variant, $variants, true ) ) {
			$variant = 'basic-marker';
		}

		$payload = array(
			'apiKey'  => $api_key,
			'variant' => $variant,
			'theme'   => $theme,
			'zoom'    => $zoom,
		);

		if ( 'basic-marker' === $variant ) {
			$payload['basicMarker'] = array(
				'title'   => isset( $settings['basic_marker_title'] ) ? sanitize_text_field( $settings['basic_marker_title'] ) : '',
				'address' => isset( $settings['basic_marker_address'] ) ? sanitize_textarea_field( $settings['basic_marker_address'] ) : '',
				'lat'     => $this->sanitize_coordinate( $settings['basic_marker_lat'] ?? '' ),
				'lng'     => $this->sanitize_coordinate( $settings['basic_marker_lng'] ?? '' ),
				'info'    => isset( $settings['basic_marker_info'] ) ? sanitize_textarea_field( $settings['basic_marker_info'] ) : '',
			);
		}

		if ( 'with-routes' === $variant ) {
			$payload['route'] = array(
				'origin'      => isset( $settings['route_origin'] ) ? sanitize_textarea_field( $settings['route_origin'] ) : '',
				'destination' => isset( $settings['route_destination'] ) ? sanitize_textarea_field( $settings['route_destination'] ) : '',
				'travelMode'  => isset( $settings['route_travel_mode'] ) ? strtoupper( sanitize_text_field( $settings['route_travel_mode'] ) ) : 'DRIVING',
			);
		}

		if ( 'multiple-markers' === $variant ) {
			$payload['markers'] = $this->prepare_marker_items( $settings['multiple_markers'] ?? array() );
		}

		$wrapper_classes = array(
			'iaew-google-map',
			'iaew-google-map--' . sanitize_html_class( $variant ),
			'iaew-google-map--theme-' . sanitize_html_class( $theme ),
		);

		if ( 'multiple-markers' === $variant && isset( $settings['show_marker_list'] ) && 'yes' === $settings['show_marker_list'] ) {
			$wrapper_classes[] = 'iaew-google-map--has-list';
		}

		$this->add_render_attribute( 'wrapper', 'class', $wrapper_classes );
		$this->add_render_attribute( 'canvas', 'class', 'iaew-google-map__canvas' );
		$this->add_render_attribute( 'canvas', 'data-map-settings', wp_json_encode( $payload ) );

		?>
		<div <?php $this->print_render_attribute_string( 'wrapper' ); ?>>
			<?php if ( '' === $api_key ) : ?>
				<div class="iaew-google-map__notice">
					<strong><?php echo esc_html__( 'Google Maps API key required.', 'impact-widgets-for-elementor' ); ?></strong>
					<p><?php echo esc_html__( 'Add your API key in the widget settings to load the map, routes, and markers on the frontend.', 'impact-widgets-for-elementor' ); ?></p>
				</div>
			<?php endif; ?>

			<div class="iaew-google-map__layout">
				<div <?php $this->print_render_attribute_string( 'canvas' ); ?>></div>

				<?php if ( 'multiple-markers' === $variant && isset( $settings['show_marker_list'] ) && 'yes' === $settings['show_marker_list'] ) : ?>
					<?php $this->render_marker_list( $payload['markers'] ?? array() ); ?>
				<?php endif; ?>
			</div>
		</div>
		<?php
	}

	/**
	 * @return array<int, array<string, string|float>>
	 */
	private function prepare_marker_items( $items ): array {
		if ( ! is_array( $items ) ) {
			return array();
		}

		$markers = array();

		foreach ( $items as $item ) {
			if ( ! is_array( $item ) ) {
				continue;
			}

			$markers[] = array(
				'title'   => isset( $item['marker_title'] ) ? sanitize_text_field( $item['marker_title'] ) : '',
				'address' => isset( $item['marker_address'] ) ? sanitize_textarea_field( $item['marker_address'] ) : '',
				'lat'     => $this->sanitize_coordinate( $item['marker_lat'] ?? '' ),
				'lng'     => $this->sanitize_coordinate( $item['marker_lng'] ?? '' ),
				'info'    => isset( $item['marker_info'] ) ? sanitize_textarea_field( $item['marker_info'] ) : '',
			);
		}

		return array_values(
			array_filter(
				$markers,
				static function ( array $marker ): bool {
					return '' !== $marker['title'] || '' !== $marker['address'];
				}
			)
		);
	}

	/**
	 * @param array<int, array<string, string|float>> $markers Marker rows.
	 */
	private function render_marker_list( array $markers ): void {
		if ( empty( $markers ) ) {
			return;
		}

		?>
		<div class="iaew-google-map__sidebar">
			<div class="iaew-google-map__sidebar-header">
				<h3 class="iaew-google-map__sidebar-title"><?php echo esc_html__( 'Locations', 'impact-widgets-for-elementor' ); ?></h3>
				<p class="iaew-google-map__sidebar-description"><?php echo esc_html__( 'Use the map pins or browse the marker list.', 'impact-widgets-for-elementor' ); ?></p>
			</div>
			<div class="iaew-google-map__marker-list">
				<?php foreach ( $markers as $index => $marker ) : ?>
					<button type="button" class="iaew-google-map__marker-item" data-marker-index="<?php echo esc_attr( (string) $index ); ?>">
						<span class="iaew-google-map__marker-badge"><?php echo esc_html( (string) ( $index + 1 ) ); ?></span>
						<span class="iaew-google-map__marker-copy">
							<span class="iaew-google-map__marker-title"><?php echo esc_html( (string) $marker['title'] ); ?></span>
							<?php if ( '' !== (string) $marker['address'] ) : ?>
								<span class="iaew-google-map__marker-address"><?php echo esc_html( (string) $marker['address'] ); ?></span>
							<?php endif; ?>
						</span>
					</button>
				<?php endforeach; ?>
			</div>
		</div>
		<?php
	}

	/**
	 * @return array<int, array<string, string>>
	 */
	private function get_default_markers(): array {
		return array(
			array(
				'marker_title'   => esc_html__( 'Mountain View HQ', 'impact-widgets-for-elementor' ),
				'marker_address' => '1600 Amphitheatre Parkway, Mountain View, CA',
				'marker_lat'     => '37.4220',
				'marker_lng'     => '-122.0841',
				'marker_info'    => esc_html__( 'Primary office and product team hub.', 'impact-widgets-for-elementor' ),
			),
			array(
				'marker_title'   => esc_html__( 'San Francisco Office', 'impact-widgets-for-elementor' ),
				'marker_address' => '1 Market St, San Francisco, CA',
				'marker_lat'     => '37.7936',
				'marker_lng'     => '-122.3958',
				'marker_info'    => esc_html__( 'Client meetings and partner sessions.', 'impact-widgets-for-elementor' ),
			),
			array(
				'marker_title'   => esc_html__( 'San Jose Studio', 'impact-widgets-for-elementor' ),
				'marker_address' => '333 W Santa Clara St, San Jose, CA',
				'marker_lat'     => '37.3336',
				'marker_lng'     => '-121.8947',
				'marker_info'    => esc_html__( 'Creative planning and workshop space.', 'impact-widgets-for-elementor' ),
			),
		);
	}

	/**
	 * @param mixed $value Potential coordinate value.
	 * @return float|string
	 */
	private function sanitize_coordinate( $value ) {
		if ( '' === trim( (string) $value ) ) {
			return '';
		}

		return (float) $value;
	}
}
