<?php

declare(strict_types=1);

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

class KLCNN_Register_Routes
{
  private $namespace = 'klcnn/v1';

  public function __construct()
  {
    add_action('rest_api_init', [$this, 'register_routes']);
  }

  public function register_routes()
  {
    // Connection Routes
    register_rest_route($this->namespace, '/connection', [
      [
        'methods' => 'GET',
        'callback' => ['KLCNN_API_Connection', 'get_connection_endpoint'],
        'permission_callback' => [$this, 'check_permissions'],
      ],
      [
        'methods' => 'POST',
        'callback' => ['KLCNN_API_Connection', 'save_connection_endpoint'],
        'permission_callback' => [$this, 'check_permissions'],
      ],
      [
        'methods' => 'DELETE',
        'callback' => ['KLCNN_API_Connection', 'delete_connection_endpoint'],
        'permission_callback' => [$this, 'check_permissions'],
      ],
    ]);

    register_rest_route($this->namespace, '/connection/secret', [
      'methods' => 'GET',
      'callback' => ['KLCNN_API_Connection', 'get_secret_key_endpoint'],
      'permission_callback' => [$this, 'check_permissions'],
    ]);

    register_rest_route($this->namespace, '/connection/test', [
      'methods' => 'POST',
      'callback' => ['KLCNN_API_Connection', 'test_connection_endpoint'],
      'permission_callback' => [$this, 'check_permissions'],
    ]);

    register_rest_route($this->namespace, '/categories', [
      'methods' => 'POST',
      'callback' => ['KLCNN_API_Connection', 'test_connection_endpoint'],
      'permission_callback' => [$this, 'check_permissions'],
    ]);

    // Get category suggestions
    register_rest_route($this->namespace, '/categories/decide', [
      'methods' => 'POST',
      'callback' => ['KLCNN_Category_Manager', 'get_suggestions'],
      'permission_callback' => [$this, 'check_permissions'],
    ]);

    // Get category attributes
    register_rest_route($this->namespace, '/categories/(?P<id>\d+)/attributes', [
      'methods' => 'GET',
      'callback' => [$this, 'get_category_attributes'],
      'permission_callback' => [$this, 'check_permissions'],
    ]);

    // Search categories
    register_rest_route($this->namespace, '/categories/search', [
      'methods' => 'GET',
      'callback' => [$this, 'search_categories'],
      'permission_callback' => [$this, 'check_permissions'],
    ]);

    // Get products
    register_rest_route($this->namespace, '/products', [
      'methods' => 'GET',
      'callback' => [$this, 'get_products'],
      'permission_callback' => [$this, 'check_permissions'],
      'args' => [
        'page' => [
          'default' => 1,
          'sanitize_callback' => 'absint'
        ],
        'per_page' => [
          'default' => 10,
          'sanitize_callback' => 'absint'
        ],
        'search' => [
          'default' => '',
          'sanitize_callback' => 'sanitize_text_field'
        ]
      ]
    ]);

    // Save product category
    register_rest_route($this->namespace, '/products/(?P<id>\d+)/category', [
      'methods' => 'POST',
      'callback' => [$this, 'save_product_category'],
      'permission_callback' => [$this, 'check_permissions'],
      'args' => [
        'category_id' => [
          'required' => true,
          'type' => 'string',
          'sanitize_callback' => 'sanitize_text_field'
        ],
        'category_name' => [
          'required' => true,
          'type' => 'string',
          'sanitize_callback' => 'sanitize_text_field'
        ],
        'category_title' => [
          'required' => true,
          'type' => 'string',
          'sanitize_callback' => 'sanitize_text_field'
        ]
      ]
    ]);

    // Push product to Kaufland
    register_rest_route($this->namespace, '/products/(?P<id>\d+)/push', [
      'methods' => 'POST',
      'callback' => [$this, 'push_product_to_kaufland'],
      'permission_callback' => [$this, 'check_permissions'],
    ]);

    // Save product EAN
    register_rest_route($this->namespace, '/products/(?P<id>\d+)/ean', [
      'methods' => 'POST',
      'callback' => [$this, 'save_product_ean'],
      'permission_callback' => [$this, 'check_permissions'],
      'args' => [
        'ean' => [
          'required' => true,
          'type' => 'string',
          'validate_callback' => function ($param) {
            // Must be exactly 13 digits with valid checksum
            if (strlen($param) !== 13 || !ctype_digit($param)) {
              return false;
            }

            // Validate EAN-13 checksum
            $sum = 0;
            for ($i = 0; $i < 12; $i++) {
              $sum += intval($param[$i]) * ($i % 2 ? 3 : 1);
            }
            $check = (10 - ($sum % 10)) % 10;

            return $check === intval($param[12]);
          }
        ]
      ]
    ]);

    // Save product manufacturer
    register_rest_route($this->namespace, '/products/(?P<id>\d+)/manufacturer', [
      'methods' => 'POST',
      'callback' => [$this, 'save_product_manufacturer'],
      'permission_callback' => [$this, 'check_permissions'],
      'args' => [
        'manufacturer' => [
          'required' => true,
          'type' => 'string',
          'sanitize_callback' => 'sanitize_text_field'
        ]
      ]
    ]);

    // Get recent manufacturers
    register_rest_route($this->namespace, '/manufacturers/recent', [
      'methods' => 'GET',
      'callback' => [$this, 'get_recent_manufacturers'],
      'permission_callback' => [$this, 'check_permissions']
    ]);

    // Bulk update product categories
    register_rest_route($this->namespace, '/products/bulk-category', [
      'methods' => 'POST',
      'callback' => [$this, 'bulk_update_product_categories'],
      'permission_callback' => [$this, 'check_permissions'],
      'args' => [
        'product_ids' => [
          'required' => true,
          'type' => 'array',
          'items' => [
            'type' => 'integer'
          ]
        ],
        'category_id' => [
          'required' => true,
          'type' => 'string',
          'sanitize_callback' => 'sanitize_text_field'
        ],
        'category_name' => [
          'required' => true,
          'type' => 'string',
          'sanitize_callback' => 'sanitize_text_field'
        ],
        'category_title' => [
          'required' => true,
          'type' => 'string',
          'sanitize_callback' => 'sanitize_text_field'
        ]
      ]
    ]);

    // Save processed images
    register_rest_route(
      $this->namespace,
      '/save-processed-images',
      [
        'methods' => 'POST',
        'callback' => [$this, 'save_processed_images'],
        'permission_callback' => function () {
          return current_user_can('upload_files') && current_user_can('edit_products');
        }
      ]
    );

    // Future routes will be added here
    // Categories routes
    // register_rest_route($this->namespace, '/categories', [...]);
    // register_rest_route($this->namespace, '/categories/sync', [...]);
  }

  public function check_permissions($request): bool
  {
    // First check if user has required capabilities
    if (!current_user_can('manage_woocommerce')) {
      return false;
    }

    // For state-changing operations, verify nonce
    $method = $request->get_method();
    if (in_array($method, ['POST', 'PUT', 'DELETE'])) {
      // Get nonce from header or parameters
      $nonce = $request->get_header('X-WP-Nonce');
      if (empty($nonce)) {
        $nonce = $request->get_param('_wpnonce');
      }

      // If no nonce found or verification fails, deny access
      if (empty($nonce) || !wp_verify_nonce($nonce, 'wp_rest')) {
        return false;
      }
    }

    return true;
  }

  /**
   * Get category attributes from Kaufland
   */
  public function get_category_attributes($request)
  {
    try {
      $category_id = $request['id'];

      // Create a new instance with credentials
      $category_manager = new KLCNN_Category_Manager(
        get_option('klcnn_client_key', ''),
        get_option('klcnn_secret_key', '')
      );

      $attributes = $category_manager->get_category_attributes($category_id);

      return rest_ensure_response([
        'success' => true,
        'data' => $attributes
      ]);
    } catch (Exception $e) {
      return new WP_Error(
        'get_attributes_failed',
        'Failed to get category attributes: ' . esc_html($e->getMessage()),
        ['status' => 500]
      );
    }
  }

  /**
   * Search categories in Kaufland
   */
  public function search_categories($request)
  {
    try {
      $query = $request->get_param('q');
      if (empty($query)) {
        return new WP_Error(
          'invalid_request',
          'Search query parameter is required',
          ['status' => 400]
        );
      }

      // Create a new instance with credentials
      $category_manager = new KLCNN_Category_Manager(
        get_option('klcnn_client_key', ''),
        get_option('klcnn_secret_key', '')
      );

      $categories = $category_manager->search_categories($query);

      return rest_ensure_response([
        'success' => true,
        'data' => $categories
      ]);
    } catch (Exception $e) {
      return new WP_Error(
        'search_failed',
        'Failed to search categories: ' . esc_html($e->getMessage()),
        ['status' => 500]
      );
    }
  }

  public function get_products($request)
  {
    $product_sync = new KLCNN_Product_Sync(
      get_option('klcnn_client_key', ''),
      get_option('klcnn_secret_key', '')
    );

    return $product_sync->get_products(
      $request->get_param('page'),
      $request->get_param('per_page'),
      $request->get_param('search')
    );
  }

  public function save_product_category($request)
  {
    $product_id = $request['id'];
    $category_id = $request->get_param('category_id');
    $category_name = $request->get_param('category_name');
    $category_title = $request->get_param('category_title');

    // Get the product
    $product = wc_get_product($product_id);
    if (!$product) {
      return new WP_Error(
        'product_not_found',
        'Product not found',
        ['status' => 404]
      );
    }

    // Save category data as product meta
    $product->update_meta_data('_klcnn_kaufland_category_id', $category_id);
    $product->update_meta_data('_klcnn_kaufland_category_name', $category_name);
    $product->update_meta_data('_klcnn_kaufland_category_title', $category_title);

    // Save the changes
    $product->save();

    return [
      'success' => true,
      'message' => 'Category updated successfully',
      'data' => [
        'category_id' => $category_id,
        'category_name' => $category_name,
        'category_title' => $category_title
      ]
    ];
  }

  public function push_product_to_kaufland($request)
  {
    try {
      $product_id = $request['id'];

      // Get the product
      $product = wc_get_product($product_id);
      if (!$product) {
        return new WP_Error(
          'product_not_found',
          'Product not found',
          ['status' => 404]
        );
      }

      // Get category data
      $category_id = $product->get_meta('_klcnn_kaufland_category_id');
      $category_name = $product->get_meta('_klcnn_kaufland_category_name');

      if (!$category_id || !$category_name) {
        return new WP_Error(
          'category_not_set',
          'Please set a Kaufland category for this product first',
          ['status' => 400]
        );
      }

      // Check if EAN is set
      $ean = $product->get_meta('_klcnn_ean');
      if (empty($ean)) {
        return new WP_Error(
          'ean_not_set',
          'Please set an EAN for this product first',
          ['status' => 400]
        );
      }

      // Prepare data for Kaufland
      $kaufland_data = [
        'id' => $product_id,
        'name' => $product->get_name(),
        'description' => $product->get_description(),
        'category' => $category_name
      ];

      try {
        // Get API credentials
        $credentials = KLCNN_API_Connection::get_credentials();

        if (empty($credentials['client_key']) || empty($credentials['secret_key'])) {
          return new WP_Error(
            'missing_credentials',
            'Kaufland API credentials are not configured',
            ['status' => 400]
          );
        }

        // Create new product sync instance with credentials
        $product_sync = new KLCNN_Product_Sync(
          $credentials['client_key'],
          $credentials['secret_key']
        );

        // Push the product data
        $response = $product_sync->push_product($kaufland_data);

        // Update product sync status
        $product->update_meta_data('_klcnn_sync_status', 'pending');
        $product->update_meta_data('_klcnn_last_synced', current_time('mysql'));
        $product->save();

        return [
          'success' => true,
          'message' => 'Product pushed to Kaufland successfully',
          'data' => $response
        ];
      } catch (Exception $e) {
        return new WP_Error(
          'push_failed',
          'Failed to push product to Kaufland: ' . $e->getMessage(),
          ['status' => 500]
        );
      }
    } catch (Exception $e) {
      return new WP_Error(
        'internal_error',
        'Internal server error: ' . $e->getMessage(),
        ['status' => 500]
      );
    }
  }

  public function save_product_ean($request)
  {
    $product_id = $request['id'];
    $ean = $request->get_param('ean');

    // Get the product
    $product = wc_get_product($product_id);
    if (!$product) {
      return new WP_Error(
        'product_not_found',
        'Product not found',
        ['status' => 404]
      );
    }

    // Save EAN as product meta
    $product->update_meta_data('_klcnn_ean', $ean);
    $product->save();

    return [
      'success' => true,
      'message' => 'EAN updated successfully',
      'data' => [
        'ean' => $ean
      ]
    ];
  }

  public function save_product_manufacturer($request)
  {
    $product_id = $request['id'];
    $manufacturer = $request->get_param('manufacturer');

    // Get the product
    $product = wc_get_product($product_id);
    if (!$product) {
      return new WP_Error(
        'product_not_found',
        'Product not found',
        ['status' => 404]
      );
    }

    // Save manufacturer as product meta
    $product->update_meta_data('_klcnn_manufacturer', $manufacturer);
    $product->save();

    // Update recent manufacturers list
    $this->update_recent_manufacturers($manufacturer);

    return [
      'success' => true,
      'message' => 'Manufacturer updated successfully',
      'data' => [
        'manufacturer' => $manufacturer
      ]
    ];
  }

  public function get_recent_manufacturers()
  {
    $recent = get_option('klcnn_recent_manufacturers', []);
    return array_values(array_unique($recent));
  }

  private function update_recent_manufacturers($manufacturer)
  {
    $recent = get_option('klcnn_recent_manufacturers', []);

    // Add new manufacturer to the beginning
    array_unshift($recent, $manufacturer);

    // Keep only unique values and limit to 10
    $recent = array_values(array_unique($recent));
    if (count($recent) > 10) {
      $recent = array_slice($recent, 0, 10);
    }

    update_option('klcnn_recent_manufacturers', $recent);
  }

  /**
   * Bulk update product categories
   */
  public function bulk_update_product_categories($request)
  {
    try {
      $product_ids = $request->get_param('product_ids');
      $category_id = $request->get_param('category_id');
      $category_name = $request->get_param('category_name');
      $category_title = $request->get_param('category_title');

      $updated_products = [];
      $failed_products = [];

      foreach ($product_ids as $product_id) {
        try {
          // Get the product
          $product = wc_get_product($product_id);
          if (!$product) {
            $failed_products[] = [
              'id' => $product_id,
              'error' => 'Product not found'
            ];
            continue;
          }

          // Save category data as product meta
          $product->update_meta_data('_klcnn_kaufland_category_id', $category_id);
          $product->update_meta_data('_klcnn_kaufland_category_name', $category_name);
          $product->update_meta_data('_klcnn_kaufland_category_title', $category_title);

          // Save the changes
          $product->save();

          $updated_products[] = [
            'id' => $product_id,
            'name' => $product->get_name(),
            'category_id' => $category_id,
            'category_name' => $category_name,
            'category_title' => $category_title
          ];
        } catch (Exception $e) {
          $failed_products[] = [
            'id' => $product_id,
            'error' => $e->getMessage()
          ];
        }
      }

      return [
        'success' => true,
        'message' => sprintf(
          'Updated %d products, %d failed',
          count($updated_products),
          count($failed_products)
        ),
        'data' => [
          'updated' => $updated_products,
          'failed' => $failed_products
        ]
      ];
    } catch (Exception $e) {
      return new WP_Error(
        'bulk_update_failed',
        'Failed to update products: ' . $e->getMessage(),
        ['status' => 500]
      );
    }
  }

  public function save_processed_images($request)
  {
    try {
      if (!isset($_FILES['images'])) {
        return new WP_Error(
          'no_images',
          'No images were provided',
          ['status' => 400]
        );
      }

      $original_ids = $request->get_param('original_ids');
      if (!$original_ids || !is_array($original_ids)) {
        return new WP_Error(
          'no_original_ids',
          'No original image IDs were provided',
          ['status' => 400]
        );
      }

      $processed_images = [];

      // Define allowed file types - only accept images
      $allowed_file_types = ['image/jpeg', 'image/png', 'image/gif', 'image/webp'];
      $max_file_size = 5 * 1024 * 1024; // 5MB limit

      // WordPress upload directory
      $upload_dir = wp_upload_dir();

      foreach ($_FILES['images']['tmp_name'] as $index => $tmp_name) {
        // Security checks for the uploaded file
        $file_size = $_FILES['images']['size'][$index];
        $file_type = $_FILES['images']['type'][$index];

        // Validate file size
        if ($file_size > $max_file_size) {
          continue; // Skip oversized files
        }

        // Validate file type
        if (!in_array($file_type, $allowed_file_types)) {
          continue; // Skip disallowed file types
        }

        $original_id = isset($original_ids[$index]) ? absint($original_ids[$index]) : 0;
        if (!$original_id) {
          continue;
        }

        // Get original image metadata
        $original_image = get_post($original_id);
        if (!$original_image) {
          continue;
        }

        // Create unique filename
        $filename = 'processed-' . sanitize_file_name(basename($original_image->guid));

        // Use WordPress file handling functions instead of move_uploaded_file
        require_once(ABSPATH . 'wp-admin/includes/file.php');
        $file_array = array(
          'name' => $filename,
          'tmp_name' => $tmp_name,
          'type' => $file_type,
          'error' => 0,
          'size' => $file_size
        );

        // Copy the file to the uploads directory with more secure handling
        $file = wp_handle_sideload($file_array, array('test_form' => false));

        if (isset($file['error'])) {
          continue; // Skip files with errors
        }

        $upload_path = $file['file']; // Full path to the uploaded file

        // Prepare attachment data
        $wp_filetype = wp_check_filetype($filename);
        $attachment = array(
          'post_mime_type' => $wp_filetype['type'],
          'post_title' => sanitize_file_name($filename),
          'post_content' => '',
          'post_status' => 'inherit'
        );

        // Insert attachment into WordPress media library
        $attach_id = wp_insert_attachment($attachment, $upload_path);
        if (is_wp_error($attach_id)) {
          continue; // Skip if attachment creation fails
        }

        // Generate metadata and update attachment
        require_once(ABSPATH . 'wp-admin/includes/image.php');
        $attach_data = wp_generate_attachment_metadata($attach_id, $upload_path);
        wp_update_attachment_metadata($attach_id, $attach_data);

        // Add to processed images array
        $processed_images[] = array(
          'id' => $attach_id,
          'url' => wp_get_attachment_url($attach_id),
          'original_id' => $original_id
        );

        // Update original image meta to track processed version
        update_post_meta($original_id, '_klcnn_processed_image_id', $attach_id);
      }

      if (empty($processed_images)) {
        return new WP_Error(
          'no_valid_images',
          'No valid images were processed',
          ['status' => 400]
        );
      }

      return [
        'success' => true,
        'message' => 'Images processed and saved successfully',
        'images' => $processed_images
      ];
    } catch (Exception $e) {
      return new WP_Error(
        'save_failed',
        'Failed to save processed images: ' . esc_html($e->getMessage()),
        ['status' => 500]
      );
    }
  }
}
