<?php
/**
 * Export Controller
 * Handles CSV and XLSX exports
 */

namespace VariationHub\API;

defined('ABSPATH') || exit;

class Export_Controller extends \WP_REST_Controller {
    
    protected $namespace = 'variation-hub/v1';
    protected $rest_base = 'export';
    
    /**
     * Register routes
     */
    public function register_routes() {
        // POST /export/csv - Export variations to CSV
        register_rest_route($this->namespace, '/' . $this->rest_base . '/csv', [
            [
                'methods'             => \WP_REST_Server::CREATABLE,
                'callback'            => [$this, 'export_csv'],
                'permission_callback' => [$this, 'get_items_permissions_check'],
                'args'                => $this->get_export_args(),
            ],
        ]);
        
        // POST /export/xlsx - Export variations to XLSX
        register_rest_route($this->namespace, '/' . $this->rest_base . '/xlsx', [
            [
                'methods'             => \WP_REST_Server::CREATABLE,
                'callback'            => [$this, 'export_xlsx'],
                'permission_callback' => [$this, 'get_items_permissions_check'],
                'args'                => $this->get_export_args(),
            ],
        ]);
    }
    
    /**
     * Export variations to CSV
     *
     * @param \WP_REST_Request $request Full request object.
     * @return \WP_REST_Response|\WP_Error
     */
    public function export_csv($request) {
        $params = $request->get_params();
        $variation_ids = isset($params['variation_ids']) ? array_map('intval', $params['variation_ids']) : [];
        $export_all = isset($params['export_all']) && $params['export_all'];
        
        // Get variations
        $variations = $this->get_variations_data($variation_ids, $export_all);
        
        if (empty($variations)) {
            return new \WP_Error(
                'no_variations',
                __('No variations to export', 'variation-hub'),
                ['status' => 400]
            );
        }
        
        // Generate CSV
        $csv_content = $this->generate_csv($variations);
        
        // Return base64 encoded CSV (frontend will decode and download)
        return rest_ensure_response([
            'success' => true,
            'data' => [
                'content' => base64_encode($csv_content),
                'filename' => 'variations_export_' . gmdate('Y-m-d_H-i-s') . '.csv',
                'count' => count($variations),
            ],
        ]);
    }
    
    /**
     * Export variations to XLSX
     *
     * @param \WP_REST_Request $request Full request object.
     * @return \WP_REST_Response|\WP_Error
     */
    public function export_xlsx($request) {
        $params = $request->get_params();
        $variation_ids = isset($params['variation_ids']) ? array_map('intval', $params['variation_ids']) : [];
        $export_all = isset($params['export_all']) && $params['export_all'];
        
        // Get variations
        $variations = $this->get_variations_data($variation_ids, $export_all);
        
        if (empty($variations)) {
            return new \WP_Error(
                'no_variations',
                __('No variations to export', 'variation-hub'),
                ['status' => 400]
            );
        }
        
        // Generate XLSX (using PhpSpreadsheet if available, otherwise fallback to CSV)
        if (class_exists('PhpOffice\PhpSpreadsheet\Spreadsheet')) {
            $xlsx_content = $this->generate_xlsx($variations);
            $extension = 'xlsx';
        } else {
            // Fallback to CSV if PhpSpreadsheet not available
            $xlsx_content = $this->generate_csv($variations);
            $extension = 'csv';
        }
        
        return rest_ensure_response([
            'success' => true,
            'data' => [
                'content' => base64_encode($xlsx_content),
                'filename' => 'variations_export_' . gmdate('Y-m-d_H-i-s') . '.' . $extension,
                'count' => count($variations),
            ],
        ]);
    }
    
    /**
     * Get variations data for export
     *
     * ✅ HIGH-04 FIX: Use WP_Query instead of wc_get_products for better performance
     *
     * @param array $variation_ids Variation IDs (empty = all)
     * @param bool $export_all Export all variations
     * @return array
     */
    protected function get_variations_data($variation_ids, $export_all) {
        // ✅ HIGH-04: Direct WP_Query for performance (no WooCommerce overhead)
        $query_args = [
            'post_type' => 'product_variation',
            'post_status' => 'publish',
            'posts_per_page' => $export_all ? -1 : count($variation_ids),
            'orderby' => 'ID',
            'order' => 'ASC',
            'fields' => 'ids', // Only get IDs first (faster)
        ];
        
        if (!$export_all && !empty($variation_ids)) {
            $query_args['post__in'] = $variation_ids;
        }
        
        $query = new \WP_Query($query_args);
        $variation_ids_result = $query->posts;
        
        // Now load WC_Product objects only for found IDs
        $variations = [];
        
        foreach ($variation_ids_result as $variation_id) {
            $variation = wc_get_product($variation_id);
            
            if (!$variation || !$variation->is_type('variation')) {
                continue;
            }
            
            $parent = wc_get_product($variation->get_parent_id());
            
            // Get all attributes
            $attributes = [];
            foreach ($variation->get_attributes() as $key => $value) {
                $attributes[$key] = $value;
            }
            
            $variations[] = [
                'id' => $variation->get_id(),
                'parent_id' => $variation->get_parent_id(),
                'parent_name' => $parent ? $parent->get_name() : '',
                'sku' => $variation->get_sku(),
                'regular_price' => $variation->get_regular_price(),
                'sale_price' => $variation->get_sale_price(),
                'price' => $variation->get_price(),
                'stock_quantity' => $variation->get_stock_quantity(),
                'stock_status' => $variation->get_stock_status(),
                'manage_stock' => $variation->get_manage_stock() ? 'yes' : 'no',
                'weight' => $variation->get_weight(),
                'length' => $variation->get_length(),
                'width' => $variation->get_width(),
                'height' => $variation->get_height(),
                'tax_class' => $variation->get_tax_class(),
                'image_id' => $variation->get_image_id(),
                'attributes' => $attributes,
                'status' => $variation->get_status(),
            ];
        }
        
        return $variations;
    }
    
    /**
     * Generate CSV content
     *
     * @param array $variations Variations data
     * @return string
     */
    protected function generate_csv($variations) {
        if (empty($variations)) {
            return '';
        }
        
        // Get all unique attribute keys
        $attribute_keys = [];
        foreach ($variations as $variation) {
            foreach ($variation['attributes'] as $key => $value) {
                if (!in_array($key, $attribute_keys)) {
                    $attribute_keys[] = $key;
                }
            }
        }
        
        // CSV headers
        $headers = [
            'ID',
            'Parent ID',
            'Parent Name',
            'SKU',
            'Regular Price',
            'Sale Price',
            'Price',
            'Stock Quantity',
            'Stock Status',
            'Manage Stock',
            'Weight',
            'Length',
            'Width',
            'Height',
            'Tax Class',
            'Image ID',
            'Status',
        ];
        
        // Add attribute columns
        foreach ($attribute_keys as $key) {
            $headers[] = ucfirst(str_replace(['attribute_', 'pa_', '_'], [' ', '', ' '], $key));
        }
        
        // Start CSV (php://temp stream required for CSV generation, WP_Filesystem not applicable)
        // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_fopen -- php://temp stream required for fputcsv()
        $output = fopen('php://temp', 'r+');
        
        // Write BOM for UTF-8
        fprintf($output, chr(0xEF).chr(0xBB).chr(0xBF));
        
        // Write headers
        fputcsv($output, $headers);
        
        // Write data
        foreach ($variations as $variation) {
            $row = [
                $variation['id'],
                $variation['parent_id'],
                $variation['parent_name'],
                $variation['sku'],
                $variation['regular_price'],
                $variation['sale_price'],
                $variation['price'],
                $variation['stock_quantity'],
                $variation['stock_status'],
                $variation['manage_stock'],
                $variation['weight'],
                $variation['length'],
                $variation['width'],
                $variation['height'],
                $variation['tax_class'],
                $variation['image_id'],
                $variation['status'],
            ];
            
            // Add attribute values
            foreach ($attribute_keys as $key) {
                $row[] = isset($variation['attributes'][$key]) ? $variation['attributes'][$key] : '';
            }
            
            fputcsv($output, $row);
        }
        
        rewind($output);
        $csv_content = stream_get_contents($output);
        // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_fclose -- Closing php://temp stream
        fclose($output);
        
        return $csv_content;
    }
    
    /**
     * Generate XLSX content (using PhpSpreadsheet)
     *
     * @param array $variations Variations data
     * @return string
     */
    protected function generate_xlsx($variations) {
        if (!class_exists('PhpOffice\PhpSpreadsheet\Spreadsheet')) {
            return $this->generate_csv($variations);
        }
        
        $spreadsheet = new \PhpOffice\PhpSpreadsheet\Spreadsheet();
        $sheet = $spreadsheet->getActiveSheet();
        $sheet->setTitle('Variations');
        
        // Get attribute keys
        $attribute_keys = [];
        foreach ($variations as $variation) {
            foreach ($variation['attributes'] as $key => $value) {
                if (!in_array($key, $attribute_keys)) {
                    $attribute_keys[] = $key;
                }
            }
        }
        
        // Headers
        $headers = [
            'ID', 'Parent ID', 'Parent Name', 'SKU', 'Regular Price', 'Sale Price',
            'Price', 'Stock Quantity', 'Stock Status', 'Manage Stock', 'Weight',
            'Length', 'Width', 'Height', 'Tax Class', 'Image ID', 'Status'
        ];
        
        foreach ($attribute_keys as $key) {
            $headers[] = ucfirst(str_replace(['attribute_', 'pa_', '_'], [' ', '', ' '], $key));
        }
        
        // Write headers (bold)
        $col = 1;
        foreach ($headers as $header) {
            $cellCoordinate = \PhpOffice\PhpSpreadsheet\Cell\Coordinate::stringFromColumnIndex($col) . '1';
            $sheet->setCellValue($cellCoordinate, $header);
            $sheet->getStyle($cellCoordinate)->getFont()->setBold(true);
            $col++;
        }
        
        // Write data
        $row = 2;
        foreach ($variations as $variation) {
            $col = 1;
            $data = [
                $variation['id'], $variation['parent_id'], $variation['parent_name'],
                $variation['sku'], $variation['regular_price'], $variation['sale_price'],
                $variation['price'], $variation['stock_quantity'], $variation['stock_status'],
                $variation['manage_stock'], $variation['weight'], $variation['length'],
                $variation['width'], $variation['height'], $variation['tax_class'],
                $variation['image_id'], $variation['status']
            ];
            
            foreach ($data as $value) {
                $cellCoordinate = \PhpOffice\PhpSpreadsheet\Cell\Coordinate::stringFromColumnIndex($col) . $row;
                $sheet->setCellValue($cellCoordinate, $value);
                $col++;
            }
            
            // Attributes
            foreach ($attribute_keys as $key) {
                $value = isset($variation['attributes'][$key]) ? $variation['attributes'][$key] : '';
                $cellCoordinate = \PhpOffice\PhpSpreadsheet\Cell\Coordinate::stringFromColumnIndex($col) . $row;
                $sheet->setCellValue($cellCoordinate, $value);
                $col++;
            }
            
            $row++;
        }
        
        // Auto-size columns
        foreach (range(1, count($headers)) as $col) {
            $sheet->getColumnDimensionByColumn($col)->setAutoSize(true);
        }
        
        // Write to string
        $writer = new \PhpOffice\PhpSpreadsheet\Writer\Xlsx($spreadsheet);
        ob_start();
        $writer->save('php://output');
        $xlsx_content = ob_get_clean();
        
        return $xlsx_content;
    }
    
    /**
     * Check permissions
     *
     * @param \WP_REST_Request $request Full request object.
     * @return bool
     */
    public function get_items_permissions_check($request) {
        return current_user_can('manage_woocommerce');
    }
    
    /**
     * Get export args
     *
     * @return array
     */
    protected function get_export_args() {
        return [
            'variation_ids' => [
                'description' => __('Array of variation IDs', 'variation-hub'),
                'type'        => 'array',
                'items'       => ['type' => 'integer'],
                'default'     => [],
            ],
            'export_all' => [
                'description' => __('Export all variations', 'variation-hub'),
                'type'        => 'boolean',
                'default'     => false,
            ],
        ];
    }
}
