<?php

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

trait Niwa_AI_Tools_Bulk_Pricing {

    private function validate_bulk_catalog_price_action_args( $args ) {
        $items = isset( $args['items'] ) && is_array( $args['items'] ) ? array_values( $args['items'] ) : array();
        if ( empty( $items ) ) {
            return array(
                'success' => false,
                'error'   => 'Bulk Woo price update nema nijednu ciljanu stavku.',
            );
        }

        if ( count( $items ) > self::MAX_BULK_CATALOG_TARGETS ) {
            return array(
                'success' => false,
                'error'   => 'Bulk Woo price update prelazi maksimalan broj ciljnih stavki za jedan run.',
            );
        }

        foreach ( $items as $item ) {
            $kind = isset( $item['kind'] ) ? (string) $item['kind'] : 'simple_product';
            if ( 'variation' === $kind ) {
                $id_check = $this->validate_required_positive_id( isset( $item['variation_id'] ) ? $item['variation_id'] : 0, 'Bulk Woo update ima nevalidnu varijaciju.' );
                if ( empty( $id_check['success'] ) ) {
                    return $id_check;
                }
            } else {
                $id_check = $this->validate_required_positive_id( isset( $item['product_id'] ) ? $item['product_id'] : 0, 'Bulk Woo update ima nevalidan proizvod.' );
                if ( empty( $id_check['success'] ) ) {
                    return $id_check;
                }
            }

            $has_price_change = false;
            foreach ( array( 'new_regular_price', 'new_sale_price' ) as $field ) {
                if ( array_key_exists( $field, $item ) && null !== $item[ $field ] && '' !== trim( (string) $item[ $field ] ) ) {
                    $has_price_change = true;
                    break;
                }
            }

            if ( ! $has_price_change && empty( $item['clear_sale_price'] ) ) {
                return array(
                    'success' => false,
                    'error'   => 'Bulk Woo update sadrzi stavku bez ikakve cenovne promene.',
                );
            }
        }

        return array(
            'success' => true,
        );
    }

    private function preview_bulk_update_catalog_prices( $args, $prompt = '' ) {
        if ( ! class_exists( 'WooCommerce' ) || ! function_exists( 'wc_get_product' ) ) {
            return array(
                'success' => false,
                'error'   => 'WooCommerce nije aktivan.',
            );
        }

        $scope_result = $this->resolve_bulk_price_scope( $args, $prompt );
        if ( empty( $scope_result['success'] ) ) {
            return $scope_result;
        }

        $change_result = $this->resolve_bulk_price_change( $args, $prompt );
        if ( empty( $change_result['success'] ) ) {
            return $change_result;
        }

        $limit              = isset( $args['limit'] ) ? max( 1, min( self::MAX_BULK_CATALOG_TARGETS, intval( $args['limit'] ) ) ) : self::MAX_BULK_CATALOG_TARGETS;
        $include_sale_prices = ! array_key_exists( 'include_sale_prices', $args ) || ! empty( $args['include_sale_prices'] );
        $collection         = $this->collect_bulk_price_targets( $scope_result['scope'], $limit );
        if ( empty( $collection['success'] ) ) {
            return $collection;
        }

        $items         = array();
        $target_preview = array();
        $skipped_count = 0;
        foreach ( (array) $collection['targets'] as $target ) {
            $planned = $this->plan_bulk_price_change_for_target( $target, $change_result['mode'], $change_result['value'], $include_sale_prices );
            if ( empty( $planned['success'] ) ) {
                if ( ! empty( $planned['skipped'] ) ) {
                    $skipped_count++;
                    continue;
                }

                return $planned;
            }

            $items[] = $planned['item'];
            if ( count( $target_preview ) < 25 ) {
                $target_preview[] = array(
                    'post_id'        => intval( isset( $target['post_id'] ) ? $target['post_id'] : 0 ),
                    'variation_id'   => intval( isset( $target['variation_id'] ) ? $target['variation_id'] : 0 ),
                    'post_title'     => isset( $target['post_title'] ) ? (string) $target['post_title'] : '',
                    'target_label'   => isset( $planned['item']['target_label'] ) ? (string) $planned['item']['target_label'] : '',
                    'product_type'   => isset( $target['product_type'] ) ? (string) $target['product_type'] : '',
                    'regular_price'  => isset( $target['regular_price'] ) ? (string) $target['regular_price'] : '',
                    'new_regular_price' => isset( $planned['item']['new_regular_price'] ) ? (string) $planned['item']['new_regular_price'] : '',
                    'sale_price'     => isset( $target['sale_price'] ) ? (string) $target['sale_price'] : '',
                    'new_sale_price' => isset( $planned['item']['new_sale_price'] ) ? (string) $planned['item']['new_sale_price'] : '',
                );
            }
        }

        if ( empty( $items ) ) {
            return array(
                'success' => false,
                'error'   => 'Nisam nasla nijedan live Woo proizvod sa cenom koju mogu da izmenim za taj katalogski zahtev.',
            );
        }

        $warnings = array();
        if ( ! empty( $collection['truncated'] ) ) {
            $warnings[] = 'Katalog je veci od limita za jedan run, pa sam obuhvatila prvih ' . count( $collection['targets'] ) . ' stavki.';
        }
        if ( $skipped_count > 0 ) {
            $warnings[] = 'Preskoceno je ' . intval( $skipped_count ) . ' stavki bez validne cene.';
        }

        $changed_count   = count( $items );
        $scope_label     = 'live_products_and_variations' === $scope_result['scope'] ? 'live proizvoda i varijacija' : 'live proizvoda';
        $change_summary  = $this->describe_bulk_price_change( $change_result['mode'], $change_result['value'], $include_sale_prices );
        $rollback_plan   = 'Vraca prethodne Woo regular i sale cene za sve izmenjene stavke.';

        return array(
            'success'  => true,
            'action'   => array(
                'type'             => 'bulk_update_catalog_prices',
                'label'            => 'Bulk Woo update cena',
                'summary'          => 'Primeni ' . $change_summary . ' na ' . intval( $changed_count ) . ' ' . $scope_label . '.',
                'rollback_plan'    => $rollback_plan,
                'rollback_support' => 'full',
                'targets'          => $target_preview,
                'args'             => array(
                    'scope'               => $scope_result['scope'],
                    'change_mode'         => $change_result['mode'],
                    'change_value'        => $change_result['value'],
                    'include_sale_prices' => $include_sale_prices ? 1 : 0,
                    'items'               => $items,
                ),
            ),
            'warnings' => $warnings,
        );
    }

    private function execute_bulk_update_catalog_prices_action( $action ) {
        if ( ! function_exists( 'wc_get_product' ) ) {
            return array( 'success' => false, 'error' => 'WooCommerce nije dostupan.' );
        }

        $items    = isset( $action['args']['items'] ) && is_array( $action['args']['items'] ) ? array_values( $action['args']['items'] ) : array();
        $executed = array();
        $rollback = array();
        $parents  = array();
        $unchanged = array();

        if ( empty( $items ) ) {
            return array( 'success' => false, 'error' => 'Bulk Woo update nema nijednu ciljanu stavku.' );
        }

        foreach ( $items as $item ) {
            $kind = isset( $item['kind'] ) ? (string) $item['kind'] : 'simple_product';

            if ( 'variation' === $kind ) {
                $variation_id = intval( isset( $item['variation_id'] ) ? $item['variation_id'] : 0 );
                $variation    = wc_get_product( $variation_id );
                if ( ! $variation || ! $variation->is_type( 'variation' ) ) {
                    $this->rollback_entries( $rollback );
                    return array( 'success' => false, 'error' => 'Ciljna Woo varijacija vise ne postoji: #' . $variation_id );
                }

                $apply = $this->apply_bulk_price_item_to_product( $variation, $item );
                if ( empty( $apply['success'] ) ) {
                    $this->rollback_entries( $rollback );
                    return $apply;
                }

                if ( method_exists( $variation, 'get_changes' ) && empty( $variation->get_changes() ) ) {
                    $unchanged[] = array(
                        'type'         => 'bulk_update_catalog_prices',
                        'variation_id' => $variation_id,
                        'unchanged'    => true,
                    );
                    continue;
                }

                $rollback[] = $this->build_variation_restore_entry( $variation );

                $saved = $variation->save();
                if ( ! $saved ) {
                    $this->rollback_entries( $rollback );
                    return array( 'success' => false, 'error' => 'Woo varijacija nije sacuvana tokom bulk price update-a.' );
                }

                $parent_id = intval( isset( $item['parent_id'] ) ? $item['parent_id'] : $variation->get_parent_id() );
                if ( $parent_id > 0 ) {
                    $parents[ $parent_id ] = true;
                }

                $executed[] = array(
                    'type'         => 'bulk_update_catalog_prices',
                    'variation_id' => $variation_id,
                    'changes'      => $apply['changes'],
                );
                continue;
            }

            $product_id = intval( isset( $item['product_id'] ) ? $item['product_id'] : 0 );
            $post       = get_post( $product_id );
            if ( ! $post || 'product' !== $post->post_type ) {
                $this->rollback_entries( $rollback );
                return array( 'success' => false, 'error' => 'Ciljni proizvod vise ne postoji: #' . $product_id );
            }

            if ( 'trash' === (string) $post->post_status ) {
                $this->rollback_entries( $rollback );
                return array( 'success' => false, 'error' => 'Proizvod je zavrsio u trash-u tokom bulk update-a: #' . $product_id );
            }

            $product = wc_get_product( $product_id );
            if ( ! $product || ! $product->is_type( 'simple' ) ) {
                $this->rollback_entries( $rollback );
                return array( 'success' => false, 'error' => 'Bulk price update trenutno podrzava live simple proizvode i pojedinacne varijacije. Ne mogu da nastavim sa #' . $product_id . '.' );
            }

            $apply = $this->apply_bulk_price_item_to_product( $product, $item );
            if ( empty( $apply['success'] ) ) {
                $this->rollback_entries( $rollback );
                return $apply;
            }

            if ( method_exists( $product, 'get_changes' ) && empty( $product->get_changes() ) ) {
                $unchanged[] = array(
                    'type'       => 'bulk_update_catalog_prices',
                    'product_id' => $product_id,
                    'unchanged'  => true,
                );
                continue;
            }

            $rollback[] = $this->build_simple_product_restore_entry( $product_id, $product );

            $saved = $product->save();
            if ( ! $saved ) {
                $this->rollback_entries( $rollback );
                return array( 'success' => false, 'error' => 'Woo proizvod nije sacuvan tokom bulk price update-a.' );
            }

            $this->sync_product_ops_write( $product_id );

            $executed[] = array(
                'type'       => 'bulk_update_catalog_prices',
                'product_id' => $product_id,
                'changes'    => $apply['changes'],
            );
        }

        if ( empty( $executed ) ) {
            return array(
                'success'         => false,
                'error'           => 'Sve bulk catalog cene su vec u trazenom stanju; nema promene za snimanje.',
                'unchanged_items' => $unchanged,
            );
        }

        foreach ( array_keys( $parents ) as $parent_id ) {
            $this->sync_variable_parent( intval( $parent_id ) );
        }

        return array(
            'success'          => true,
            'summary'          => 'Azurirala sam cene za ' . count( $executed ) . ' live Woo stavki.',
            'executed_actions' => $executed,
            'rollback_entries' => $rollback,
            'unchanged_items'  => $unchanged,
        );
    }

    private function resolve_bulk_price_scope( $args, $prompt = '' ) {
        $scope = isset( $args['scope'] ) ? sanitize_key( (string) $args['scope'] ) : '';
        if ( in_array( $scope, array( 'live_products', 'live_products_and_variations' ), true ) ) {
            return array(
                'success' => true,
                'scope'   => $scope,
            );
        }

        $source = remove_accents( strtolower( trim( (string) $prompt ) ) );
        if ( false !== strpos( $source, 'varijac' ) || false !== strpos( $source, 'variation' ) ) {
            return array(
                'success' => true,
                'scope'   => 'live_products_and_variations',
            );
        }

        return array(
            'success' => true,
            'scope'   => 'live_products',
        );
    }

    private function resolve_bulk_price_change( $args, $prompt = '' ) {
        $mode  = isset( $args['change_mode'] ) ? sanitize_key( (string) $args['change_mode'] ) : '';
        $value = isset( $args['change_value'] ) ? trim( (string) $args['change_value'] ) : '';

        if ( '' === $mode && '' !== trim( (string) $prompt ) ) {
            $normalized_prompt = remove_accents( strtolower( trim( (string) $prompt ) ) );
            if ( false !== strpos( $normalized_prompt, '%' ) || false !== strpos( $normalized_prompt, ' posto' ) || false !== strpos( $normalized_prompt, ' percent' ) || false !== strpos( $normalized_prompt, 'procen' ) ) {
                $mode = 'percent';
            }
        }

        if ( '' === $value && '' !== trim( (string) $prompt ) && preg_match( '/(-?\d+(?:[.,]\d+)?)/', (string) $prompt, $matches ) ) {
            $value = (string) $matches[1];
        }

        if ( ! in_array( $mode, array( 'percent', 'fixed_delta', 'set_regular_price' ), true ) ) {
            return array(
                'success' => false,
                'error'   => 'Treba mi jasan tip bulk promene cene: percent, fixed_delta ili set_regular_price.',
            );
        }

        $normalized_value = $this->normalize_decimal_price( $value );
        if ( null === $normalized_value ) {
            return array(
                'success' => false,
                'error'   => 'Bulk promena cene nema validnu brojcanu vrednost.',
            );
        }

        return array(
            'success' => true,
            'mode'    => $mode,
            'value'   => (string) $normalized_value,
        );
    }

    private function collect_bulk_price_targets( $scope, $limit ) {
        if ( ! function_exists( 'wc_get_product' ) ) {
            return array(
                'success' => false,
                'error'   => 'WooCommerce nije dostupan.',
            );
        }

        $scope     = in_array( (string) $scope, array( 'live_products', 'live_products_and_variations' ), true ) ? (string) $scope : 'live_products';
        $limit     = max( 1, min( self::MAX_BULK_CATALOG_TARGETS, intval( $limit ) ) );
        $targets    = array();
        $seen       = array();
        $truncated  = false;

        $product_ids = get_posts(
            array(
                'post_type'              => 'product',
                'post_status'            => array( 'publish' ),
                'posts_per_page'         => $limit + 1,
                'fields'                 => 'ids',
                'orderby'                => 'ID',
                'order'                  => 'ASC',
                'no_found_rows'          => true,
                'update_post_term_cache' => false,
                'update_post_meta_cache' => false,
            )
        );

        foreach ( (array) $product_ids as $product_id ) {
            if ( count( $targets ) >= $limit ) {
                $truncated = true;
                break;
            }

            $post    = get_post( intval( $product_id ) );
            $product = $post ? wc_get_product( intval( $product_id ) ) : false;
            if ( ! $post || ! $product || 'product' !== (string) $post->post_type ) {
                continue;
            }

            if ( $product->is_type( 'simple' ) ) {
                $target                 = $this->build_product_target( $post, $product );
                $target['kind']         = 'simple_product';
                $target['target_label'] = (string) $post->post_title;
                $targets[]              = $target;
                $seen[ 'p:' . intval( $post->ID ) ] = true;
            }
        }

        if ( 'live_products_and_variations' === $scope && count( $targets ) < $limit ) {
            $variation_ids = get_posts(
                array(
                    'post_type'              => 'product_variation',
                    'post_status'            => array( 'publish' ),
                    'posts_per_page'         => $limit + 1,
                    'fields'                 => 'ids',
                    'orderby'                => 'ID',
                    'order'                  => 'ASC',
                    'no_found_rows'          => true,
                    'update_post_term_cache' => false,
                    'update_post_meta_cache' => false,
                )
            );

            foreach ( (array) $variation_ids as $variation_id ) {
                if ( count( $targets ) >= $limit ) {
                    $truncated = true;
                    break;
                }

                $key = 'v:' . intval( $variation_id );
                if ( isset( $seen[ $key ] ) ) {
                    continue;
                }

                $variation = wc_get_product( intval( $variation_id ) );
                if ( ! $variation || ! $variation->is_type( 'variation' ) ) {
                    continue;
                }

                $parent_id = intval( $variation->get_parent_id() );
                $parent    = $parent_id > 0 ? get_post( $parent_id ) : null;
                $post      = get_post( intval( $variation_id ) );
                if ( ! $post || ! $parent || 'publish' !== (string) $parent->post_status ) {
                    continue;
                }

                $targets[]   = $this->build_variation_bulk_target( $variation, $parent );
                $seen[ $key ] = true;
            }
        }

        return array(
            'success'   => true,
            'targets'   => $targets,
            'truncated' => $truncated,
        );
    }

    private function plan_bulk_price_change_for_target( $target, $change_mode, $change_value, $include_sale_prices ) {
        $current_regular = isset( $target['regular_price'] ) ? trim( (string) $target['regular_price'] ) : '';
        $current_sale    = isset( $target['sale_price'] ) ? trim( (string) $target['sale_price'] ) : '';

        if ( '' === $current_regular && '' === $current_sale ) {
            return array(
                'success' => false,
                'skipped' => true,
            );
        }

        $base_regular = '' !== $current_regular ? $current_regular : $current_sale;
        $new_regular  = $this->calculate_bulk_adjusted_price( $base_regular, $change_mode, $change_value );
        if ( null === $new_regular ) {
            return array(
                'success' => false,
                'error'   => 'Neuspesan obracun nove regular cene za bulk Woo update.',
            );
        }

        $new_sale        = null;
        $clear_sale_price = false;
        if ( $include_sale_prices && '' !== $current_sale ) {
            $computed_sale = $this->calculate_bulk_adjusted_price( $current_sale, $change_mode, $change_value );
            if ( null === $computed_sale ) {
                return array(
                    'success' => false,
                    'error'   => 'Neuspesan obracun nove sale cene za bulk Woo update.',
                );
            }
            $new_sale = $this->ensure_sale_price_below_regular( $computed_sale, $new_regular );
        } elseif ( ! $include_sale_prices && '' !== $current_sale ) {
            $new_sale = $this->ensure_sale_price_below_regular( $current_sale, $new_regular );
        }

        if ( null !== $new_sale && '' === trim( (string) $new_sale ) ) {
            $clear_sale_price = true;
            $new_sale         = null;
        }

        return array(
            'success' => true,
            'item'    => array(
                'kind'              => isset( $target['kind'] ) ? (string) $target['kind'] : 'simple_product',
                'product_id'        => intval( isset( $target['post_id'] ) ? $target['post_id'] : 0 ),
                'variation_id'      => intval( isset( $target['variation_id'] ) ? $target['variation_id'] : 0 ),
                'parent_id'         => intval( isset( $target['parent_id'] ) ? $target['parent_id'] : 0 ),
                'target_label'      => isset( $target['target_label'] ) ? (string) $target['target_label'] : ( isset( $target['post_title'] ) ? (string) $target['post_title'] : '' ),
                'new_regular_price' => (string) $new_regular,
                'new_sale_price'    => null !== $new_sale ? (string) $new_sale : null,
                'clear_sale_price'  => $clear_sale_price ? 1 : 0,
            ),
        );
    }

    private function calculate_bulk_adjusted_price( $current_price, $change_mode, $change_value ) {
        $current = $this->normalize_decimal_price( $current_price );
        $delta   = $this->normalize_decimal_price( $change_value );
        if ( null === $current || null === $delta ) {
            return null;
        }

        $current_float = floatval( $current );
        $delta_float   = floatval( $delta );

        if ( 'percent' === $change_mode ) {
            $result = $current_float * ( 1 + ( $delta_float / 100 ) );
        } elseif ( 'fixed_delta' === $change_mode ) {
            $result = $current_float + $delta_float;
        } else {
            $result = $delta_float;
        }

        if ( $result < 0 ) {
            $result = 0;
        }

        return function_exists( 'wc_format_decimal' ) ? wc_format_decimal( $result, wc_get_price_decimals() ) : (string) $result;
    }

    private function ensure_sale_price_below_regular( $sale_price, $regular_price ) {
        $sale    = $this->normalize_decimal_price( $sale_price );
        $regular = $this->normalize_decimal_price( $regular_price );
        if ( null === $sale || null === $regular ) {
            return null;
        }

        if ( floatval( $sale ) < floatval( $regular ) ) {
            return $sale;
        }

        $step   = function_exists( 'wc_get_price_decimals' ) ? 1 / pow( 10, wc_get_price_decimals() ) : 0.01;
        $next   = max( 0, floatval( $regular ) - $step );
        if ( $next <= 0 ) {
            return '';
        }

        return function_exists( 'wc_format_decimal' ) ? wc_format_decimal( $next, wc_get_price_decimals() ) : (string) $next;
    }

    private function describe_bulk_price_change( $mode, $value, $include_sale_prices ) {
        $sale_note = $include_sale_prices ? ' zajedno sa sale cenama gde postoje' : '';
        if ( 'percent' === $mode ) {
            return $value . '%' . $sale_note;
        }
        if ( 'fixed_delta' === $mode ) {
            return 'delta ' . $value . $sale_note;
        }

        return 'regular price = ' . $value;
    }

}
