<?php

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

final class CPF_Artwork_Wizard
{
    private const PAGE_SLUG = 'canvas-artwork-wizard';

    public function __construct()
    {
        add_action('admin_menu', [$this, 'register_page']);
        add_action('admin_enqueue_scripts', [$this, 'enqueue_assets']);
        add_action('admin_post_cpf_create_artwork', [$this, 'create_artwork']);
    }

    public function register_page(): void
    {
        add_submenu_page(
            'woocommerce',
            'Add Canvas Artwork',
            'Add Canvas Artwork',
            'manage_woocommerce',
            self::PAGE_SLUG,
            [$this, 'render_page']
        );
    }

    public function enqueue_assets(string $hook): void
    {
        if (!str_contains($hook, self::PAGE_SLUG)) {
            return;
        }

        wp_enqueue_media();
        wp_register_style('cpf-artwork-wizard', false, [], '1.2.0');
        wp_enqueue_style('cpf-artwork-wizard');
        wp_add_inline_style('cpf-artwork-wizard', $this->css());
        wp_register_script('cpf-artwork-wizard', false, ['jquery'], '1.2.0', true);
        wp_enqueue_script('cpf-artwork-wizard');
        wp_add_inline_script('cpf-artwork-wizard', $this->javascript());
    }

    public function render_page(): void
    {
        if (!current_user_can('manage_woocommerce')) {
            wp_die('You do not have permission to create products.');
        }

        $catalog = $this->request('GET', '/catalog');
        $product = $catalog['products'][0] ?? [];
        $sizes = is_array($product['sizes'] ?? null) ? $product['sizes'] : [];
        $styles = is_array($product['styles'] ?? null) ? $product['styles'] : [];
        $error = (string) ($catalog['error'] ?? '');
        $created = isset($_GET['created']) ? absint($_GET['created']) : 0;
        ?>
        <div class="wrap cpf-wizard">
            <div class="notice notice-info"><p><strong>Recommended:</strong> Build products in <a href="https://www.canvasprintscalgary.com/customer/product-studio" target="_blank" rel="noopener">Canvas Product Studio</a>, then send the complete draft to WooCommerce. This local wizard remains available as a fallback.</p></div>
            <div class="cpf-wizard__heading">
                <div>
                    <span class="cpf-eyebrow">CANVAS PRINTS DROPSHIPPING</span>
                    <h1>Add Canvas Artwork</h1>
                    <p>Upload the production file once. We will create a hidden WooCommerce product, automatic canvas mockups, size variations, and retail prices.</p>
                </div>
                <a class="button" href="<?php echo esc_url(admin_url('admin.php?page=canvas-printing-fulfillment')); ?>">Connection settings</a>
            </div>

            <?php if ($created): ?>
                <div class="notice notice-success is-dismissible"><p>Canvas artwork created as a draft. <a href="<?php echo esc_url(get_edit_post_link($created)); ?>">Review and publish the product</a>.</p></div>
            <?php endif; ?>

            <?php if ($error !== ''): ?>
                <div class="notice notice-error"><p><?php echo esc_html($error); ?> Check the API key under Canvas Fulfillment settings.</p></div>
            <?php elseif ($sizes === []): ?>
                <div class="notice notice-error"><p>The live Canvas catalog did not return any sizes.</p></div>
            <?php else: ?>
                <form class="cpf-builder" method="post" action="<?php echo esc_url(admin_url('admin-post.php')); ?>">
                    <input type="hidden" name="action" value="cpf_create_artwork">
                    <input type="hidden" id="cpf_artwork_attachment" name="artwork_attachment" value="">
                    <?php wp_nonce_field('cpf_create_artwork'); ?>

                    <section class="cpf-panel">
                        <span class="cpf-step">1</span>
                        <div>
                            <h2>Artwork</h2>
                            <p>Use the original JPG, PNG, or WebP production file. It remains separate from the generated storefront mockups.</p>
                            <button type="button" class="button button-primary" id="cpf_choose_artwork">Choose production artwork</button>
                            <div id="cpf_artwork_preview" class="cpf-artwork-preview" hidden>
                                <img src="" alt="Selected artwork">
                                <div><strong id="cpf_artwork_name"></strong><span id="cpf_artwork_dimensions"></span><button type="button" class="button-link" id="cpf_change_artwork">Change</button></div>
                            </div>
                        </div>
                    </section>

                    <section class="cpf-panel">
                        <span class="cpf-step">2</span>
                        <div class="cpf-fields">
                            <div>
                                <h2>Storefront details</h2>
                                <label>Artwork title<input type="text" name="title" required maxlength="180" placeholder="Mountain Sunset"></label>
                                <label>Artist or collection <input type="text" name="artist" maxlength="180" placeholder="Optional"></label>
                                <label>Description<textarea name="description" rows="4" placeholder="Tell customers about this artwork and where it belongs."></textarea></label>
                            </div>
                            <div class="cpf-mockup-explainer">
                                <strong>Three previews created automatically</strong>
                                <span>Clean gallery wall</span>
                                <span>Canvas close-up</span>
                                <span>Styled room scene</span>
                                <small>You can replace or rearrange them in WooCommerce before publishing.</small>
                            </div>
                        </div>
                    </section>

                    <section class="cpf-panel">
                        <span class="cpf-step">3</span>
                        <div>
                            <h2>Canvas styles</h2>
                            <p>Choose what shoppers can order. Each style becomes a WooCommerce variation.</p>
                            <div class="cpf-style-grid">
                                <?php foreach ($styles as $index => $style): ?>
                                    <label class="cpf-choice">
                                        <input type="checkbox" name="styles[]" value="<?php echo esc_attr((string) $style['id']); ?>" data-multiplier="<?php echo esc_attr((string) ($style['price_multiplier'] ?? 1)); ?>" <?php checked($index === 0); ?>>
                                        <strong><?php echo esc_html((string) $style['name']); ?></strong>
                                        <span><?php echo esc_html((string) $style['description']); ?></span>
                                    </label>
                                <?php endforeach; ?>
                            </div>
                        </div>
                    </section>

                    <section class="cpf-panel">
                        <span class="cpf-step">4</span>
                        <div>
                            <div class="cpf-pricing-heading">
                                <div><h2>Sizes and retail pricing</h2><p>Select sizes that suit the artwork. Canvas cost comes from your live Canvas Prints account.</p></div>
                                <label class="cpf-markup">Retail markup <span><input id="cpf_markup" type="number" name="markup" min="0" max="1000" step="5" value="100">%</span></label>
                            </div>
                            <div class="cpf-size-tools">
                                <button type="button" class="button" id="cpf_select_popular">Select popular sizes</button>
                                <button type="button" class="button-link" id="cpf_clear_sizes">Clear</button>
                            </div>
                            <div class="cpf-size-table-wrap">
                                <table class="widefat striped cpf-size-table">
                                    <thead><tr><th></th><th>Size</th><th>Artwork fit</th><th>Shape</th><th>Your Canvas cost</th><th>Suggested retail</th></tr></thead>
                                    <tbody>
                                    <?php foreach ($sizes as $size): ?>
                                        <?php $id = (string) $size['id']; $popular = in_array($id, ['8x10', '12x16', '16x20', '18x24', '20x30', '24x36', '30x40'], true); ?>
                                        <tr data-width="<?php echo esc_attr((string) $size['width']); ?>" data-height="<?php echo esc_attr((string) $size['height']); ?>">
                                            <td><input type="checkbox" name="sizes[]" value="<?php echo esc_attr($id); ?>" data-cost="<?php echo esc_attr((string) $size['merchant_cost']); ?>" data-popular="<?php echo $popular ? '1' : '0'; ?>"></td>
                                            <td><strong><?php echo esc_html(str_replace('x', ' × ', $id)); ?> in</strong></td>
                                            <td class="cpf-fit">Choose artwork</td>
                                            <td><?php echo esc_html((string) ($size['ratio_label'] ?? $size['ratio'] ?? '')); ?></td>
                                            <td>CAD <?php echo esc_html(number_format((float) $size['merchant_cost'], 2)); ?></td>
                                            <td class="cpf-retail">—</td>
                                        </tr>
                                    <?php endforeach; ?>
                                    </tbody>
                                </table>
                            </div>
                            <p class="description">Retail prices are created automatically and can be changed per variation before publishing. Tax is handled by the seller's WooCommerce settings.</p>
                        </div>
                    </section>

                    <div class="cpf-submit-bar">
                        <div><strong>Safe first step:</strong> the product is created as a draft and is not visible to shoppers.</div>
                        <button type="submit" class="button button-primary button-hero">Create draft canvas product</button>
                    </div>
                </form>
            <?php endif; ?>
        </div>
        <?php
    }

    public function create_artwork(): void
    {
        if (!current_user_can('manage_woocommerce')) {
            wp_die('You do not have permission to create products.');
        }
        check_admin_referer('cpf_create_artwork');

        try {
            $attachmentId = absint($_POST['artwork_attachment'] ?? 0);
            $title = sanitize_text_field(wp_unslash($_POST['title'] ?? ''));
            $artist = sanitize_text_field(wp_unslash($_POST['artist'] ?? ''));
            $description = wp_kses_post(wp_unslash($_POST['description'] ?? ''));
            $selectedSizes = array_values(array_unique(array_map('sanitize_text_field', (array) ($_POST['sizes'] ?? []))));
            $selectedStyles = array_values(array_unique(array_map('sanitize_text_field', (array) ($_POST['styles'] ?? []))));
            $markup = min(1000.0, max(0.0, (float) ($_POST['markup'] ?? 100)));

            if ($title === '' || $attachmentId < 1 || !wp_attachment_is_image($attachmentId)) {
                throw new RuntimeException('Choose an artwork image and enter its title.');
            }
            if ($selectedSizes === [] || $selectedStyles === []) {
                throw new RuntimeException('Choose at least one canvas size and one canvas style.');
            }

            $catalog = $this->request('GET', '/catalog');
            if (!empty($catalog['error'])) {
                throw new RuntimeException((string) $catalog['error']);
            }
            $catalogProduct = $catalog['products'][0] ?? [];
            $sizes = array_column((array) ($catalogProduct['sizes'] ?? []), null, 'id');
            $styles = array_column((array) ($catalogProduct['styles'] ?? []), null, 'id');
            $selectedSizes = array_values(array_filter($selectedSizes, static fn (string $id): bool => isset($sizes[$id])));
            $selectedStyles = array_values(array_filter($selectedStyles, static fn (string $id): bool => isset($styles[$id])));
            if ($selectedSizes === [] || $selectedStyles === []) {
                throw new RuntimeException('The selected options are no longer available in the Canvas catalog.');
            }

            $productId = $this->build_product($title, $artist, $description, $attachmentId, $selectedSizes, $selectedStyles, $sizes, $styles, $markup);
            wp_safe_redirect(add_query_arg(['page' => self::PAGE_SLUG, 'created' => $productId], admin_url('admin.php')));
            exit;
        } catch (Throwable $e) {
            wp_die(esc_html($e->getMessage()), 'Could not create Canvas artwork', ['back_link' => true]);
        }
    }

    public function build_product(string $title, string $artist, string $description, int $attachmentId, array $selectedSizes, array $selectedStyles, array $sizes, array $styles, float $markup): int
    {
        $artworkUrl = (string) wp_get_attachment_url($attachmentId);
        if ($artworkUrl === '') {
            throw new RuntimeException('The production artwork URL is unavailable.');
        }
        $imageMeta = wp_get_attachment_metadata($attachmentId);
        $imageWidth = (int) ($imageMeta['width'] ?? 0);
        $imageHeight = (int) ($imageMeta['height'] ?? 0);
        $tooSmall = [];
        foreach ($selectedSizes as $sizeId) {
            $printWidth = (int) ($sizes[$sizeId]['width'] ?? 0) * 150;
            $printHeight = (int) ($sizes[$sizeId]['height'] ?? 0) * 150;
            $fits = ($imageWidth >= $printWidth && $imageHeight >= $printHeight)
                || ($imageWidth >= $printHeight && $imageHeight >= $printWidth);
            if (!$fits) {
                $tooSmall[] = $sizeId;
            }
        }
        if ($imageWidth < 1 || $imageHeight < 1 || $tooSmall !== []) {
            throw new RuntimeException('The artwork is not large enough at 150 PPI for: ' . implode(', ', $tooSmall ?: $selectedSizes) . '. Choose smaller sizes or upload a larger production file.');
        }

        $product = new WC_Product_Variable();
        $product->set_name($title);
        $product->set_status('draft');
        $product->set_catalog_visibility('visible');
        $product->set_description($description !== '' ? $description : sprintf('%s is available as a made-to-order canvas print.', esc_html($title)));
        if ($artist !== '') {
            $product->set_short_description('Artwork by ' . esc_html($artist) . '. Printed to order on premium canvas.');
        }
        $product->set_sku($this->unique_sku($title));
        $product->update_meta_data('_cpf_enabled', 'yes');
        $product->update_meta_data('_cpf_image_mode', 'merchant_artwork');
        $product->update_meta_data('_cpf_allowed_sizes', implode(',', $selectedSizes));
        $product->update_meta_data('_cpf_default_size', $selectedSizes[0]);
        $product->update_meta_data('_cpf_artwork_url', $artworkUrl);
        $product->update_meta_data('_cpf_artwork_attachment_id', $attachmentId);
        $product->update_meta_data('_cpf_markup_percent', $markup);

        $sizeAttribute = new WC_Product_Attribute();
        $sizeAttribute->set_id(0);
        $sizeAttribute->set_name('Canvas size');
        $sizeAttribute->set_options($selectedSizes);
        $sizeAttribute->set_position(0);
        $sizeAttribute->set_visible(true);
        $sizeAttribute->set_variation(true);

        $styleLabels = [];
        foreach ($selectedStyles as $styleId) {
            $styleLabels[] = (string) ($styles[$styleId]['name'] ?? $styleId);
        }
        $styleAttribute = new WC_Product_Attribute();
        $styleAttribute->set_id(0);
        $styleAttribute->set_name('Canvas style');
        $styleAttribute->set_options($styleLabels);
        $styleAttribute->set_position(1);
        $styleAttribute->set_visible(true);
        $styleAttribute->set_variation(true);
        $product->set_attributes([$sizeAttribute, $styleAttribute]);
        $productId = $product->save();

        foreach ($selectedSizes as $sizeId) {
            foreach ($selectedStyles as $styleId) {
                $cost = round((float) $sizes[$sizeId]['merchant_cost'] * (float) ($styles[$styleId]['price_multiplier'] ?? 1), 2);
                $retail = max($cost, round($cost * (1 + $markup / 100), 2));
                $variation = new WC_Product_Variation();
                $variation->set_parent_id($productId);
                $variation->set_status('publish');
                $variation->set_regular_price((string) $retail);
                $variation->set_price((string) $retail);
                $variation->set_manage_stock(false);
                $variation->set_stock_status('instock');
                $variation->set_attributes([
                    'canvas-size' => $sizeId,
                    'canvas-style' => (string) ($styles[$styleId]['name'] ?? $styleId),
                ]);
                $variation->update_meta_data('_cpf_size', $sizeId);
                $variation->update_meta_data('_cpf_style', $styleId);
                $variation->update_meta_data('_cpf_merchant_cost', $cost);
                $variation->update_meta_data('_cpf_markup_percent', $markup);
                $variation->save();
            }
        }

        $mockups = $this->generate_mockups($attachmentId, $title, $productId);
        if ($mockups !== []) {
            $product = wc_get_product($productId);
            $product->set_image_id($mockups[0]);
            $product->set_gallery_image_ids(array_slice($mockups, 1));
            $product->save();
        } else {
            set_post_thumbnail($productId, $attachmentId);
        }

        wc_delete_product_transients($productId);
        return $productId;
    }

    private function generate_mockups(int $attachmentId, string $title, int $productId): array
    {
        if (!extension_loaded('gd')) {
            return [];
        }
        $sourcePath = get_attached_file($attachmentId);
        $mime = (string) get_post_mime_type($attachmentId);
        if (!is_string($sourcePath) || !is_readable($sourcePath)) {
            return [];
        }
        $source = match ($mime) {
            'image/jpeg' => @imagecreatefromjpeg($sourcePath),
            'image/png' => @imagecreatefrompng($sourcePath),
            'image/webp' => function_exists('imagecreatefromwebp') ? @imagecreatefromwebp($sourcePath) : false,
            default => false,
        };
        if (!$source) {
            return [];
        }

        $ids = [];
        $templates = [
            'warm-living-room' => ['file' => 'warm-living-room.png', 'x' => 475, 'y' => 90, 'w' => 610, 'h' => 550],
            'dark-gallery' => ['file' => 'dark-gallery.png', 'x' => 430, 'y' => 145, 'w' => 680, 'h' => 570],
            'calm-bedroom' => ['file' => 'calm-bedroom.png', 'x' => 455, 'y' => 70, 'w' => 650, 'h' => 550],
        ];
        foreach ($templates as $scene => $template) {
            $templatePath = dirname(__DIR__) . '/assets/mockups/' . $template['file'];
            $canvas = is_readable($templatePath) ? @imagecreatefrompng($templatePath) : false;
            if (!$canvas) {
                continue;
            }
            imagealphablending($canvas, true);
            imageantialias($canvas, true);
            $this->place_art($canvas, $source, $template['x'], $template['y'], $template['w'], $template['h'], 20, false);
            $uploads = wp_upload_dir();
            $filename = wp_unique_filename($uploads['path'], sanitize_title($title) . '-' . $scene . '.jpg');
            $path = trailingslashit($uploads['path']) . $filename;
            imagejpeg($canvas, $path, 91);
            imagedestroy($canvas);
            $attachment = [
                'post_mime_type' => 'image/jpeg',
                'post_title' => $title . ' – ' . ucwords(str_replace('-', ' ', $scene)),
                'post_status' => 'inherit',
                'post_parent' => $productId,
            ];
            $id = wp_insert_attachment($attachment, $path, $productId);
            if (!is_wp_error($id)) {
                require_once ABSPATH . 'wp-admin/includes/image.php';
                wp_update_attachment_metadata($id, wp_generate_attachment_metadata($id, $path));
                update_post_meta($id, '_cpf_generated_mockup', 'yes');
                $ids[] = (int) $id;
            }
        }
        imagedestroy($source);
        return $ids;
    }

    private function place_art($canvas, $source, int $x, int $y, int $maxW, int $maxH, int $shadow, bool $detail): void
    {
        $sw = imagesx($source); $sh = imagesy($source);
        $scale = min($maxW / max(1, $sw), $maxH / max(1, $sh));
        $dw = max(1, (int) round($sw * $scale)); $dh = max(1, (int) round($sh * $scale));
        $x += (int) (($maxW - $dw) / 2); $y += (int) (($maxH - $dh) / 2);
        $shadowColor = imagecolorallocatealpha($canvas, 0, 0, 0, 85);
        for ($i = $shadow; $i > 0; $i -= 4) {
            imagefilledrectangle($canvas, $x + $i, $y + $i, $x + $dw + $i, $y + $dh + $i, $shadowColor);
        }
        $edge = imagecolorallocate($canvas, 69, 70, 68);
        imagefilledrectangle($canvas, $x - 12, $y - 12, $x + $dw + 15, $y + $dh + 15, $edge);
        imagecopyresampled($canvas, $source, $x, $y, 0, 0, $dw, $dh, $sw, $sh);
        if ($detail) {
            $highlight = imagecolorallocatealpha($canvas, 255, 255, 255, 100);
            imagefilledrectangle($canvas, $x, $y, $x + 8, $y + $dh, $highlight);
        }
    }

    private function unique_sku(string $title): string
    {
        $base = 'ART-' . strtoupper(substr(preg_replace('/[^A-Za-z0-9]+/', '-', $title), 0, 28));
        $sku = trim($base, '-');
        $candidate = $sku;
        $index = 2;
        while (wc_get_product_id_by_sku($candidate)) {
            $candidate = $sku . '-' . $index++;
        }
        return $candidate;
    }

    private function request(string $method, string $path): array
    {
        $api = rtrim((string) get_option('cpf_api_url', 'https://www.canvasprintscalgary.com/api/partner/v1'), '/');
        $response = wp_remote_request($api . $path, [
            'method' => $method,
            'timeout' => 45,
            'headers' => [
                'Content-Type' => 'application/json',
                'X-Canvas-Api-Key' => (string) get_option('cpf_api_key', ''),
                'X-Canvas-Store-Url' => home_url('/'),
            ],
        ]);
        if (is_wp_error($response)) {
            return ['error' => $response->get_error_message()];
        }
        $decoded = json_decode((string) wp_remote_retrieve_body($response), true);
        if (!is_array($decoded)) {
            return ['error' => 'Canvas returned an invalid response.'];
        }
        if (wp_remote_retrieve_response_code($response) >= 400) {
            return ['error' => (string) ($decoded['error'] ?? 'Canvas connection failed.')];
        }
        return $decoded;
    }

    private function css(): string
    {
        return <<<'CSS'
.cpf-wizard{max-width:1180px}.cpf-wizard__heading{display:flex;justify-content:space-between;align-items:flex-start;gap:24px;margin:28px 0}.cpf-wizard__heading h1{font-size:34px;margin:5px 0}.cpf-wizard__heading p{font-size:16px;max-width:780px;color:#536273}.cpf-eyebrow{font-size:12px;font-weight:800;letter-spacing:.16em;color:#087f73}.cpf-builder{display:grid;gap:18px}.cpf-panel{display:grid;grid-template-columns:46px 1fr;gap:18px;background:#fff;border:1px solid #d8e0e8;border-radius:14px;padding:24px;box-shadow:0 8px 24px rgba(25,43,60,.05)}.cpf-panel h2{margin:0 0 6px;font-size:21px}.cpf-panel p{color:#5f6f7f}.cpf-step{display:flex;width:36px;height:36px;border-radius:50%;align-items:center;justify-content:center;background:#11375e;color:#fff;font-weight:800}.cpf-fields{display:grid;grid-template-columns:1.4fr .8fr;gap:28px}.cpf-fields label{display:grid;gap:6px;margin:14px 0;font-weight:600}.cpf-fields input,.cpf-fields textarea{width:100%}.cpf-mockup-explainer{display:grid;align-content:start;gap:9px;border-radius:12px;padding:20px;background:#eefaf7;border:1px solid #bde7df}.cpf-mockup-explainer span:before{content:'✓';color:#078b78;font-weight:800;margin-right:8px}.cpf-mockup-explainer small{margin-top:8px;color:#586b6a}.cpf-artwork-preview{display:flex;align-items:center;gap:15px;margin-top:16px}.cpf-artwork-preview img{width:120px;height:100px;object-fit:cover;border-radius:8px}.cpf-artwork-preview div{display:grid;gap:4px}.cpf-style-grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:12px}.cpf-choice{display:grid;gap:6px;border:1px solid #d7e0e8;border-radius:10px;padding:16px;cursor:pointer}.cpf-choice:has(input:checked){border-color:#0b8f7e;background:#effbf8;box-shadow:inset 0 0 0 1px #0b8f7e}.cpf-choice input{position:absolute;opacity:0}.cpf-choice span{color:#5d6a76}.cpf-pricing-heading{display:flex;justify-content:space-between;gap:20px;align-items:start}.cpf-markup{display:grid;gap:6px;font-weight:700}.cpf-markup span{display:flex;align-items:center;gap:5px}.cpf-markup input{width:100px}.cpf-size-tools{display:flex;gap:14px;align-items:center;margin:16px 0}.cpf-size-table-wrap{max-height:480px;overflow:auto;border:1px solid #d8e0e8}.cpf-size-table th{position:sticky;top:0;background:#f5f7f9;z-index:1}.cpf-retail{font-weight:800;color:#087f73}.cpf-fit{font-weight:700;color:#6f7c88}.cpf-fit.is-good{color:#07856f}.cpf-fit.is-crop{color:#9a6400}.cpf-fit.is-small{color:#c52a36}.cpf-submit-bar{position:sticky;bottom:12px;z-index:4;display:flex;justify-content:space-between;align-items:center;gap:20px;padding:18px 22px;border-radius:12px;background:#112f50;color:#fff;box-shadow:0 12px 32px rgba(15,37,59,.25)}@media(max-width:780px){.cpf-fields,.cpf-style-grid{grid-template-columns:1fr}.cpf-panel{grid-template-columns:1fr}.cpf-wizard__heading,.cpf-pricing-heading,.cpf-submit-bar{display:grid}.cpf-size-table-wrap{overflow:auto}.cpf-submit-bar{position:static}}
CSS;
    }

    private function javascript(): string
    {
        return <<<'JS'
(function($){
    var frame, artworkRatio=0, artworkWidth=0, artworkHeight=0;
    function updateFit(){
        $('.cpf-size-table tbody tr').each(function(){
            var row=$(this),box=row.find('input[name="sizes[]"]'),w=parseFloat(row.data('width')),h=parseFloat(row.data('height')),target=Math.max(w,h)/Math.min(w,h),fit=row.find('.cpf-fit');
            if(!artworkRatio){box.prop('disabled',false);fit.text('Choose artwork').removeClass('is-good is-crop is-small');return;}
            var minW=w*150,minH=h*150,fits=(artworkWidth>=minW&&artworkHeight>=minH)||(artworkWidth>=minH&&artworkHeight>=minW);
            if(!fits){box.prop('checked',false).prop('disabled',true);fit.text('File too small').addClass('is-small').removeClass('is-good is-crop');return;}
            box.prop('disabled',false);
            if(Math.abs(target-artworkRatio)<=0.04){fit.text('Excellent fit').addClass('is-good').removeClass('is-crop is-small');}
            else{fit.text('Cropping needed').addClass('is-crop').removeClass('is-good is-small');}
        });
    }
    function chooseArtwork(){
        if(frame){frame.open();return;}
        frame=wp.media({title:'Choose production artwork',button:{text:'Use this artwork'},multiple:false,library:{type:'image'}});
        frame.on('select',function(){
            var item=frame.state().get('selection').first().toJSON();
            $('#cpf_artwork_attachment').val(item.id);
            $('#cpf_artwork_preview img').attr('src',(item.sizes&&item.sizes.medium?item.sizes.medium.url:item.url));
            $('#cpf_artwork_name').text(item.filename||item.title);
            $('#cpf_artwork_dimensions').text((item.width||'?')+' × '+(item.height||'?')+' px');
            artworkRatio=Math.max(item.width||1,item.height||1)/Math.max(1,Math.min(item.width||1,item.height||1));
            artworkWidth=parseInt(item.width||0,10); artworkHeight=parseInt(item.height||0,10);
            updateFit();
            $('#cpf_artwork_preview').prop('hidden',false);
            $('#cpf_choose_artwork').hide();
        });
        frame.open();
    }
    function updatePrices(){
        var markup=parseFloat($('#cpf_markup').val()||'0');
        var multipliers=$('input[name="styles[]"]:checked').map(function(){return parseFloat($(this).data('multiplier')||1);}).get();
        $('.cpf-size-table tbody tr').each(function(){
            var box=$(this).find('input[name="sizes[]"]'),cell=$(this).find('.cpf-retail');
            if(!box.prop('checked')||!multipliers.length){cell.text('—');return;}
            var base=parseFloat(box.data('cost')||0),prices=multipliers.map(function(mult){return base*mult*(1+markup/100);});
            var min=Math.min.apply(Math,prices),max=Math.max.apply(Math,prices);
            cell.text('CAD '+min.toFixed(2)+(max>min?'–'+max.toFixed(2):''));
        });
    }
    $(document).on('click','#cpf_choose_artwork,#cpf_change_artwork',chooseArtwork);
    $(document).on('change input','#cpf_markup,input[name="sizes[]"],input[name="styles[]"]',updatePrices);
    $(document).on('click','#cpf_select_popular',function(){
        var popular=$('input[name="sizes[]"][data-popular="1"]');
        if(artworkRatio){popular=popular.filter(function(){return $(this).closest('tr').find('.cpf-fit').hasClass('is-good');});}
        popular.prop('checked',true); updatePrices();
    });
    $(document).on('click','#cpf_clear_sizes',function(){ $('input[name="sizes[]"]').prop('checked',false); updatePrices(); });
    $(document).on('submit','.cpf-builder',function(e){
        if(!$('#cpf_artwork_attachment').val()||!$('input[name="sizes[]"]:checked').length||!$('input[name="styles[]"]:checked').length){e.preventDefault();alert('Choose artwork, at least one size, and at least one canvas style.');}
    });
})(jQuery);
JS;
    }
}
