<?php

namespace App\Services\Amazon;

use Carbon\Carbon;
use GuzzleHttp\Client;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Storage;
use Yajny\EventsYj\Events\SaleNew;
use Yajny\EventsYj\Events\SaleUpdated;
use Yajny\Member\Models\AmazonReadLog;
use Yajny\Member\Models\Click;
use Yajny\Member\Models\Sale;
use Yajny\Member\Models\SaleItem;

abstract class AmazonItemsCheckerService
{
    public $baseURL = 'https://assoc-datafeeds-eu.amazon.com/datafeed/getReport';
    public $client;
    public $network;
    public $dateToFetch;

    abstract function getFileName($dateToFetch): string;

    abstract function getAuthUserName(): string;

    abstract function getAuthPassword(): string;

    abstract function getCurrencyCode(): string;

    public function __construct($network, $dateToFetch)
    {
        $this->client = new Client();
        $this->network = $network;
        $this->dateToFetch = $dateToFetch;
    }

    public function check()
    {
        $reportItems = [];
        $dbItemsIDs = [];

        $fileDate = date('Ymd', strtotime($this->dateToFetch));
        $fileName = $this->getFileName($fileDate);
        $salesCompressedResponse = $this->client->get($this->baseURL . '?filename=' . $fileName, [
            'auth' => [
                $this->getAuthUserName(),
                $this->getAuthPassword(),
                'digest'
            ]
        ]);

        $responseAttributes = $this->readFile($salesCompressedResponse);
        if (isset($responseAttributes['items'])) {
            foreach ($responseAttributes['items'] as $key => $item) {
                if (strval($key) == '@attributes')
                    $saleItem = $item;
                else
                    $saleItem = $item['@attributes'];

                if (!is_numeric($saleItem['SubTag']))
                    continue;

                /** Clean File Data **/
                $unitPrice = str_replace(',', '', $saleItem['Price']);
                $commission = str_replace(',', '', $saleItem['Earnings']);
                $quantity = str_replace(',', '', $saleItem['Qty']);
                $revenue = str_replace(',', '', $saleItem['Revenue']);
                $saleItem['Price'] = doubleval($unitPrice);
                $saleItem['Earnings'] = doubleval($commission);
                $saleItem['Qty'] = doubleval($quantity);
                $saleItem['Revenue'] = doubleval($revenue);
                $saleItem['categoryName'] = $responseAttributes['categories'][$saleItem['Category']] ?? '';
                $saleItem['sale_id'] = null;
                $saleItem['sale_item_id'] = null;
                $saleItem['db_click_id'] = null;

                $dbItem = DB::table('sale_items')
                    ->join('sales', 'sale_items.sale_id', '=', 'sales.id')
                    ->where('sales.network_id', $this->network->id)
                    ->where('sales.click_id', '=', $saleItem['SubTag'])
                    ->whereDate('sale_items.report_date', '=', $this->dateToFetch)
                    ->where('sale_items.unit_price', '=', $saleItem['Price'])
                    ->where('sale_items.quantity', '=', $saleItem['Qty'])
                    ->where('sale_items.commission', '=', $saleItem['Earnings'])
                    ->where('sale_items.category', '=', $saleItem['categoryName']) // For Duplicates
                    ->whereNotIn('sale_items.id', $dbItemsIDs)
                    ->select(['sales.id as sale_id', 'sale_items.id as sale_item_id', 'sales.click_id as db_click_id'])
                    ->first();

                if ($dbItem) {
                    $saleItem['sale_id'] = $dbItem->sale_id;
                    $saleItem['sale_item_id'] = $dbItem->sale_item_id;
                    $saleItem['db_click_id'] = $dbItem->db_click_id;
                    $dbItemsIDs[] = $dbItem->sale_item_id;
                }

                $reportItems[] = $saleItem;
            }
        }

        $otherItems = DB::table('sale_items')
            ->join('sales', 'sale_items.sale_id', '=', 'sales.id')
            ->where('sales.network_id', $this->network->id)
            ->whereDate('sale_items.report_date', '=', $this->dateToFetch)
            ->whereNotIn('sale_items.id', $dbItemsIDs)
            ->select(['sale_items.*', 'sales.id as sale_id', 'sales.click_id'])
            ->get();

        return ['reportItems' => $reportItems, 'otherItems' => $otherItems];
    }

    private function readFile($response)
    {
        $xmlDecodedResponse = '';
        $compressedResponse = $response->getBody()->getContents();
        if ($compressedResponse)
            $xmlDecodedResponse = gzdecode($compressedResponse);
        else
            Log::info('Unexpected Empty Response');

        $rawSalesXML = simplexml_load_string($xmlDecodedResponse);
        $rawSales = json_decode(json_encode($rawSalesXML), true);
        if (isset($rawSales['Items']['Item'])) {
            $items = $rawSales['Items']['Item'];
            $categories = Arr::pluck($rawSales['ProductLine_array']['ProductLine'], 'ProductGroupName', 'GLProductGroupID');
            return compact('items', 'categories');
        }
        return ['items' => [], 'categories' => []];
    }
}
