<?php defined('SYSPATH') or die('No direct access allowed.');

/**
 * This class provides OSB service admin capabilities.
 *
 * @package    OSB
 * @subpackage Service
 * @category   Controllers/Admin
 * @author     Deon George
 * @copyright  (c) 2010 Open Source Billing
 * @license    http://dev.osbill.net/license.html
 */
class Controller_Admin_Service extends Controller_TemplateDefault {
	protected $control = array('Services'=>'services');

	public $secure_actions = array(
		'listbycheckout'=>TRUE,
		'listadslservices'=>TRUE,
		'listhspaservices'=>TRUE,
	);

	/**
	 * List all services by their default checkout method
	 */
	public function action_listbycheckout() {
		// @todo need to add the DB prefix here
		$services = DB::query(Database::SELECT,'
SELECT c.id AS cid,c.name as checkout_plugin_name,s.id AS sid,a.company,a.first_name,a.last_name,a.id as aid
FROM ab_service s LEFT JOIN ab_account_billing ab ON (s.account_billing_id=ab.id) LEFT JOIN ab_checkout c ON (ab.checkout_plugin_id=c.id),ab_account a, ab_account_group ag
WHERE s.active=1 AND s.price > 0 AND s.account_id=a.id AND a.id=ag.account_id AND ((s.account_billing_id IS NOT NULL AND ag.group_id IS NOT NULL) OR (a.id=ag.account_id and ag.group_id=1003))
ORDER BY c.id,s.recur_schedule,c.name,a.company,a.last_name,a.first_name
			')
			->execute();

		// @todo If no items, show a nice message. This is not correct for ORM.
		if (! count($services)) {
			echo Kohana::debug('No services with account_billing');
			die();
		}

		$last_checkout = '';
		$last_account = '';
		$i = 0;
		$sc = $st = 0;
		$output = '<table class="box-left">';
		foreach ($services as $service) {
			$so = ORM::factory('service',$service['sid']);
			$si = $so->account_id.$so->recur_schedule;

			if (($si != $last_account) AND $last_account) {
				if ($sc > 1)
					$output .= View::factory('service/list/bycheckout_subtotal')
						->set('subtotal',Currency::display($st))
						->set('i',$i++%2);
				$sc = $st = 0;
			}

			if (($service['cid'] != $last_checkout) OR (! is_null($last_checkout) AND ! $last_checkout)) {
				$output .= View::factory('service/list/bycheckout_header')
					->set('checkout_name',$service['checkout_plugin_name'])
					->set('last_checkout',$last_checkout);
			}

			$last_checkout = $service['cid'];
			$last_account = $si;
			// @todo This rounding should be a system default
			$st += round($so->price+$so->tax(),2);
			$sc++;

			$output .= View::factory('service/list/bycheckout_body')
				->set('service',$so)
				->set('i',$i++%2);
		}

		// Last subtotal
		if ($sc > 1)
			$output .= View::factory('service/list/bycheckout_subtotal')
				->set('subtotal',$st)
				->set('i',$i++%2);

		$output .= '</table>';

		Block::add(array(
			'title'=>_('List all Services by Default Payment Method'),
			'body'=>$output,
			));

		Style::add(array(
			'type'=>'file',
			'data'=>'css/list.css',
		));

		$this->template->content = Block::factory();
	}

	//@todo this should really be in a different class, since adsl wont be part of the main app
	public function action_listadslservices() {
		// @todo need to add the DB prefix here
		$services = DB::query(Database::SELECT,'
SELECT A.service_id
FROM ab_service__adsl A,ab_service B,ab_account C,ab_service D,ab_product E
WHERE B.active=1 AND A.service_id=B.id AND A.site_id=B.site_id
AND B.account_id=C.id AND B.site_id=C.site_id
AND A.service_id=D.id AND A.site_id=D.site_id
AND D.product_id=E.id AND D.site_id=E.site_id
AND E.sku like "%ADSL%"
ORDER BY C.last_name,B.account_id,A.service_number
			')
			->execute();

		// @todo If no items, show a nice message. This is not correct for ORM.
		if (! count($services)) {
			echo Kohana::debug('No services for ADSL');
			die();
		}

		$last_account = '';
		$i = 0;
		$output = '<table class="box-left">';
		foreach ($services as $service) {
			$so = ORM::factory('service',$service['service_id']);

			if ($last_account != $so->account_id) {
				if ($i)
					$output .= '<tr><td colspan="10">&nbsp;</td></tr>';

				$output .= View::factory('service/list/adslservices_header')
					->set('service',$so);

				$last_account = $so->account_id;
			}

			$output .= View::factory('service/list/adslservices_body')
				->set('service',$so)
				->set('i',$i++%2);
		}
		$output .= '</table>';

		// Chart the traffic for the last 12 months.
		// @todo need to add the DB prefix here
		$traffic = DB::query(Database::SELECT,sprintf('
SELECT DATE_FORMAT(DATE,"%%y-%%m") AS MONTH,SID,MAX(NUM) AS NUM,SUM(DOWN_PEAK) AS DOWN_PEAK,SUM(IFNULL(DOWN_OFFPEAK,0)+IFNULL(PEER,0)+IFNULL(INTERNAL,0)) AS DOWN_OFFPEAK
FROM ab_view_traffic_adsl_daily
WHERE SID in (%s) AND DATE>"%s"
GROUP BY DATE_FORMAT(DATE,"%%Y-%%m"),SID
			','1,2',date('Y-m',time()-365*86400)))
			->execute();

		$peak = $offpeak = $services = array();

		foreach ($traffic as $a => $v) {
			$peak[$v['SID']]['Peak'][$v['MONTH']] = $v['DOWN_PEAK'];
			$peak[$v['SID']]['OffPeak'][$v['MONTH']] = $v['DOWN_OFFPEAK'];
			$peak[$v['SID']]['Services'][$v['MONTH']] = $v['NUM'];
		}

		$google = GoogleChart::factory('vertical_bar');
		$google->title = sprintf('ADSL traffic as at %s',date('Y-m-d',strtotime('yesterday')));
		$google->series(array(
			'title'=>array('Exetel-Peak','Exetel-Offpeak'),
			'axis'=>'x',
			'data'=>array('Exetel-Peak'=>$peak[1]['Peak'],'Exetel-OffPeak'=>$peak[1]['OffPeak'])));
		$google->series(array(
			'title'=>array('People-Peak','People-Offpeak'),
			'axis'=>'x',
			'data'=>array('People-Peak'=>$peak[2]['Peak'],'People-OffPeak'=>$peak[2]['OffPeak'])));
		$google->series(array(
			'title'=>'Exetel-Services',
			'axis'=>'r',
			'data'=>array('Exetel-Services'=>$peak[1]['Services'])));
		$google->series(array(
			'title'=>'People-Services',
			'axis'=>'r',
			'data'=>array('People-Services'=>$peak[2]['Services'])));

		Block::add(array(
			'body'=>$google,
			));

		Block::add(array(
			'title'=>_('List all ADSL Services'),
			'body'=>$output,
			));

		Style::add(array(
			'type'=>'file',
			'data'=>'css/list.css',
		));

		$this->template->content = Block::factory();
	}

	public function action_listhspaservices() {
		// @todo need to add the DB prefix here
		$services = DB::query(Database::SELECT,'
SELECT A.service_id
FROM ab_service__adsl A,ab_service B,ab_account C,ab_service D,ab_product E
WHERE B.active=1 AND A.service_id=B.id AND A.site_id=B.site_id
AND B.account_id=C.id AND B.site_id=C.site_id
AND A.service_id=D.id AND A.site_id=D.site_id
AND D.product_id=E.id AND D.site_id=E.site_id
AND E.sku like "%HSPA%"
ORDER BY C.last_name,B.account_id,A.service_number
			')
			->execute();

		// @todo If no items, show a nice message. This is not correct for ORM.
		if (! count($services)) {
			echo Kohana::debug('No services for HSPA');
			die();
		}

		$last_account = '';
		$i = 0;
		$output = '<table class="box-left">';
		foreach ($services as $service) {
			$so = ORM::factory('service',$service['service_id']);

			if ($last_account != $so->account_id) {
				if ($i)
					$output .= '<tr><td colspan="10">&nbsp;</td></tr>';

				$output .= View::factory('service/list/adslservices_header')
					->set('service',$so);

				$last_account = $so->account_id;
			}

			$output .= View::factory('service/list/adslservices_body')
				->set('service',$so)
				->set('i',$i++%2);
		}
		$output .= '</table>';

		// Chart the traffic for the last 12 months.
		// @todo need to add the DB prefix here
		$traffic = DB::query(Database::SELECT,sprintf('
SELECT DATE_FORMAT(DATE,"%%y-%%m") AS MONTH,SID,MAX(NUM) AS NUM,SUM(DOWN_PEAK)*1000 AS DOWN_PEAK,SUM(IFNULL(DOWN_OFFPEAK,0)+IFNULL(PEER,0)+IFNULL(INTERNAL,0))*1000 AS DOWN_OFFPEAK
FROM ab_view_traffic_adsl_daily
WHERE SID=%s AND DATE>"%s"
GROUP BY DATE_FORMAT(DATE,"%%Y-%%m"),SID
			',3,date('Y-m',time()-365*86400)))
			->execute();

		$peak = $offpeak = $services = array();

		foreach ($traffic as $a => $v) {
			$peak['Peak'][$v['MONTH']] = $v['DOWN_PEAK'];
			$peak['OffPeak'][$v['MONTH']] = $v['DOWN_OFFPEAK'];
			$peak['Services'][$v['MONTH']] = $v['NUM'];
		}

		$google = GoogleChart::factory('vertical_bar');
		$google->title = sprintf('HSPA traffic as at %s',date('Y-m-d',strtotime('yesterday')));
		$google->series(array('title'=>array('Peak','Offpeak'),'axis'=>'x','data'=>array('Peak'=>$peak['Peak'],'OffPeak'=>$peak['OffPeak'])));
		$google->series(array('title'=>'Services','axis'=>'r','data'=>array('Services'=>$peak['Services'])));

		Block::add(array(
			'body'=>$google,
			));

		Block::add(array(
			'title'=>_('List all HSPA Services'),
			'body'=>$output,
			));

		Style::add(array(
			'type'=>'file',
			'data'=>'css/list.css',
		));

		$this->template->content = Block::factory();
	}

	/**
	 * Reconcile billing for an ADSL supplier
	 *
	 * @todo this should really be in a different class, since adsl wont be part of the main app
	 */
	public function action_listadslbilling($id) {
		$aso = ORM::factory('adsl_supplier',$id);

		// Process upload
		// @todo This should be separated out by supplier in case each supplier has a different format
		$files = Validate::factory($_FILES);
		$files->rules('csv',array(
			'Upload::valid'=>array(),
			'Upload::not_empty'=>array(),
			'Upload::type'=>array('Upload::type' => array('csv')),
			'Upload::size'=>array('10M'))
		);

		if ($files->check()) {
			foreach ($files as $file) {
				$csv = $this->process($file);
			}
		}

		// @todo add a display if there are no items
		$i = $j = 0;
		$total = 0;
		$summary = '';
		$output = View::factory('service/list/adslbilling_head');
		$output .= '<table class="box-left">';
		foreach ($aso->services(TRUE) as $so) {
			// Reset our uploaded data
			$uploaded = array();
			// If our uploaded file has some cost data.
			if (! empty($csv[$so->service_adsl->service_number])) {
				$uploaded['amount'] = 
					(empty($csv[$so->service_adsl->service_number]['cost']) ? 0 : $csv[$so->service_adsl->service_number]['cost']) +
					(empty($csv[$so->service_adsl->service_number]['credit']) ? 0 : $csv[$so->service_adsl->service_number]['credit']);

				// Record the the exception if the cost is not expected
				if (round($so->service_adsl->adsl_plan->adsl_supplier_plan->base_cost+$so->service_adsl->adsl_plan->adsl_supplier_plan->tax(),2) != $uploaded['amount']) {
					$summary .= View::factory('service/list/adslbilling_summary')
						->set('service',$so)
						->set('amount',$uploaded['amount'])
						->set('i',$j++%2);

					$uploaded['checked'] = '';
				} else {
					$uploaded['checked'] = 'checked="checked"';
				}

				unset($csv[$so->service_adsl->service_number]);

			} else {
				$uploaded['checked'] = '';
				$uploaded['amount'] = 0;
			}
			$total += $uploaded['amount'];

			$output .= View::factory('service/list/adslbilling_body')
				->set('service',$so)
				->set('checked',$uploaded['checked'])
				->set('amount',$uploaded['amount'])
				->set('adsl',$so->service_adsl)
				->set('i',$i++%2);
		}

		$output .= View::factory('service/list/adslbilling_foot')
			->set('total',$total);

		$output .= '</table>';

		// Summary Report of remaining CSV items.
		if (! empty($csv))
			foreach ($csv as $service => $item) {
				$summary .= View::factory('service/list/adslbilling_summary_exception')
					->set('service',$service)
					->set('item',$item)
					->set('i',$j++%2);
			}

		$output .= Form::open(NULL,array('enctype'=>'multipart/form-data'));
		$output .= '<div>';
		$output .= Form::file('csv');
		$output .= Form::submit('submit','upload');
		$output .= '</div>';
		$output .= Form::close();

		Block::add(array(
			'title'=>_('ADSL Services'),
			'body'=>$output,
			));

		if ($summary)
			Block::add(array(
				'title'=>_('Exception Charges'),
				'body'=>'<table class="box-left">'.$summary.'</table>',
				));

		Style::add(array(
			'type'=>'file',
			'data'=>'css/list.css',
		));

		$this->template->content = Block::factory();
	}

	private function process(array $file) {
		$data = file_get_contents($file['tmp_name']);

		if (! $data)
			return;

		$start = $end = FALSE;
		$return = array();
		foreach (preg_split("/\n/",$data) as $line) {
			// Items start after "Item ID"
			if (! $start && preg_match('/^Item ID,/',$line)) {
				$start = true;
				continue;
			// Items end after "Subtotal"
			} elseif ($start && ! $end && preg_match('/^Subtotal:,/',$line)) {
				$end = true;
				continue;
			// If we havent started or not ended, continue
			} elseif (! $start || $end) {
				continue;
			}

			list($id,$ref,$unknown,$linedata,$q,$cost,$total) = explode(',',$line);

			// Extract the phone number from the $linedata
			@list($service,$description) = explode(':',(preg_replace('/([0-9]+)\s+-\s+(.*)$/',"$1:$2",$linedata)));

			// If the description says Monthly Charge, we know its the monthly fee.
			if (preg_match('/^Monthly Charge/',$description))
				$return[$service]['cost'] = preg_replace('/\$/','',$total);
			// If the description says VISP credit, we know this is commission.
			elseif (preg_match('/^VISP Credit/',$description))
				$return[$service]['credit'] = preg_replace('/\$/','',$total);
			// If the description says Excess, we know this is commission.
			elseif (preg_match('/^Excess usage/',$description))
				$return[$service]['excess'] = preg_replace('/\$/','',$total);
			else
				$return[$service]['info'] = $line;
		}

		return $return;
	}
}
?>