<?php

namespace App\Services;

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

class ShiprocketService
{
    private $base_url = "https://apiv2.shiprocket.in/v1/external";

    /*
       AUTH
     */
    public function login()
    {
        $response = Http::withoutVerifying()->post(
            $this->base_url . "/auth/login",
            [
                "email" => env('SHIPROCKET_EMAIL'),
                "password" => env('SHIPROCKET_PASSWORD')
            ]
        );

        $data = $response->json();

        if (!isset($data['token'])) {
            Log::error('Shiprocket Login Failed', ['response' => $data]);
            throw new \Exception("Shiprocket authentication failed");
        }

        Cache::put('shiprocket_token', $data['token'], now()->addHours(9));

        return $data['token'];
    }

    public function getToken()
    {
        return Cache::get('shiprocket_token') ?? $this->login();
    }

    /* 
       API REQUEST 
     */
    public function request($method, $endpoint, $data = [])
    {
        $token = $this->getToken();

        $http = Http::withoutVerifying()
            ->withToken($token)
            ->acceptJson();

        $url = $this->base_url . $endpoint;

        if ($method === 'get') {
            $response = $http->get($url, $data);   // query params
        } else {
            $response = $http->$method($url, $data); // JSON body
        }

        return $response->json();
    }

    /* 
       CREATE SHIPMENT/ORDER
    */
    public function createShipment($order)
    {
        // Prevent duplicate shipment
        if ($order->shipment_id) {
            return;
        }

        try {
            $payload = [
                "order_id" => $order->order_number,
                "order_date" => $order->created_at->format('Y-m-d H:i'),
                "pickup_location" => env('SHIPROCKET_PICKUP_NAME', 'warehouse'), // configure in Shiprocket panel

                "billing_customer_name" => $order->first_name,
                "billing_last_name" => $order->last_name,
                "billing_address" => $order->address1,
                "billing_address_2" => $order->address2 ?? '',
                "billing_city"  => $order->city,
                "billing_pincode" => $order->post_code,
                "billing_state" => $order->state,
                "billing_country" => "India",
                "billing_email" => $order->email,
                "billing_phone" => $order->phone,

                "shipping_is_billing" => true,

                "order_items" => $this->buildItems($order),

                "payment_method" => $order->payment_method == 'cod' ? "COD" : "Prepaid",
                "sub_total" => $order->sub_total,
                "shipping_charges" => $order->delivery_charge,

                "length" => 10,
                "breadth" => 10,
                "height" => 10,
                "weight" => 0.5
            ];
            Log::info('Shiprocket Create Order Payload', $payload);
            $response = $this->request('post', '/orders/create/adhoc', $payload);
            Log::info('Shiprocket Create Order Response', $response);
            if (isset($response['order_id'])) {
                $order->update([
                    'shiprocket_order_ref' => $response['order_id'],
                    'shiprocket_status'    => 'order_created'
                ]);
            }
            if (!isset($response['shipment_id'])) {
                Log::error('Shiprocket Order Create Failed', ['response' => $response]);
                return;
            }

            if ($order->courier_id) {

                // assign courier
                $this->request('post', '/courier/assign', [
                    "shipment_id" => $response['shipment_id'],
                    "courier_id"  => (int) $order->courier_id
                ]);

                // generate AWB for that courier
                $awb = $this->request('post', '/courier/assign/awb', [
                    "shipment_id" => $response['shipment_id'],
                    "courier_id"  => (int) $order->courier_id
                ]);
            } else {

                // fallback 
                $awb = $this->request('post', '/courier/assign/awb', [
                    "shipment_id" => $response['shipment_id']
                ]);
            }

            $awb_code = $awb['awb_code'] ?? null;

            // Generate Label
            $label = $this->request('post', '/courier/generate/label', [
                "shipment_id" => [$response['shipment_id']]
            ]);

            // Generate Invoice
$invoice = $this->request('post', '/orders/print/invoice', [
    "ids" => [$response['order_id']]
]);

Log::info('Shiprocket Invoice Response', $invoice);

$invoice_url = $invoice['invoice_url'] ?? null;

            // Track URL
            $tracking_url = null;
            if ($awb_code) {
                $track = $this->request('get', '/courier/track/awb/' . $awb_code);
                $tracking_url = $track['tracking_data']['track_url'] ?? null;
            }
            // Save in DB
            $order->update([
    'shipment_id' => $response['shipment_id'],
    'awb_code' => $awb_code,
    'courier_name' => $awb['courier_name'] ?? null,
    'courier_id'   => $order->courier_id,
    'tracking_url' => $tracking_url,
    'label_url' => $label['label_url'] ?? null,
    'shiprocket_invoice_url' => $invoice_url,
    'shiprocket_status' => 'awb_assigned'
]);
        } catch (\Exception $e) {
            Log::error('Shiprocket Shipment Error: ' . $e->getMessage());
        }


        return [
'create_order' => $response ?? null,
'awb' => $awb ?? null,
'label' => $label ?? null,
'invoice' => $invoice ?? null,
'tracking' => $tracking_url ?? null,
];
    }


    public function createReturnPickup($order)
    {
        try {

            $payload = [
                "order_id" => "RET-" . $order->order_number,
                "order_date" => now()->format('Y-m-d H:i'),

                "pickup_customer_name" => $order->first_name,
                "pickup_last_name" => $order->last_name,

                "pickup_address" => $order->address1,
                "pickup_address_2" => $order->address2 ?? "",
                "pickup_city" => $order->city,
                "pickup_state" => $order->state,
                "pickup_country" => "India",
                "pickup_pincode" => $order->post_code,

                "pickup_email" => $order->email,
                "pickup_phone" => $order->phone,

                "order_items" => $this->buildItems($order),

                "payment_method" => "Prepaid",
                "sub_total" => $order->sub_total,

                "length" => 10,
                "breadth" => 10,
                "height" => 10,
                "weight" => 0.5
            ];

            Log::info('Shiprocket Return Pickup Payload', $payload);

            $response = $this->request('post', '/orders/create/return', $payload);

            Log::info('Shiprocket Return Pickup Response', $response);

            return $response;
        } catch (\Exception $e) {
            Log::error('Shiprocket Return Pickup Error: ' . $e->getMessage());
            return null;
        }
    }

    /* 
       BUILD ORDER ITEMS
     */
private function buildItems($order)
{
    $items = [];

    foreach ($order->cart as $cart) {

        if ($cart->item_type === 'product' && $cart->product) {

            $product = $cart->product;

            $price = $cart->price;
            $taxRate = $product->tax_percentage ?? 0;

            $items[] = [
                "name" => $product->title,
                "sku" => $product->slug,
                "units" => $cart->quantity,

                "selling_price" => $price,

                // GST %
                "tax" => $taxRate,

                // HSN CODE
                "hsn" => $product->hsn_code ?? "",

                "discount" => 0
            ];
        }
    }

    return $items;
}
    public function getRates($deliveryPincode, $weight = 0.5, $cod = false)
    {
        return $this->request('get', '/courier/serviceability', [
            'pickup_postcode'   => env('SHIPROCKET_PICKUP_PINCODE'),
            'delivery_postcode' => $deliveryPincode,
            'weight'            => max(0.5, $weight),
            'cod'               => $cod ? 1 : 0
        ]);

        \Log::info("Shiprocket raw response",$response->json());
    }
}
