<?php
if ( ! defined( 'ABSPATH' ) ) {
    exit;
}

class BLM_Schema {

    public static function should_output() {
        if ( is_front_page() ) {
            return true;
        }

        if ( is_page() ) {
            $slug = get_post_field( 'post_name', get_queried_object_id() );
            $contact_slugs = array( 'contact', 'contact-us', 'get-in-touch', 'our-location' );
            if ( in_array( $slug, $contact_slugs, true ) ) {
                return true;
            }
        }

        return false;
    }

    public static function generate() {
        $data = get_option( 'blm_business_data', array() );

        if ( empty( $data ) || empty( $data['business_name'] ) ) {
            return null;
        }

        $type_key    = isset( $data['business_type'] ) ? $data['business_type'] : 'local_business';
        $schema_type = BLM_Business_Types::get_schema_type( $type_key );

        $schema = array(
            '@context' => 'https://schema.org',
            '@type'    => $schema_type,
            'name'     => $data['business_name'],
        );

        if ( ! empty( $data['description'] ) ) {
            $schema['description'] = $data['description'];
        }

        if ( ! empty( $data['website'] ) ) {
            $schema['url'] = $data['website'];
        }

        if ( ! empty( $data['phone'] ) ) {
            $schema['telephone'] = $data['phone'];
        }

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

        if ( ! empty( $data['logo'] ) ) {
            $schema['logo'] = $data['logo'];
            $schema['image'] = $data['logo'];
        }

        if ( ! empty( $data['price_range'] ) ) {
            $schema['priceRange'] = $data['price_range'];
        }

        // Postal Address
        $has_address = ! empty( $data['address'] ) || ! empty( $data['city'] ) || ! empty( $data['state'] ) || ! empty( $data['postal_code'] ) || ! empty( $data['country'] );
        if ( $has_address ) {
            $address = array(
                '@type' => 'PostalAddress',
            );
            if ( ! empty( $data['address'] ) ) {
                $address['streetAddress'] = $data['address'];
            }
            if ( ! empty( $data['city'] ) ) {
                $address['addressLocality'] = $data['city'];
            }
            if ( ! empty( $data['state'] ) ) {
                $address['addressRegion'] = $data['state'];
            }
            if ( ! empty( $data['postal_code'] ) ) {
                $address['postalCode'] = $data['postal_code'];
            }
            if ( ! empty( $data['country'] ) ) {
                $address['addressCountry'] = $data['country'];
            }
            $schema['address'] = $address;
        }

        // Opening Hours
        if ( ! empty( $data['open_247'] ) ) {
            $schema['openingHoursSpecification'] = array(
                array(
                    '@type'     => 'OpeningHoursSpecification',
                    'dayOfWeek' => array( 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday' ),
                    'opens'     => '00:00',
                    'closes'    => '23:59',
                ),
            );
        } elseif ( ! empty( $data['hours'] ) && is_array( $data['hours'] ) ) {
            $hours_spec = array();
            $day_map = array(
                'monday'    => 'Monday',
                'tuesday'   => 'Tuesday',
                'wednesday' => 'Wednesday',
                'thursday'  => 'Thursday',
                'friday'    => 'Friday',
                'saturday'  => 'Saturday',
                'sunday'    => 'Sunday',
            );

            foreach ( $data['hours'] as $day => $info ) {
                if ( ! empty( $info['open'] ) && isset( $day_map[ $day ] ) ) {
                    $hours_spec[] = array(
                        '@type'     => 'OpeningHoursSpecification',
                        'dayOfWeek' => $day_map[ $day ],
                        'opens'     => isset( $info['open_time'] ) ? $info['open_time'] : '09:00',
                        'closes'    => isset( $info['close_time'] ) ? $info['close_time'] : '17:00',
                    );
                }
            }

            if ( ! empty( $hours_spec ) ) {
                $schema['openingHoursSpecification'] = $hours_spec;
            }
        }

        // Social / sameAs — skip when Yoast is active (its Organization block already outputs sameAs).
        $yoast_active = defined( 'WPSEO_VERSION' );
        if ( ! $yoast_active && ! empty( $data['social'] ) && is_array( $data['social'] ) ) {
            $same_as = array();
            foreach ( $data['social'] as $url ) {
                if ( ! empty( $url ) ) {
                    $same_as[] = $url;
                }
            }
            if ( ! empty( $same_as ) ) {
                $schema['sameAs'] = $same_as;
            }
        }

        // Type-specific properties
        if ( ! empty( $data['type_fields'] ) && is_array( $data['type_fields'] ) ) {
            self::apply_type_fields( $schema, $type_key, $data['type_fields'] );
        }

        return $schema;
    }

    private static function apply_type_fields( &$schema, $type_key, $fields ) {
        // Field key to schema property mapping for simple text fields (single value)
        $text_mappings = array(
            'menu_url'            => 'hasMenu',
            'checkin_time'        => 'checkinTime',
            'checkout_time'       => 'checkoutTime',
            'mission_statement'   => 'nonprofitMission',
            'nonprofit_status'    => 'nonprofitStatus',
            'capacity'            => 'maximumAttendeeCapacity',
            'screen_count'        => 'screenCount',
        );

        // Process simple text/textarea fields
        foreach ( $text_mappings as $field_key => $schema_prop ) {
            if ( ! empty( $fields[ $field_key ] ) ) {
                $schema[ $schema_prop ] = $fields[ $field_key ];
            }
        }

        // Multi-line textarea fields that should become arrays
        $multiline_mappings = array(
            'known_for'          => 'knowsAbout',
            'available_services' => 'availableService',
            'serves_cuisine'     => 'servesCuisine',
            'auto_brands'        => 'brand',
            'medical_specialty'  => 'medicalSpecialty',
            'currencies_accepted'=> 'currenciesAccepted',
            'sport'              => 'sport',
        );

        foreach ( $multiline_mappings as $field_key => $schema_prop ) {
            if ( ! empty( $fields[ $field_key ] ) ) {
                $items = array_filter( array_map( 'trim', explode( "\n", $fields[ $field_key ] ) ) );
                $items = array_values( $items );
                if ( count( $items ) === 1 ) {
                    $schema[ $schema_prop ] = $items[0];
                } elseif ( count( $items ) > 1 ) {
                    $schema[ $schema_prop ] = $items;
                }
            }
        }

        // Checkbox fields that map to boolean 'True' values
        $checkbox_mappings = array(
            'accepts_reservations' => 'acceptsReservations',
            'has_drive_through'    => 'hasDriveThroughService',
            'accepting_patients'   => 'isAcceptingNewPatients',
        );

        foreach ( $checkbox_mappings as $field_key => $schema_prop ) {
            if ( ! empty( $fields[ $field_key ] ) ) {
                $schema[ $schema_prop ] = 'True';
            }
        }

        // Service area (textarea -> areaServed array)
        if ( ! empty( $fields['service_area'] ) ) {
            $areas = array_filter( array_map( 'trim', explode( "\n", $fields['service_area'] ) ) );
            $areas = array_values( $areas );
            if ( count( $areas ) === 1 ) {
                $schema['areaServed'] = array(
                    '@type' => 'AdministrativeArea',
                    'name'  => $areas[0],
                );
            } elseif ( count( $areas ) > 1 ) {
                $schema['areaServed'] = array_map( function ( $area ) {
                    return array(
                        '@type' => 'AdministrativeArea',
                        'name'  => $area,
                    );
                }, $areas );
            }
        }

        // Star rating (select -> Rating object)
        if ( ! empty( $fields['star_rating'] ) ) {
            $schema['starRating'] = array(
                '@type'       => 'Rating',
                'ratingValue' => $fields['star_rating'],
            );
        }

        // Payment accepted (checkboxes -> comma-separated string)
        if ( ! empty( $fields['payment_accepted'] ) && is_array( $fields['payment_accepted'] ) ) {
            $schema['paymentAccepted'] = implode( ', ', $fields['payment_accepted'] );
        }

        // Amenities (checkboxes -> amenityFeature array)
        if ( ! empty( $fields['amenities'] ) && is_array( $fields['amenities'] ) ) {
            $schema['amenityFeature'] = array_map( function ( $a ) {
                return array(
                    '@type' => 'LocationFeatureSpecification',
                    'name'  => $a,
                    'value' => true,
                );
            }, $fields['amenities'] );
        }
    }

    public static function output() {
        if ( ! self::should_output() ) {
            return;
        }

        $schema = self::generate();

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

        $json = wp_json_encode( $schema, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT );

        if ( false === $json ) {
            return;
        }

        // JSON-LD is safe: wp_json_encode escapes all values.
        echo "\n<script type=\"application/ld+json\">\n" . wp_kses_post( $json ) . "\n</script>\n";
    }
}
