<?php

namespace App\Jobs;

use Carbon\Carbon;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;

use App\Mail\TrafficMismatch;
use App\Models\Service\Adsl;
use App\Models\Service\AdslTraffic;
use App\Models\AdslSupplier;
use Illuminate\Support\Facades\Mail;

/**
 * Class BroadbandTraffic
 * Read and update the traffic for an Broadband supplier
 *
 * @package App\Jobs
 */
class BroadbandTraffic implements ShouldQueue
{
	use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

	protected $aso = NULL;
	private $class_prefix = 'App\Classes\External\Supplier\\';

	public function __construct(AdslSupplier $o)
	{
		$this->aso = $o;
	}

	/**
	 * Execute the job.
	 *
	 * @return void
	 */
	public function handle()
	{
		$u = 0;

		$class = $this->class_prefix.$this->aso->name;

		if (class_exists($class)) {
			$o = new $class($this->aso);

		} else {
			Log::error(sprintf('%s: Class doesnt exist: %d',get_class($this),$class));
			exit(1);
		}

		AdslTraffic::where('supplier_id',$this->aso->id)
			->where('date',$this->aso->stats_lastupdate)
			->delete();

		// @todo Need to trap errors from getting data
		$c = 0;
		foreach (explode("\n",$o->connect()) as $line) {
			if (! trim($line))
				continue;

			// The first row is our header
			if (! $c++) {
				$fields = $o->getColumns(preg_replace('/,\s+/',',',$line),collect($o->header()));
				continue;
			}

			if (! $fields->count())
				abort(500,'? No fields in data exportupda');

			$row = str_getcsv(trim($line));

			try {
				$date = Carbon::createFromFormat('Y-m-d',$row[$o->getColumnKey('Date')]);

				$oo = Adsl::where('service_username',$row[$o->getColumnKey('Login')])
					->select(DB::raw('ab_service__adsl.*'))
					->join('ab_service','ab_service.id','=','service_id')
					->where('ab_service.date_start','<=',$date->format('U'))
					->where(function($query) use ($date) {
						$query->whereNULL('ab_service.date_end')
							->orWhere('ab_service.date_end','<=',$date->format('U'));
					})
					->get();

				// If we have no records
				if ($oo->count() != 1) {
					Log::error(sprintf('! Records Errors for:%s (%s) [%s]',$row[$o->getColumnKey('Login')],$date,$oo->count()));

					$to = new AdslTraffic;
					$to->site_id = 1; // @todo TO ADDRESS
					$to->service = $row[$o->getColumnKey('Login')];
					$to->date = $this->aso->stats_lastupdate;
					$to->supplier_id = $this->aso->id;
					$to->up_peak = $row[$o->getColumnKey('Peak upload')];
					$to->up_offpeak = $row[$o->getColumnKey('Off peak upload')];
					$to->down_peak = $row[$o->getColumnKey('Peak download')];
					$to->down_offpeak = $row[$o->getColumnKey('Off peak download')];
					// $to->peer
					// $to->internal
					$to->time = '24:00'; // @todo
					$to->save();
					$u++;

				} else {
					$to = new AdslTraffic;
					$to->site_id = 1; // @todo TO ADDRESS
					$to->date = $this->aso->stats_lastupdate;
					$to->supplier_id = $this->aso->id;
					$to->up_peak = $row[$o->getColumnKey('Peak upload')];
					$to->up_offpeak = $row[$o->getColumnKey('Off peak upload')];
					$to->down_peak = $row[$o->getColumnKey('Peak download')];
					$to->down_offpeak = $row[$o->getColumnKey('Off peak download')];
					// $to->peer
					// $to->internal
					$to->time = '24:00'; // @todo
					$oo->first()->traffic()->save($to);
					$u++;
				}
			} catch (\Exception $e) {
				dd(['row'=>$row,'line'=>$line]);
			}
		}

		if ($u) {
			$this->aso->stats_lastupdate = $this->aso->stats_lastupdate->addDay();
			$this->aso->save();

			if ($this->aso->traffic_mismatch($date)->count())
				Mail::to('deon@graytech.net.au')        // @todo To change
					->send(new TrafficMismatch($this->aso,$date));
		}

		Log::info(sprintf('%s: Records Imported: %d',get_class($this),$u));
	}
}