<?php

namespace App\Services;

use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Cache;
use Exception;

/**
 * Shopify API connection - same approach as productos-costo-cero(1).php
 * (OAuth client_credentials token + GraphQL).
 */
class ShopifyService
{
    protected string $shop;
    protected string $clientId;
    protected string $clientSecret;
    protected string $apiVersion;

    public function __construct()
    {
        $this->shop = config('services.shopify.shop');
        $this->clientId = config('services.shopify.client_id');
        $this->clientSecret = config('services.shopify.client_secret');
        $this->apiVersion = config('services.shopify.api_version');
    }

    /**
     * Get access token (client_credentials). Cached 23h to avoid repeated calls.
     */
    public function getAccessToken(): string
    {
        $cacheKey = 'shopify_access_token_' . $this->shop;
        return Cache::remember($cacheKey, 60 * 23, function () {
            $url = "https://{$this->shop}.myshopify.com/admin/oauth/access_token";
            $response = Http::asForm()
                ->timeout(30)
                ->post($url, [
                    'grant_type' => 'client_credentials',
                    'client_id' => $this->clientId,
                    'client_secret' => $this->clientSecret,
                ]);

            if (!$response->successful()) {
                throw new Exception('Shopify token HTTP ' . $response->status() . ': ' . $response->body());
            }

            $json = $response->json();
            if (empty($json['access_token'])) {
                throw new Exception('Shopify token invalid: ' . $response->body());
            }

            return $json['access_token'];
        });
    }

    /**
     * Run GraphQL query/mutation (same as shopify_graphql in reference file).
     */
    public function graphql(string $query, array $variables = []): array
    {
        $token = $this->getAccessToken();
        $url = "https://{$this->shop}.myshopify.com/admin/api/{$this->apiVersion}/graphql.json";

        $response = Http::withHeaders([
            'X-Shopify-Access-Token' => $token,
            'Content-Type' => 'application/json',
        ])
            ->timeout(60)
            ->post($url, [
                'query' => $query,
                'variables' => (object) $variables,
            ]);

        if (!$response->successful()) {
            throw new Exception('Shopify GraphQL HTTP ' . $response->status() . ': ' . $response->body());
        }

        $json = $response->json();
        if (!is_array($json)) {
            throw new Exception('Shopify GraphQL invalid JSON: ' . $response->body());
        }
        if (!empty($json['errors'])) {
            throw new Exception('Shopify GraphQL errors: ' . json_encode($json['errors']));
        }

        return $json;
    }

    /**
     * Search products by title (query string for Shopify, same style as reference file).
     */
    public function searchProductsByTitle(string $query, int $first = 50, ?string $cursor = null): array
    {
        $q = $query !== '' ? trim($query) : 'status:active';
        $query = <<<'GQL'
query($cursor: String, $q: String!, $first: Int!) {
  products(first: $first, after: $cursor, query: $q) {
    edges {
      node {
        id
        title
        status
        variants(first: 100) {
          edges {
            node {
              id
              price
              compareAtPrice
              inventoryItem {
                unitCost { amount }
              }
            }
          }
        }
      }
    }
    pageInfo { hasNextPage endCursor }
  }
}
GQL;

        $vars = ['q' => $q, 'first' => $first];
        if ($cursor) {
            $vars['cursor'] = $cursor;
        }

        $resp = $this->graphql($query, $vars);
        return $resp['data']['products'] ?? ['edges' => [], 'pageInfo' => ['hasNextPage' => false, 'endCursor' => null]];
    }

    /**
     * Update variant price and compareAtPrice in Shopify.
     */
    public function updateVariantPrice(string $variantId, string $price, ?string $compareAtPrice = null): array
    {
        $query = <<<'GQL'
mutation productVariantUpdate($input: ProductVariantInput!) {
  productVariantUpdate(input: $input) {
    productVariant {
      id
      price
      compareAtPrice
    }
    userErrors { field message }
  }
}
GQL;

        $input = [
            'id' => $variantId,
            'price' => $price,
        ];
        if ($compareAtPrice !== null) {
            $input['compareAtPrice'] = $compareAtPrice;
        }

        $resp = $this->graphql($query, ['input' => $input]);
        $data = $resp['data']['productVariantUpdate'] ?? null;
        if ($data && !empty($data['userErrors'])) {
            throw new Exception('Shopify update errors: ' . json_encode($data['userErrors']));
        }
        return $data ?? [];
    }
}
