<?php

namespace App\Http\Controllers\Network;

use App\Http\Controllers\Network\Classes\CJ;
use Illuminate\Support\Str;
use Yajny\Member\Models\Network;
use Yajny\Member\Models\Sale;
use Yajny\Models\Coupon;
use Yajny\Models\Store;
use Yajny\Models\StoreCashback;

class CommissionJunction extends BaseNetwork
{
    //TODO: this class needs refactoring to align with SOLID.
    public $stores;

    /**
     * Create a new network instance.
     *
     * @param Network $network
     */
    public function __construct(Network $network)
    {
        $this->stores = [];
        parent::__construct($network, new CJ($network->api_key, $network->affiliate_id, $network->website_id));
    }

    /**
     * Mapping sales from network for saving.
     *
     * @param array|object $saleOrder the network sale order
     *
     * @return Sale Sale object saved on Database.
     * @throws Exception If issue happened on saving sales
     *
     */
    public function mapNetworkSaleToYajnySale($saleOrder): ?Sale
    {
        $sale = Sale::withoutGlobalScopes()->firstOrNew(['network_id' => $this->network->id, 'network_transaction_id' => $saleOrder['commissionId']]);

        if (!$sale->exists) {
            $sale->order_id = $saleOrder['orderId'];
            $sale->click_id = intval($saleOrder['shopperId']);
            $sale->network_sale_id = $saleOrder['aid'];
            $sale->transaction_time = date('Y-m-d H:i:s', strtotime($saleOrder['eventDate']));
            $sale->currency = 'USD';
        }
        $sale->local_order_amount = $saleOrder['saleAmountPubCurrency'];
        $sale->local_comission = $saleOrder['pubCommissionAmountPubCurrency'];
        $sale->network_status = $saleOrder['actionStatus'];
        $sale->setStatus($this->network->sale_statuses);
        return $sale;
    }

    /**
     * Getting stores from network and Updating cashback rates.
     *
     * @param Network $network the network object
     */
    public function getStores($network)
    {
        $cj = new CJ($network->api_key, $network->affiliate_id, $network->website_id);
        $cj->getStores();
        foreach ($cj->stores as $batchstores) {
            foreach ($batchstores as $cjStore) {
                $store = Store::withoutGlobalScopes()->firstOrNew(['creation_mode' => 'CommissionJunction', 'network_store_id' => $cjStore->{'advertiser-id'}]);
                // update
                if ($store->exists) {
                    $cbArray = $this->getCashbackStruct($cjStore);
                    foreach ($cbArray as $cbStruct) {
                        $storecb = StoreCashback::updateOrCreate(['store_id' => $store->id, 'network_refid' => $cbStruct['id']], ['rate_type' => $cbStruct['type'], 'rate_amount' => $cbStruct['amount']]);
                        if (!$storecb->exists) {
                            foreach (explode(',', config('website.cnf_langs')) as $lang)
                                $storecb->setTranslation('title', $lang, $cbStruct['name']);
                        }
                        $storecb->save();
                    }
                } // create
                else {
                    // set multi lang names
                    foreach (explode(',', config('website.cnf_langs')) as $lang)
                        $store->setTranslation('name', $lang, $cjStore->{'advertiser-name'}->__toString());
                    $cats = [];
                    if (isset($cjStore->{'primary-category'})) {
                        $pcat = null;
                        $ccat = null;
                        if (!is_array($cjStore->{'primary-category'}->parent))
                            $pcat = ($network->categoryMappingName[md5(Str::slug($cjStore->{'primary-category'}->parent))]) ?? null;
                        if (!is_array($cjStore->{'primary-category'}->child))
                            $pcat = ($network->categoryMappingName[md5(Str::slug($cjStore->{'primary-category'}->child))]) ?? null;
                        if ($pcat) $cats[] = $pcat;
                        if ($ccat) $cats[] = $ccat;
                    }
                    $store->homepage = $cjStore->{'program-url'}->__toString();
                    $store->slug = Str::slug($cjStore->{'advertiser-name'}->__toString() . '-' . $cjStore->{'advertiser-id'});
                    $store->status = 'draft';
                    $store->network_id = $network->id;
                    $store->save();
                    $cbArray = $this->getCashbackStruct($cjStore);
                    foreach ($cbArray as $cbStruct) {
                        $storecb = new StoreCashback(['rate_type' => $cbStruct['type'], 'rate_amount' => $cbStruct['amount'], 'network_refid' => $cbStruct['id']]);
                        foreach (explode(',', config('website.cnf_langs')) as $lang)
                            $storecb->setTranslation('title', $lang, $cbStruct['name']);
                        $store->store_cashback()->save($storecb);
                    }
                }
            }
        }
    }

    /**
     * Getting cashback structure and rates.
     *
     * @param object $cjStore the network object
     *
     * @return array The array of cashback rates.
     */
    public function getCashbackStruct($cjStore)
    {
        $cbArray = [];
        if (isset($cjStore->actions)) {
            if (isset($cjStore->actions->action)) {
                foreach ($cjStore->actions->action as $action) {
                    $commission = $action->commission->default;
                    if (strpos($commission, '%') > 1)
                        $type = 'percent';
                    else $type = 'fixed';
                    $rate = preg_replace("/[^0-9\.]/", "", $commission);
                    $cbArray[] = array('type' => $type, 'amount' => $rate, 'name' => $action->name->__toString(), 'id' => $action->id);
                    if (isset($action->commission->itemlist)) {
                        if (is_array($action->commission->itemlist)) {
                            foreach (isset($action->commission->itemlist) as $itemlist) {
                                if (strpos($itemlist, '%') > 1)
                                    $type = 'percent';
                                else $type = 'fixed';
                                $rate = preg_replace("/[^0-9\.]/", "", $itemlist);
                                $cbArray[] = array(
                                    'type' => $type, 'amount' => $rate,
                                    'name' => $action->name->__toString() . ' ' . $itemlist->attributes()->name->__toString(),
                                    'id' => $action['id'] . '-' . $itemlist->attributes()->id->__toString()
                                );
                            }
                        }
                    }
                }
            }
        }
        return $cbArray;
    }

    /**
     * Getting coupons from network and saving them.
     *
     * @param Network $network the network object
     */
    public function getCoupons($network)
    {
        $cj = new CJ($network->api_key, $network->affiliate_id, $network->website_id);
        $cj->getCoupons();
        foreach ($cj->coupons as $batchCoupons) {
            foreach ($batchCoupons as $cjCoupon) {
                $coupon = Coupon::firstOrNew(['created_mode' => 'CommissionJunction', 'network_coupon_id' => $cjCoupon->{'link-id'}]);
                if ($coupon->exists) {
                    // update case
                } else {
                    if (!isset($network->storeIds[$cjCoupon->{'advertiser-id'}->__toString()])) continue;
                    foreach (explode(',', config('website.cnf_langs')) as $lang)
                        $coupon->setTranslation('title', $lang, $cjCoupon->{'link-name'}->__toString());
                    foreach (explode(',', config('website.cnf_langs')) as $lang)
                        $coupon->setTranslation('description', $lang, $cjCoupon->{'description'}->__toString());
                    $coupon->link = $cjCoupon->destination;
                    $cat = ($network->categoryMappingName[md5(Str::slug($cjCoupon->category))]) ?? null;
                    if ($cat)
                        $coupon->cats = [$cat];
                    if ($cjCoupon->{'coupon-code'}) {
                        $coupon->code = $cjCoupon->{'coupon-code'}->__toString();
                    }
                    if ($cjCoupon->{'promotion-end-date'})
                        $coupon->expiry_date = date('Y-m-d', strtotime($cjCoupon->{'promotion-end-date'}->__toString()));
                    $coupon->store_id = $network->storeIds[$cjCoupon->{'advertiser-id'}->__toString()];
                    $coupon->network_id = $network->id;
                    $coupon->status = 'draft';
                    $coupon->save();
                }
            }
        }
    }
}
