<?php
if ( ! defined( 'ABSPATH' ) ) {
    exit; // Exit if accessed directly.
}

class CGC_Fetch {

    public function __construct() {
       // nothing for now
    }

    
    public function get_user_uploads(){
        $user_id = get_current_user_id();

        $args = array(
            'post_type' => 'attachment',
            'post_status' => 'inherit',
            'post_author' => $user_id,
            'posts_per_page' => -1,
            'order' => 'DESC',
            'orderby' => 'date',
            'meta_query' => array(
                array(
                    'key' => 'cgc-design-image',
                    'compare' => 'NOT EXISTS',
                ),
            ),
        );

        $attachments = get_posts( $args );

        $uploads = array();

        if( ! $attachments ) {
            return $uploads;
        }

        foreach( $attachments as $attachment ) {
            $uploads[] = array(
                'id' => $attachment->ID,
                'url' => wp_get_attachment_image_url( $attachment->ID, 'large' ),
                'name' => $attachment->post_title,
            );
        }

        return $uploads;
    }

    public function get_design() {
        global $post;

        if ( ! $post || $post->post_type !== 'cgc-design' ) {
            return null;
        }

  
        $json = unserialize( base64_decode( $post->post_content ) );

        $design = array(
            'name' => $post->post_title,
            'description' => $post->post_excerpt,
            'url' => get_the_post_thumbnail_url( $post->ID, 'full' ),
            'json' => $json,
            'card_id' => $post->ID,
            'width' => get_post_meta( $post->ID, '_cgc_canvas_width', true ),
            'height' => get_post_meta( $post->ID, '_cgc_canvas_height', true ),
            // Falls back to 'giftCard' - the "Template Type" control that
            // used to set this (Label vs Gift Card) is gone from the
            // editor now that this plugin only makes gift cards, but a
            // brand-new design has no _cgc_design_type meta yet, and
            // get_starter_templates() filters on this value being
            // 'giftCard' specifically.
            'type' => get_post_meta( $post->ID, '_cgc_design_type', true ) ?: 'giftCard',
            'starter' => 'open' == $post->ping_status,
            'action' => 'edit',
        );

        return $design;
    }

    public function get_starter_templates( $type = 'giftCard' ) {
        $args = array(
            'post_type' => 'cgc-design',
            'posts_per_page' => -1,
            'post_status' => 'any',
            'order' => 'DESC',
            'ping_status' => 'open',
             'meta_query' => array(
                array(
                    'key' => '_cgc_design_type',
                    'value' => $type,
                ),
            ), 
        );

        $posts = get_posts( $args );

        $templates = array();

        if( ! $posts ) {
            return $templates;
        }

        foreach( $posts as $post ) {

            $json = unserialize( base64_decode($post->post_content) );
            $templates[] = array(
                'name' => $post->post_title,
                'description' => $post->post_excerpt,
                'url' => get_the_post_thumbnail_url( $post->ID, 'full' ),
                'json' => $json,
                'starter' => true,
                'card_id' => $post->ID,
                'width' => get_post_meta( $post->ID, '_cgc_canvas_width', true ),
                'height' => get_post_meta( $post->ID, '_cgc_canvas_height', true ),
                'type' => get_post_meta( $post->ID, '_cgc_design_type', true ),
                'action' => 'create',
            );
        }
        return $templates;

    }

    public function get_designs( $card_id ) {
        $args = array(
            'post_type' => 'cgc-design',
            'posts_per_page' => -1,
            'post_status' => 'any',
            'order' => 'DESC',
            'post_parent' => $card_id,
        );

        $posts = get_posts( $args );

        $designs = array();

        if( ! $posts ) {
            return $designs;
        }

        foreach( $posts as $post ) {

            $json = unserialize( base64_decode($post->post_content) );
            $designs[] = array(
                'name' => $post->post_title,
                'description' => $post->post_excerpt,
                'url' => get_the_post_thumbnail_url( $post->ID, 'full' ),
                'json' => $json,
                'card_id' => $post->ID,
                'starter' => false,
                'width' => get_post_meta( $post->ID, '_cgc_canvas_width', true ),
                'height' => get_post_meta( $post->ID, '_cgc_canvas_height', true ),
                'type' => get_post_meta( $post->ID, '_cgc_design_type', true ),
                'action' => 'edit',
                'key' => uniqid(),
            );
        }
        return $designs;

    }

    // Used by the block/widget editor's "pick a starter/template" design
    // picker - deliberately scoped to post_parent = 0 (starters + the site
    // owner's own "My Templates", per CGC_Post_Type::DESIGN_CATEGORIES) so
    // it can never return "personalized" designs (post_parent != 0 - a
    // specific customer's own customized instance of a template, created at
    // checkout). Those carry a real customer's recipient name/message/photo
    // and must never appear in a shared template-picker listing regardless
    // of who's asking - see the permission_callback on the /designs route
    // in class-cgc-rest-api.php for the complementary access-control fix.
    public function get_all_designs() {
        $args = array(
            'post_type' => 'cgc-design',
            'posts_per_page' => -1,
            'post_status' => 'any',
            'post_parent' => 0,
            'order' => 'DESC',
        );

        $posts = get_posts( $args );

        $designs = array();

        if( ! $posts ) {
            return $designs;
        }

        foreach( $posts as $post ) {

            $json = unserialize( base64_decode($post->post_content) );
            $designs[] = array(
                'name' => $post->post_title,
                'description' => $post->post_excerpt,
                'url' => get_the_post_thumbnail_url( $post->ID, 'full' ),
                'json' => $json,
                'card_id' => $post->ID,
                'starter' => 'open' == $post->ping_status,
                'width' => get_post_meta( $post->ID, '_cgc_canvas_width', true ),
                'height' => get_post_meta( $post->ID, '_cgc_canvas_height', true ),
                'type' => get_post_meta( $post->ID, '_cgc_design_type', true ),
                'action' => 'edit',
                'key' => uniqid(),
            );
        }
        return $designs;

    }

    public function get_designs_by_ids( $ids ) {
        $ids = array_values( array_filter( array_map( 'absint', (array) $ids ) ) );

        $designs = array();

        if( ! $ids ) {
            return $designs;
        }

        $args = array(
            'post_type' => 'cgc-design',
            'posts_per_page' => -1,
            'post_status' => 'any',
            'post__in' => $ids,
            'orderby' => 'post__in',
        );

        $posts = get_posts( $args );

        if( ! $posts ) {
            return $designs;
        }

        foreach( $posts as $post ) {

            $json = unserialize( base64_decode($post->post_content) );
            $designs[] = array(
                'name' => $post->post_title,
                'description' => $post->post_excerpt,
                'url' => get_the_post_thumbnail_url( $post->ID, 'full' ),
                'json' => $json,
                'card_id' => $post->ID,
                'starter' => 'open' == $post->ping_status,
                'width' => get_post_meta( $post->ID, '_cgc_canvas_width', true ),
                'height' => get_post_meta( $post->ID, '_cgc_canvas_height', true ),
                'type' => get_post_meta( $post->ID, '_cgc_design_type', true ),
                'action' => 'edit',
                'key' => uniqid(),
            );
        }
        return $designs;

    }

    // Lean summary for the block editor's product picker - just enough to
    // render a searchable grid, not full variation detail.
    public function get_products_summary( $search = '' ) {
        if ( ! function_exists( 'wc_get_products' ) ) {
            return array();
        }

        $products = wc_get_products( array(
            'type' => array( 'simple', 'variable' ),
            'status' => 'publish',
            'limit' => 20,
            's' => $search,
        ) );

        $summary = array();

        foreach ( $products as $product ) {
            $summary[] = $this->summarize_product( $product );
        }

        return $summary;
    }

    private function summarize_product( $product ) {
        $is_variable = $product->is_type( 'variable' );
        $image_url = wp_get_attachment_image_url( $product->get_image_id(), 'thumbnail' );

        return array(
            'id' => $product->get_id(),
            'name' => $product->get_name(),
            'type' => $is_variable ? 'variable' : 'simple',
            'image' => $image_url ?: wc_placeholder_img_src(),
            'price' => $is_variable ? null : (float) wc_get_price_to_display( $product ),
            'price_min' => $is_variable ? (float) $product->get_variation_price( 'min', true ) : null,
            'price_max' => $is_variable ? (float) $product->get_variation_price( 'max', true ) : null,
            'price_html' => $product->get_price_html(),
        );
    }

    // Full detail for the productIds a field has been configured with -
    // resolved server-side at render time so the frontend never needs its
    // own WooCommerce REST call. For variable products this includes every
    // available variation's attributes/price so the frontend can match a
    // customer's attribute selection to a variation without another request.
    public function get_products_by_ids( $ids ) {
        $ids = array_values( array_filter( array_map( 'absint', (array) $ids ) ) );

        if ( ! $ids || ! function_exists( 'wc_get_products' ) ) {
            return array();
        }

        $products = wc_get_products( array(
            'type' => array( 'simple', 'variable' ),
            'include' => $ids,
            'limit' => -1,
        ) );

        $by_id = array();
        foreach ( $products as $product ) {
            $by_id[ $product->get_id() ] = $product;
        }

        $resolved = array();

        foreach ( $ids as $id ) {
            if ( empty( $by_id[ $id ] ) ) {
                continue; // deleted/unpublished since being picked - silently omit
            }

            $product = $by_id[ $id ];

            if ( ! $product->is_purchasable() ) {
                continue;
            }

            $entry = $this->summarize_product( $product );

            if ( $product->is_type( 'variable' ) ) {
                $entry['variations'] = array();
                $available_values = array();

                foreach ( $product->get_available_variations( 'objects' ) as $variation ) {
                    // Strip the "attribute_" prefix WooCommerce stores these
                    // under so the frontend can key off the same slugs as
                    // the "attributes" map built below.
                    $attributes = array();
                    foreach ( $variation->get_variation_attributes() as $key => $value ) {
                        $attr_key = preg_replace( '/^attribute_/', '', $key );
                        $attributes[ $attr_key ] = $value;

                        // Empty string is WooCommerce's "matches any option"
                        // wildcard, not a concrete choice to offer.
                        if ( '' !== $value ) {
                            $available_values[ $attr_key ][ $value ] = true;
                        }
                    }

                    $entry['variations'][] = array(
                        'variation_id' => $variation->get_id(),
                        'attributes' => $attributes,
                        'price' => (float) wc_get_price_to_display( $variation ),
                        'in_stock' => $variation->is_in_stock(),
                    );
                }

                // Deliberately NOT $product->get_variation_attributes() here -
                // that includes values from variations that are out of
                // stock/disabled/trashed, which would offer a choice in the
                // dropdown with no way to ever resolve a real variation for
                // it. Only offer values at least one *available* variation
                // actually uses.
                $entry['attributes'] = array();
                foreach ( $available_values as $attr_key => $values ) {
                    $entry['attributes'][ $attr_key ] = array_keys( $values );
                }
            }

            $addons = $this->get_product_addons( $id );
            if ( $addons ) {
                $entry['addons'] = $addons;
            }

            $resolved[] = $entry;
        }

        return $resolved;
    }

    // WooCommerce Product Add-Ons (_product_addons post meta) attaches to
    // the parent product, never a variation, so this is always called with
    // a product ID even when the customer ends up picking a variation.
    // Only the "core selection" addon types are supported (checkbox, radio,
    // select, custom text/textarea) - anything else (heading, file upload,
    // custom price, datepicker, etc.) is silently skipped so neither editor
    // nor frontend ever has to handle it. Used both to resolve render-time
    // config here and to re-validate/re-price a submission server-side in
    // CGC_Rest_API::add_to_cart() - keeping this the single normalization
    // path is what keeps those two call sites from drifting apart.
    public function get_product_addons( $product_id ) {
        if ( ! defined( 'WC_PRODUCT_ADDONS_VERSION' ) ) {
            return array();
        }

        $groups = get_post_meta( $product_id, '_product_addons', true );

        if ( ! is_array( $groups ) ) {
            return array();
        }

        $supported_types = array( 'checkbox', 'radio', 'select', 'custom_text', 'custom_textarea' );
        $addons = array();

        foreach ( array_values( $groups ) as $index => $group ) {
            if ( ! is_array( $group ) || empty( $group['name'] ) || empty( $group['type'] ) ) {
                continue;
            }

            if ( ! in_array( $group['type'], $supported_types, true ) ) {
                continue;
            }

            $addon = array(
                'index' => $index,
                'name' => sanitize_text_field( $group['name'] ),
                // custom_text/custom_textarea keep their own type name
                // (the markup/client both branch on it directly); the
                // three choice types stay as-is too.
                'type' => 'custom_text' === $group['type'] ? 'text' : ( 'custom_textarea' === $group['type'] ? 'textarea' : $group['type'] ),
                'required' => ! empty( $group['required'] ),
            );

            if ( in_array( $group['type'], array( 'checkbox', 'radio', 'select' ), true ) ) {
                $options = array();
                foreach ( (array) ( $group['options'] ?? array() ) as $option ) {
                    if ( ! is_array( $option ) || ! isset( $option['label'] ) ) {
                        continue;
                    }
                    $options[] = array(
                        'label' => sanitize_text_field( $option['label'] ),
                        'price' => (float) ( $option['price'] ?? 0 ),
                        // Cart quantity is always hardcoded to 1 in this
                        // plugin (see add_to_cart()), so quantity_based and
                        // flat_fee are mathematically identical here - only
                        // percentage_based needs distinct handling.
                        'price_type' => 'percentage_based' === ( $option['price_type'] ?? '' ) ? 'percentage' : 'flat',
                    );
                }
                if ( ! $options ) {
                    continue; // a choice group with nothing to choose isn't renderable
                }
                $addon['options'] = $options;
            } else {
                $addon['price'] = (float) ( $group['price'] ?? 0 );
                $addon['price_type'] = 'percentage_based' === ( $group['price_type'] ?? '' ) ? 'percentage' : 'flat';
            }

            $addons[] = $addon;
        }

        return $addons;
    }
}

global $cgc_fetch;
$cgc_fetch = new CGC_Fetch();
