<?php

namespace App\Http\Controllers;

use Carbon\Carbon;
use Illuminate\Http\Request;

use App\Http\Requests\{SupplierAddEdit,SupplierProductAddEdit};
use App\Models\{Cost,Supplier,SupplierDetail};
use App\Jobs\ImportCosts;

class SupplierController extends Controller
{
	/**
	 * Update a suppliers details
	 *
	 * @param SupplierAddEdit $request
	 * @param Supplier $o
	 * @return \Illuminate\Contracts\Foundation\Application|\Illuminate\Contracts\View\Factory|\Illuminate\Contracts\View\View|\Illuminate\Http\RedirectResponse
	 */
	public function addedit(SupplierAddEdit $request,Supplier $o)
	{
		$this->middleware(['auth','wholesaler']);

		foreach ($request->except(['_token','supplier_details','api_key','api_secret','submit']) as $key => $item)
			$o->{$key} = $item;

		$o->active = (bool)$request->active;

		try {
			$o->save();

		} catch (\Exception $e) {
			return redirect()->back()->withErrors($e->getMessage())->withInput();
		}

		$o->load(['detail']);
		$oo = $o->detail ?: new SupplierDetail;

		foreach ($request->get('supplier_details',[]) as $key => $item)
			$oo->{$key} = $item;

		$oo->connections = $oo->connections->merge([
			'api_key'=>$request->get('api_key'),
			'api_secret'=>$request->get('api_secret'),
		])->filter();
		$o->detail()->save($oo);

		return redirect()
			->back()
			->with('success','Supplier Saved');
	}

	/**
	 * Site up site wide suppliers, or a site's supplier details
	 *
	 * @note This method is protected by the routes
	 * @return \Illuminate\Contracts\Foundation\Application|\Illuminate\Contracts\View\Factory|\Illuminate\Contracts\View\View
	 */
	public function admin_home()
	{
		$this->middleware(['auth','wholesaler']);

		return view('theme.backend.adminlte.supplier.home');
	}

	/**
	 * Show the suppliers invoice
	 *
	 * @param Cost $o
	 * @return \Illuminate\Contracts\Foundation\Application|\Illuminate\Contracts\View\Factory|\Illuminate\Contracts\View\View
	 */
	public function cost(Cost $o)
	{
		// @todo Need to add the services that are active that are not on the bill for the supplier.
		return view('theme.backend.adminlte.supplier.cost.view')
			->with('o',$o);
	}

	public function cost_add(Supplier $o)
	{
		return view('theme.backend.adminlte.supplier.cost.add')
			->with('o',$o);
	}

	public function cost_submit(Request $request,Supplier $o)
	{
		$request->validate([
			'file' => 'required|filled',
			'billed_at' => 'required|date',
		]);

		$filename = $request->file('file')->store('cost_import');

		ImportCosts::dispatch(
			config('site'),
			$o,
			Carbon::create($request->billed_at),
			$filename,
		)->onQueue('low');

		return redirect()->back()->with('success','File uploaded');
	}

	/**
	 * New Product from a supplier
	 *
	 * @return \Illuminate\Contracts\Foundation\Application|\Illuminate\Contracts\View\Factory|\Illuminate\Contracts\View\View
	 */
	public function product_add()
	{
		return view('theme.backend.adminlte.supplier.product.addedit')
			->with('o',new Supplier)
			->with('oo',NULL);
	}

	public function product_addedit(SupplierProductAddEdit $request,Supplier $o,int $id,string $type)
	{
		// Quick validation
		if ($type !== $request->offering_type)
			abort(500,'Type and offering type do not match');
		if ($o->exists && ($o->detail->id !== (int)$request->supplier_detail_id))
			abort(500,sprintf('Supplier [%d] and supplier_detail_id [%d] do not match',$o->detail->id,$request->supplier_detail_id));

		switch ($request->offering_type) {
			case 'broadband':
				$oo = Supplier\Broadband::findOrNew($id);

				// @todo these are broadband requirements - get them from the broadband class.
				foreach ($request->only([
					'supplier_detail_id',
					'product_id'.
					'product_desc',
					'base_cost',
					'setup_cost',
					'contract_term',
					'metric',
					'speed',
					'technology',
					'offpeak_start',
					'offpeak_end',
					'base_down_peak',
					'base_up_peak',
					'base_down_offpeak',
					'base_up_offpeak',
					'extra_down_peak',
					'extra_up_peak',
					'extra_down_offpeak',
					'extra_up_offpeak',
				]) as $key => $value)
					$oo->$key = $value;

				// Our boolean values
				foreach ($request->only(['active','extra_shaped','extra_charged']) as $key => $value)
					$oo->$key = ($value == 'on' ? 1 : 0);

				break;

			default:
				throw new \Exception('Unknown offering type:'.$request->offering_type);
		}

		$oo->save();

		return redirect()->back()
			->with('success','Saved');
	}

	/**
	 * Edit a supplier product
	 *
	 * @param Supplier $o
	 * @param int $id
	 * @param string $type
	 * @return \Illuminate\Contracts\Foundation\Application|\Illuminate\Contracts\View\Factory|\Illuminate\Contracts\View\View
	 */
	public function product_view(Supplier $o,int $id,string $type)
	{
		$oo = $o->detail->find($type,$id);
		$oo->load(['products.product.services.product.type']);

		return view('theme.backend.adminlte.supplier.product.addedit')
			->with('o',$o)
			->with('oo',$oo);
	}

	/**
	 * Return the form for a specific product type
	 *
	 * @param Request $request
	 * @param string $type
	 * @param int|null $id
	 * @return \Illuminate\Contracts\Foundation\Application|\Illuminate\Contracts\View\Factory|\Illuminate\Contracts\View\View
	 */
	public function product_view_type(Request $request,string $type,int $id=NULL)
	{
		$o = $id ? Supplier::offeringTypeClass($type)->findOrFail($id) : NULL;

		if ($request->old)
			$request->session()->flashInput($request->old);

		if ($o)
			$o->load(['products.product.services']);

		return view('theme.backend.adminlte.supplier.product.widget.'.$type)
			->with('o',$id ? $o : NULL)
			->withErrors($request->errors);
	}

	/**
	 * View a supplier.
	 *
	 * @param Supplier|null $o
	 * @return \Illuminate\Contracts\Foundation\Application|\Illuminate\Contracts\View\Factory|\Illuminate\Contracts\View\View
	 */
	public function view(?Supplier $o)
	{
		$this->middleware(['auth','wholesaler']);

		return view('theme.backend.adminlte.supplier.details')
			->with('o',$o);
	}
}