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

/**
 * Maps JetEngine CCT / MetaBox custom fields → Schema.org properties.
 */
class AISB_Field_Mapper {

    /** Schema.org targets we can map to (Google-friendly). */
    public static function schema_targets() {
        return [
            'headline'       => 'headline / name',
            'description'    => 'description',
            'startDate'      => 'startDate (Event)',
            'endDate'        => 'endDate (Event)',
            'datePublished'  => 'datePublished',
            'price'          => 'offers.price',
            'priceCurrency'  => 'offers.priceCurrency',
            'sku'            => 'sku (Product)',
            'telephone'      => 'telephone (LocalBusiness)',
            'email'          => 'email',
            'streetAddress'  => 'address.streetAddress',
            'addressLocality'=> 'address.addressLocality',
            'postalCode'     => 'address.postalCode',
            'addressCountry' => 'address.addressCountry',
            'latitude'       => 'geo.latitude',
            'longitude'      => 'geo.longitude',
            'locationName'   => 'location.name (Event)',
            'url'            => 'url',
            'image'          => 'image (URL)',
            'jobTitle'       => 'title (JobPosting)',
            'validThrough'   => 'validThrough (JobPosting)',
        ];
    }

    public static function get_map() {
        $s = aisb_get_settings();
        $map = isset($s['schema_field_map']) && is_array($s['schema_field_map']) ? $s['schema_field_map'] : [];
        $clean = [];
        $targets = array_keys(self::schema_targets());
        foreach ($map as $pt => $fields) {
            if (!is_array($fields)) {
                continue;
            }
            $pt = sanitize_key($pt);
            $clean[$pt] = [];
            foreach ($fields as $source => $target) {
                $target = sanitize_key($target);
                if ($pt && $source && in_array($target, $targets, true)) {
                    $clean[$pt][sanitize_key($source)] = $target;
                }
            }
        }
        return apply_filters('aisb_schema_field_map', $clean);
    }

    /** Collect external field values for a post (CCT + MetaBox + jet meta). */
    public static function extract_external_fields($post_id) {
        $post_id = (int) $post_id;
        $data = [];

        if (AISB_JetEngine_CCT::is_active()) {
            $cct = AISB_JetEngine_CCT::get_item_for_post($post_id);
            if (is_array($cct)) {
                $data = array_merge($data, $cct);
            }
        }

        if (AISB_MetaBox_Fields::is_active()) {
            $data = array_merge($data, AISB_MetaBox_Fields::get_row_for_post($post_id));
        }

        $data = array_merge($data, self::extract_jet_post_meta($post_id));

        return apply_filters('aisb_external_fields_for_post', $data, $post_id);
    }

    private static function extract_jet_post_meta($post_id) {
        $out = [];
        foreach (get_post_meta($post_id) as $key => $values) {
            if (strpos($key, 'jet') === false && strpos($key, '_jet') === false) {
                continue;
            }
            $v = is_array($values) ? ($values[0] ?? '') : $values;
            if (is_scalar($v) && $v !== '') {
                $out[preg_replace('/^_+/', '', $key)] = $v;
            }
        }
        return $out;
    }

    /** Auto-suggest field → schema mappings from field names. */
    public static function suggest_mappings($field_names, $schema_type = '') {
        $rules = [
            'startDate'       => ['start_date', 'event_date', 'date_start', 'cct_start', 'start', 'data_rozpoczecia'],
            'endDate'         => ['end_date', 'event_end', 'date_end', 'cct_end', 'koniec'],
            'description'     => ['description', 'desc', 'summary', 'opis', 'excerpt'],
            'headline'        => ['title', 'name', 'headline', 'nazwa', 'event_name'],
            'price'           => ['price', 'cena', 'cost', 'amount'],
            'priceCurrency'   => ['currency', 'waluta', 'price_currency'],
            'telephone'       => ['phone', 'telephone', 'tel', 'telefon'],
            'email'           => ['email', 'e-mail', 'mail'],
            'streetAddress'   => ['address', 'street', 'ulica', 'street_address', 'adres'],
            'addressLocality' => ['city', 'locality', 'miasto', 'town'],
            'postalCode'      => ['postal', 'zip', 'postcode', 'kod_pocztowy'],
            'latitude'        => ['lat', 'latitude'],
            'longitude'       => ['lng', 'lon', 'longitude'],
            'locationName'    => ['venue', 'location_name', 'venue_name', 'miejsce', 'place'],
            'image'           => ['image', 'photo', 'thumbnail', 'zdjecie', 'img'],
            'url'             => ['url', 'link', 'website', 'strona'],
            'sku'             => ['sku', 'product_code'],
            'jobTitle'        => ['job_title', 'position', 'stanowisko'],
            'validThrough'    => ['valid_through', 'expiry', 'deadline'],
        ];

        $suggestions = [];
        foreach ((array) $field_names as $field) {
            $field = sanitize_key($field);
            $hay = strtolower($field);
            foreach ($rules as $target => $needles) {
                foreach ($needles as $needle) {
                    if ($hay === $needle || strpos($hay, $needle) !== false) {
                        $suggestions[$field] = $target;
                        break 2;
                    }
                }
            }
        }
        return $suggestions;
    }

    public static function discover_fields_for_post_type($post_type) {
        $post_type = sanitize_key($post_type);
        $fields = [];

        $cct = AISB_JetEngine_CCT::cct_for_post_type($post_type);
        if ($cct && !empty($cct['fields'])) {
            $fields = array_merge($fields, $cct['fields']);
        }

        $mb = AISB_MetaBox_Fields::discover_tables();
        if (!empty($mb[$post_type]['fields'])) {
            $fields = array_merge($fields, $mb[$post_type]['fields']);
        }

        return array_values(array_unique(array_filter($fields)));
    }

    public static function seed_map_for_post_type($post_type) {
        $post_type = sanitize_key($post_type);
        $schema_type = AISB_CPT_Registry::get_schema_type_for_post_type($post_type);
        $fields = self::discover_fields_for_post_type($post_type);
        if (empty($fields)) {
            return [];
        }
        return self::suggest_mappings($fields, $schema_type);
    }

    public static function apply_to_schema($schema, $post_id, $schema_type = '') {
        if (!is_array($schema) || !$post_id) {
            return $schema;
        }
        $post_type = get_post_type($post_id);
        $map = self::get_map();
        $pt_map = $map[$post_type] ?? [];
        if (empty($pt_map)) {
            $pt_map = self::seed_map_for_post_type($post_type);
        }
        if (empty($pt_map)) {
            return $schema;
        }

        $external = self::extract_external_fields($post_id);
        if (empty($external)) {
            return $schema;
        }

        foreach ($pt_map as $source_field => $target) {
            if (!isset($external[$source_field]) || $external[$source_field] === '') {
                continue;
            }
            $value = $external[$source_field];
            $schema = self::set_schema_value($schema, $target, $value, $schema_type);
        }

        return apply_filters('aisb_schema_after_field_map', $schema, $post_id, $external);
    }

    public static function context_for_prompt($post_id) {
        $external = self::extract_external_fields($post_id);
        if (empty($external)) {
            return '';
        }
        $lines = [];
        foreach ($external as $k => $v) {
            if (strlen((string) $v) > 500) {
                $v = substr((string) $v, 0, 500);
            }
            $lines[] = $k . ': ' . $v;
        }
        return "Custom fields (CCT/MetaBox):\n" . implode("\n", array_slice($lines, 0, 40));
    }

    private static function set_schema_value($schema, $target, $value, $schema_type) {
        $value = is_string($value) ? trim($value) : $value;

        if ($target === 'headline' && empty($schema['headline'])) {
            $schema['headline'] = $value;
        } elseif ($target === 'description' && empty($schema['description'])) {
            $schema['description'] = $value;
        } elseif ($target === 'startDate' && empty($schema['startDate'])) {
            $schema['startDate'] = self::normalize_date($value);
        } elseif ($target === 'endDate' && empty($schema['endDate'])) {
            $schema['endDate'] = self::normalize_date($value);
        } elseif ($target === 'telephone' && empty($schema['telephone'])) {
            $schema['telephone'] = $value;
        } elseif ($target === 'email' && empty($schema['email'])) {
            $schema['email'] = $value;
        } elseif ($target === 'url' && empty($schema['url'])) {
            $schema['url'] = esc_url_raw($value);
        } elseif ($target === 'image' && empty($schema['image'])) {
            $schema['image'] = is_numeric($value) ? wp_get_attachment_url((int) $value) : esc_url_raw($value);
        } elseif ($target === 'sku' && empty($schema['sku'])) {
            $schema['sku'] = $value;
        } elseif ($target === 'jobTitle' && $schema_type === 'JobPosting' && empty($schema['title'])) {
            $schema['title'] = $value;
        } elseif ($target === 'validThrough' && empty($schema['validThrough'])) {
            $schema['validThrough'] = self::normalize_date($value);
        } elseif ($target === 'price') {
            if (empty($schema['offers'])) {
                $schema['offers'] = ['@type' => 'Offer'];
            }
            if (is_array($schema['offers']) && empty($schema['offers']['price'])) {
                $schema['offers']['price'] = $value;
            }
        } elseif ($target === 'priceCurrency') {
            if (empty($schema['offers'])) {
                $schema['offers'] = ['@type' => 'Offer'];
            }
            if (is_array($schema['offers']) && empty($schema['offers']['priceCurrency'])) {
                $schema['offers']['priceCurrency'] = $value;
            }
        } elseif ($target === 'locationName') {
            if (empty($schema['location']) || !is_array($schema['location'])) {
                $schema['location'] = ['@type' => 'Place'];
            }
            if (empty($schema['location']['name'])) {
                $schema['location']['name'] = $value;
            }
        } elseif (strpos($target, 'address.') === 0) {
            $part = substr($target, 8);
            if (empty($schema['address']) || !is_array($schema['address'])) {
                $schema['address'] = ['@type' => 'PostalAddress'];
            }
            if (empty($schema['address'][$part])) {
                $schema['address'][$part] = $value;
            }
        } elseif (strpos($target, 'geo.') === 0) {
            $part = substr($target, 4);
            if (empty($schema['geo']) || !is_array($schema['geo'])) {
                $schema['geo'] = ['@type' => 'GeoCoordinates'];
            }
            if (empty($schema['geo'][$part])) {
                $schema['geo'][$part] = $value;
            }
        }

        return $schema;
    }

    private static function normalize_date($value) {
        $value = trim((string) $value);
        if ($value === '') {
            return '';
        }
        $ts = strtotime($value);
        return $ts ? gmdate('c', $ts) : $value;
    }
}
