<?php
/**
 * Shopify Connector - Real-time import from Shopify.
 *
 * @package PrimeLink
 */

namespace PrimeLink\Modules\Imports\Connectors;

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

final class ShopifyConnector implements PlatformConnectorInterface {

    /**
     * Get connector name.
     *
     * @return string
     */
    public function get_name() {
        return 'shopify';
    }

    /**
     * Get connector display name.
     *
     * @return string
     */
    public function get_display_name() {
        return 'Shopify';
    }

    /**
     * Get required credentials fields.
     *
     * @return array
     */
    public function get_credentials_fields() {
        return array(
            'shop_domain' => array(
                'label'       => 'Shop Domain',
                'type'        => 'text',
                'placeholder' => 'your-shop.myshopify.com',
                'required'    => true,
                'description' => 'Your Shopify shop domain (without https://)',
            ),
            'api_key' => array(
                'label'       => 'API Key',
                'type'        => 'text',
                'placeholder' => 'Your Shopify API key',
                'required'    => true,
                'description' => 'Private app API key',
            ),
            'api_secret' => array(
                'label'       => 'API Secret',
                'type'        => 'password',
                'placeholder' => 'Your Shopify API secret',
                'required'    => true,
                'description' => 'Private app API secret',
            ),
            'access_token' => array(
                'label'       => 'Access Token',
                'type'        => 'password',
                'placeholder' => 'Your Shopify access token',
                'required'    => true,
                'description' => 'Private app access token',
            ),
        );
    }

    /**
     * Build API URL.
     *
     * @param string $shop_domain Shop domain.
     * @param string $endpoint    API endpoint.
     * @return string
     */
    private function build_api_url( $shop_domain, $endpoint ) {
        $shop_domain = rtrim( $shop_domain, '/' );
        $shop_domain = preg_replace( '/^https?:\/\//', '', $shop_domain );
        return 'https://' . $shop_domain . '/admin/api/2024-01/' . ltrim( $endpoint, '/' );
    }

    /**
     * Make API request.
     *
     * @param string $url         API URL.
     * @param string $access_token Access token.
     * @param string $method      HTTP method.
     * @param array  $data        Request data.
     * @return array
     */
    private function api_request( $url, $access_token, $method = 'GET', $data = array() ) {
        $args = array(
            'headers' => array(
                'X-Shopify-Access-Token' => $access_token,
                'Content-Type'           => 'application/json',
            ),
            'timeout'     => 30,
            'retry'       => 2, // Retry up to 2 times on failure
            'retry_delay' => 1, // 1 second delay between retries
        );

        if ( ! empty( $data ) && in_array( $method, array( 'POST', 'PUT', 'PATCH' ), true ) ) {
            $args['body'] = $data; // HttpHelper will handle JSON encoding
        }

        $response = \PrimeLink\Helpers\HttpHelper::request( $url, $method, $args );

        if ( ! $response['success'] ) {
            return array(
                'success' => false,
                'error'   => $response['error'] ?? 'API request failed',
            );
        }

        $body = $response['body'];
        $code = $response['code'];
        $decoded_data = json_decode( $body, true );

        if ( $code >= 200 && $code < 300 ) {
            return array(
                'success' => true,
                'data'    => $decoded_data,
            );
        }

        return array(
            'success' => false,
            'error'   => isset( $decoded_data['errors'] ) ? wp_json_encode( $decoded_data['errors'] ) : 'API request failed',
            'code'    => $code,
        );
    }

    /**
     * Test connection with platform.
     *
     * @param array $credentials Connection credentials.
     * @return array
     */
    public function test_connection( $credentials ) {
        $shop_domain  = $credentials['shop_domain'] ?? '';
        $access_token = $credentials['access_token'] ?? '';

        if ( empty( $shop_domain ) || empty( $access_token ) ) {
            return array(
                'success' => false,
                'message' => 'Missing required credentials.',
            );
        }

        $url = $this->build_api_url( $shop_domain, 'shop.json' );
        $result = $this->api_request( $url, $access_token );

        if ( $result['success'] ) {
            return array(
                'success' => true,
                'message' => 'Connection successful!',
                'data'    => $result['data']['shop'] ?? array(),
            );
        }

        return array(
            'success' => false,
            'message' => $result['error'] ?? 'Connection failed.',
        );
    }

    /**
     * Fetch products from platform.
     *
     * @param array $credentials Connection credentials.
     * @param array $options     Fetch options.
     * @return array
     */
    public function fetch_products( $credentials, $options = array() ) {
        $shop_domain  = $credentials['shop_domain'] ?? '';
        $access_token = $credentials['access_token'] ?? '';
        $limit        = isset( $options['limit'] ) ? absint( $options['limit'] ) : 250;
        $since_id     = isset( $options['since_id'] ) ? absint( $options['since_id'] ) : 0;

        if ( empty( $shop_domain ) || empty( $access_token ) ) {
            return array(
                'success' => false,
                'error'   => 'Missing required credentials.',
            );
        }

        // Shopify REST API doesn't support 'page' parameter, use 'since_id' for pagination
        $endpoint = 'products.json?limit=' . $limit;
        if ( $since_id > 0 ) {
            $endpoint .= '&since_id=' . $since_id;
        }

        $url = $this->build_api_url( $shop_domain, $endpoint );
        $result = $this->api_request( $url, $access_token );

        if ( ! $result['success'] ) {
            return $result;
        }

        $products = $result['data']['products'] ?? array();
        $total = count( $products );
        $has_more = $total >= $limit;

        return array(
            'success'  => true,
            'data'    => $products,
            'total'   => $total,
            'has_more' => $has_more,
        );
    }

    /**
     * Fetch orders from platform.
     *
     * @param array $credentials Connection credentials.
     * @param array $options     Fetch options.
     * @return array
     */
    public function fetch_orders( $credentials, $options = array() ) {
        $shop_domain  = $credentials['shop_domain'] ?? '';
        $access_token = $credentials['access_token'] ?? '';
        $limit        = isset( $options['limit'] ) ? absint( $options['limit'] ) : 250;
        $since_id     = isset( $options['since_id'] ) ? absint( $options['since_id'] ) : 0;
        $status       = isset( $options['status'] ) ? sanitize_text_field( $options['status'] ) : 'any';

        if ( empty( $shop_domain ) || empty( $access_token ) ) {
            return array(
                'success' => false,
                'error'   => 'Missing required credentials.',
            );
        }

        // Shopify REST API doesn't support 'page' parameter, use 'since_id' for pagination
        $endpoint = 'orders.json?limit=' . $limit;
        if ( $since_id > 0 ) {
            $endpoint .= '&since_id=' . $since_id;
        }
        if ( $status !== 'any' ) {
            $endpoint .= '&status=' . $status;
        }

        $url = $this->build_api_url( $shop_domain, $endpoint );
        $result = $this->api_request( $url, $access_token );

        if ( ! $result['success'] ) {
            return $result;
        }

        $orders = $result['data']['orders'] ?? array();
        $total = count( $orders );
        $has_more = $total >= $limit;

        return array(
            'success'  => true,
            'data'    => $orders,
            'total'   => $total,
            'has_more' => $has_more,
        );
    }

    /**
     * Fetch customers from platform.
     *
     * @param array $credentials Connection credentials.
     * @param array $options     Fetch options.
     * @return array
     */
    public function fetch_customers( $credentials, $options = array() ) {
        $shop_domain  = $credentials['shop_domain'] ?? '';
        $access_token = $credentials['access_token'] ?? '';
        $limit        = isset( $options['limit'] ) ? absint( $options['limit'] ) : 250;
        $since_id     = isset( $options['since_id'] ) ? absint( $options['since_id'] ) : 0;

        if ( empty( $shop_domain ) || empty( $access_token ) ) {
            return array(
                'success' => false,
                'error'   => 'Missing required credentials.',
            );
        }

        // Shopify REST API doesn't support 'page' parameter, use 'since_id' for pagination
        $endpoint = 'customers.json?limit=' . $limit;
        if ( $since_id > 0 ) {
            $endpoint .= '&since_id=' . $since_id;
        }
        $url = $this->build_api_url( $shop_domain, $endpoint );
        $result = $this->api_request( $url, $access_token );

        if ( ! $result['success'] ) {
            return $result;
        }

        $customers = $result['data']['customers'] ?? array();
        $total = count( $customers );
        $has_more = $total >= $limit;

        return array(
            'success'  => true,
            'data'    => $customers,
            'total'   => $total,
            'has_more' => $has_more,
        );
    }

    /**
     * Convert Shopify product to WooCommerce format.
     *
     * @param array  $shopify_product Shopify product data.
     * @param string $type           Data type.
     * @return array
     */
    public function convert_to_woocommerce( $shopify_product, $type = 'product' ) {
        if ( $type !== 'product' ) {
            return array();
        }

        $product = array(
            'post' => array(
                'post_title'   => $shopify_product['title'] ?? '',
                'post_content' => $shopify_product['body_html'] ?? '',
                'post_excerpt' => $shopify_product['body_html'] ?? '',
                'post_status'  => ( $shopify_product['status'] ?? 'active' ) === 'active' ? 'publish' : 'draft',
            ),
            'product' => array(
                'sku'            => $this->get_first_variant_sku( $shopify_product ),
                'regular_price'  => $this->get_first_variant_price( $shopify_product ),
                'stock'          => $this->get_total_inventory( $shopify_product ),
                'stock_status'   => $this->get_stock_status( $shopify_product ),
                'weight'         => $shopify_product['weight'] ?? '',
                'product_type'   => $shopify_product['product_type'] ?? '',
            ),
            'images' => array(
                'images' => $this->extract_images( $shopify_product ),
            ),
            'tax' => array(
                'product_cat' => $this->extract_categories( $shopify_product ),
                'product_tag' => $this->extract_tags( $shopify_product ),
            ),
            'attrs' => $this->extract_attributes( $shopify_product ),
        );

        return $product;
    }

    /**
     * Get first variant SKU.
     *
     * @param array $shopify_product Shopify product.
     * @return string
     */
    private function get_first_variant_sku( $shopify_product ) {
        $variants = $shopify_product['variants'] ?? array();
        return ! empty( $variants[0]['sku'] ) ? $variants[0]['sku'] : '';
    }

    /**
     * Get first variant price.
     *
     * @param array $shopify_product Shopify product.
     * @return string
     */
    private function get_first_variant_price( $shopify_product ) {
        $variants = $shopify_product['variants'] ?? array();
        return ! empty( $variants[0]['price'] ) ? $variants[0]['price'] : '';
    }

    /**
     * Get total inventory.
     *
     * @param array $shopify_product Shopify product.
     * @return int
     */
    private function get_total_inventory( $shopify_product ) {
        $variants = $shopify_product['variants'] ?? array();
        $total = 0;
        foreach ( $variants as $variant ) {
            $total += isset( $variant['inventory_quantity'] ) ? intval( $variant['inventory_quantity'] ) : 0;
        }
        return $total;
    }

    /**
     * Get stock status.
     *
     * @param array $shopify_product Shopify product.
     * @return string
     */
    private function get_stock_status( $shopify_product ) {
        $total = $this->get_total_inventory( $shopify_product );
        return $total > 0 ? 'instock' : 'outofstock';
    }

    /**
     * Extract images from Shopify product.
     *
     * @param array $shopify_product Shopify product.
     * @return array
     */
    private function extract_images( $shopify_product ) {
        $images = array();
        $shopify_images = $shopify_product['images'] ?? array();
        foreach ( $shopify_images as $img ) {
            if ( ! empty( $img['src'] ) ) {
                $images[] = $img['src'];
            }
        }
        return $images;
    }

    /**
     * Extract categories from Shopify product.
     *
     * @param array $shopify_product Shopify product.
     * @return array
     */
    private function extract_categories( $shopify_product ) {
        $categories = array();
        $product_type = $shopify_product['product_type'] ?? '';
        if ( $product_type ) {
            $categories[] = $product_type;
        }
        // Shopify doesn't have categories like WooCommerce, use product_type
        return $categories;
    }

    /**
     * Extract tags from Shopify product.
     *
     * @param array $shopify_product Shopify product.
     * @return array
     */
    private function extract_tags( $shopify_product ) {
        $tags = $shopify_product['tags'] ?? '';
        if ( empty( $tags ) ) {
            return array();
        }
        return array_map( 'trim', explode( ',', $tags ) );
    }

    /**
     * Extract attributes from Shopify product.
     *
     * @param array $shopify_product Shopify product.
     * @return array
     */
    private function extract_attributes( $shopify_product ) {
        $attrs = array();
        $options = $shopify_product['options'] ?? array();
        foreach ( $options as $option ) {
            $name = $option['name'] ?? '';
            if ( $name ) {
                $values = array();
                foreach ( $option['values'] ?? array() as $value ) {
                    $values[] = $value;
                }
                $attrs[ $name ] = array(
                    'values'    => $values,
                    'visible'   => true,
                    'variation' => true,
                );
            }
        }
        return $attrs;
    }

    /**
     * Register webhook for real-time sync.
     *
     * @param array  $credentials Connection credentials.
     * @param string $event      Event type.
     * @param string $webhook_url Webhook URL.
     * @return array
     */
    public function register_webhook( $credentials, $event, $webhook_url ) {
        $shop_domain  = $credentials['shop_domain'] ?? '';
        $access_token = $credentials['access_token'] ?? '';

        if ( empty( $shop_domain ) || empty( $access_token ) ) {
            return array(
                'success' => false,
                'error'   => 'Missing required credentials.',
            );
        }

        $url = $this->build_api_url( $shop_domain, 'webhooks.json' );
        $data = array(
            'webhook' => array(
                'topic'   => $event,
                'address' => $webhook_url,
                'format'  => 'json',
            ),
        );

        $result = $this->api_request( $url, $access_token, 'POST', $data );

        if ( $result['success'] ) {
            $webhook = $result['data']['webhook'] ?? array();
            return array(
                'success'    => true,
                'webhook_id' => $webhook['id'] ?? '',
            );
        }

        return array(
            'success' => false,
            'error'   => $result['error'] ?? 'Failed to register webhook.',
        );
    }

    /**
     * Unregister webhook.
     *
     * @param array  $credentials Connection credentials.
     * @param string $webhook_id  Webhook ID.
     * @return bool
     */
    public function unregister_webhook( $credentials, $webhook_id ) {
        $shop_domain  = $credentials['shop_domain'] ?? '';
        $access_token = $credentials['access_token'] ?? '';

        if ( empty( $shop_domain ) || empty( $access_token ) || empty( $webhook_id ) ) {
            return false;
        }

        $url = $this->build_api_url( $shop_domain, 'webhooks/' . absint( $webhook_id ) . '.json' );
        $result = $this->api_request( $url, $access_token, 'DELETE' );

        return $result['success'];
    }
}


