<?php

namespace App\Http\Controllers\Network;

use App\Http\Controllers\Controller;
use App\Http\Controllers\Network\Classes\LinkValidationApi;
use App\Http\Controllers\Network\Classes\SalesGetterApi;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Mail;
use Yajny\EventsYj\Events\SaleNew;
use Yajny\EventsYj\Events\SaleUpdated;
use Yajny\Member\Exceptions\CurrencyNotFoundException;
use Yajny\Member\Models\Network;
use Yajny\Member\Models\Sale;
use Yajny\Models\Store;

abstract class BaseNetwork extends Controller
{
    protected $sales;

    /** @var Network $network */
    protected $network;

    /** @var SalesGetterApi $baseNetworkApi */
    protected $baseNetworkApi;

    public function __construct(Network $network, SalesGetterApi $api)
    {
        $this->sales = [];
        $this->network = $network;
        $this->baseNetworkApi = $api;
    }

    /**
     * Getting sales from network and prepare it to be ready for saving.
     *
     * @param DateTime $start_days filter sales based on start days
     * @param DateTime $end_days filter sales based on end days
     *
     * @throws Exception If issue happened on saving sales
     */
    public function getSales($start_days, $end_days)
    {
        /** Function from API of the network which returns array of Sale orders **/
        $this->sales = $this->baseNetworkApi->getSales($start_days, $end_days);
        foreach ($this->sales as $saleOrder) {
            try {
                $sale = $this->mapNetworkSaleToYajnySale($saleOrder);
                if (is_null($sale))
                    continue;

                $isSaleExist = $sale->exists;
                $sale->save();
                /** If $sale exists before so we raise SaleUpdate event. */
                $saleEvent = $isSaleExist ? new SaleUpdated($sale, $sale->getChanges()) : new SaleNew($sale);
                event($saleEvent);
                /** If the network is implements HasSaleItems interface which mean that network API return item by item */
                if ($this instanceof HasSaleItems) {
                    $this->syncSaleItems($sale, $saleOrder);
                }
            } catch (CurrencyNotFoundException $e) {
                Log::error($e->getMessage(), ['Sale' => $sale->attributes, 'network' => $this->network->toArray(), 'saleOrder' => $saleOrder]);
            } catch (\Exception $exception) {
                Log::error('error while getting sale', ['exception' => $exception, 'Sale' => isset($sale) ? $sale->attributes : null]);
            }
        }
    }

    public function validateLinks()
    {
        if (!($this->baseNetworkApi instanceof LinkValidationApi))
            return;

        $stores = Store::where('network_id', $this->network->id)->where('cb_status', 1)->get();
        $invalidStores = [];
        foreach ($stores as $store) {
            try {
                if (!$this->baseNetworkApi->ValidateLink($store->dl_url_build)) {
                    $invalidStores[] = $store->slug;
                }
            } catch (\Exception $exception) {
                $invalidStores[] = $store->slug;
                Log::error('error while validating store', ['exception' => $exception, 'store' => $store->toArray()]);
            }
        }
        if ($invalidStores) {
            Log::info("invalid links for {$this->network->name}", compact('invalidStores'));
            Mail::send([], [], function ($message) use ($invalidStores) {
                $message->from('noreply@yajny.com')
                    ->to('maher.adel@arabyads.com')
                    ->cc(['affiliate@yajny.com'])
                    ->subject("{$this->network->name} invalid stores")
                    ->setBody(implode(' , ', $invalidStores));
            });
        }
    }

    abstract function mapNetworkSaleToYajnySale($saleOrder): ?Sale;
}
