#!/usr/bin/php
<?php

require_once('/usr/share/ombutel/www/includes/cli.php');

use ombutel\db;
use ombutel\external_resource;
use ombutel\timezone;

if (is_null($cfg = parse_args())) {
	echo "Usage: {$argv[0]} --[hours/days/weeks/months/years/num] N [-d] [-D] [-t] [-T]\n".
		"Delete CDR records older than specified time period.\n".
		"  --hours     Delete records older than N hours.\n".
		"  --days      Delete records older than N days.\n".
		"  --weeks     Delete records older than N weeks.\n".
		"  --months    Delete records older than N months.\n".
		"  --years     Delete records older than N years.\n".
		"  --num       Delete all but the last N records.\n".
		"  -d          Also delete Local audio recordings.\n".
		"  -D          Also delete External Storage audio recordings.\n".
		"  -t          Also delete Local transcription files.\n".
		"  -T          Also delete External Storage transcriptions.\n".
		"\n";
} else {
	prune($cfg);
}

function parse_args() {
	global $argc, $argv;

	$unit = null;
	$amount = null;
	$delete_recordings = null;
	$delete_external_recordings = null;
	$delete_transcriptions = null;
	$delete_external_transcriptions = null;

	for ($i = 1; $i < $argc; ++$i) {
		if (is_null($unit) && preg_match('/^--(hours|days|weeks|months|years|num)$/', $argv[$i])) {
			$unit = substr($argv[$i], 2);
			if (++$i < $argc && preg_match('/^\d+$/', $argv[$i])) {
				$amount = intval($argv[$i]);
			} else {
				return null;
			}
		} else if (is_null($delete_recordings) && $argv[$i] == '-d') {
			$delete_recordings = true;
		} else if (is_null($delete_external_recordings) && $argv[$i] == '-D') {
			$delete_external_recordings = true;
		} else if (is_null($delete_transcriptions) && $argv[$i] == '-t') {
			$delete_transcriptions = true;
		} else if (is_null($delete_external_transcriptions) && $argv[$i] == '-T') {
			$delete_external_transcriptions = true;
		} else {
			return null;
		}
	}

	if (!is_null($unit) && !is_null($amount)) {
		return (object) [
			'unit' => $unit,
			'amount' => $amount,
			'delete_recordings' => !is_null($delete_recordings),
			'delete_external_recordings' => !is_null($delete_external_recordings),
			'delete_transcriptions' => !is_null($delete_transcriptions),
			'delete_external_transcriptions' => !is_null($delete_external_transcriptions),
		];
	}
}

function prune($cfg) {
	if ($cfg->amount > 0) {
		switch ($cfg->unit) {
			case 'hours': return prune_interval('HOUR', $cfg);
			case 'days': return prune_interval('DAY', $cfg);
			case 'weeks': return prune_interval('WEEK', $cfg);
			case 'months': return prune_interval('MONTH', $cfg);
			case 'years': return prune_interval('YEAR', $cfg);
			case 'num': return prune_exact($cfg);
		}
	}
}

function prune_interval($unit, $cfg) {
	db::begin_transaction();
	$range = "`calldate` < date_sub(now(), interval {$cfg->amount} {$unit})";
	if ($cfg->delete_recordings) {
		delete_local_recordings($range);
	}
	if ($cfg->delete_external_recordings) {
		delete_external_storage_recordings($range);
	}
	if ($cfg->delete_transcriptions) {
		delete_local_transcriptions($range);
	}
	if ($cfg->delete_external_transcriptions) {
		delete_external_storage_transcriptions($range);
	}
	if ($cfg->delete_transcriptions || $cfg->delete_external_transcriptions) {
		db::query("delete t from `asterisk`.`tcdr` t
			join `asterisk`.`cdr` c on c.`uniqueid` = t.`uniqueid`
			where c.{$range}");
	}
	db::query("delete from `asterisk`.`cdr` where {$range}");
	db::commit();
}

function prune_exact($cfg) {
	db::begin_transaction();
	$range = "`cdr_id` <= (
			select `cdr_id` from (
				select `cdr_id`
				from `asterisk`.`cdr`
				order by `cdr_id`
				desc limit 1 offset {$cfg->amount}
			) t
		)";
	if ($cfg->delete_recordings) {
		delete_local_recordings($range);
	}
	if ($cfg->delete_external_recordings) {
		delete_external_storage_recordings($range);
	}
	if ($cfg->delete_transcriptions) {
		delete_local_transcriptions($range);
	}
	if ($cfg->delete_external_transcriptions) {
		delete_external_storage_transcriptions($range);
	}
	db::query("delete from `asterisk`.`cdr`where {$range}");
	db::commit();
}

function delete_local_recordings($range){
	$result = db::query(
		"select `recfile` from `asterisk`.`cdr`
		where {$range} and `recfile` like '/%'");
	foreach ($result as $row) {
		@unlink($row->recfile);
	}
}

function delete_external_storage_recordings($range){
	$result = db::query(
		"select `recfile_cloud` from `asterisk`.`cdr`
		where {$range} and `recfile_cloud` is not null");

	foreach ($result as $row) {
		$timezone = new DateTimeZone(timezone::current()->identifier); // get current time zone
		$datetime_now = (new DateTime("now", $timezone))->format("Y-m-d H:i:s"); // get current date time in specific format
		if (count($parts = explode(",", $row->recfile_cloud, 2)) > 1) {
			list($resource_id, $object_name) = $parts;
			if ($resource = external_resource::get($resource_id)) {
				try{
					@$resource->delete_file($object_name);
				} catch(Exception $e){
					file_put_contents("/var/log/cpbx/cdr_cleanup.log", "{$datetime_now} E: Failed deleting \"{$object_name}\" from External Storage Provider \"{$resource->name}\"\n", FILE_APPEND);
				}

			} else {
				file_put_contents("/var/log/cpbx/cdr_cleanup.log", "{$datetime_now} E: The External Storage Provider for the CDR Record referring \"{$object_name}\" no longer exists\n", FILE_APPEND);
			}
		}
	}
}

function delete_local_transcriptions($range){
	$result = db::query(
		"select t.`transfile` from `asterisk`.`cdr` c
		join `asterisk`.`tcdr` t on c.`uniqueid` = t.`uniqueid`
		where c.{$range} and t.`transfile` != ''");
	foreach ($result as $row) {
		@unlink($row->transfile);
	}
}

function delete_external_storage_transcriptions($range){
	$result = db::query(
		"select t.`transfile_cloud` from `asterisk`.`cdr` c
		join `asterisk`.`tcdr` t on c.`uniqueid` = t.`uniqueid`
		where c.{$range} and t.`transfile_cloud` != ''");

	foreach ($result as $row) {
		$timezone = new DateTimeZone(timezone::current()->identifier);
		$datetime_now = (new DateTime("now", $timezone))->format("Y-m-d H:i:s");
		if (count($parts = explode(",", $row->transfile_cloud, 2)) > 1) {
			list($resource_id, $object_name) = $parts;
			if ($resource = external_resource::get($resource_id)) {
				try{
					@$resource->delete_file($object_name);
				} catch(Exception $e){
					file_put_contents("/var/log/cpbx/cdr_cleanup.log", "{$datetime_now} E: Failed deleting transcription \"{$object_name}\" from External Storage Provider \"{$resource->name}\"\n", FILE_APPEND);
				}

			} else {
				file_put_contents("/var/log/cpbx/cdr_cleanup.log", "{$datetime_now} E: The External Storage Provider for the transcription \"{$object_name}\" no longer exists\n", FILE_APPEND);
			}
		}
	}
}
?>
