<?php
defined('BASEPATH') OR exit('No direct script access allowed');

class Tareas extends MY_Controller
{
	public function __construct()
	{
		parent::__construct();
		$this->load->model('Tasks_model');
		$this->Tasks_model->run_migration();
	}

	public function index()
	{
		$this->require_permission('tareas.view');
		$this->Tasks_model->sync_due_assignments();
		$auth_user = $this->get_auth_user();
		$employee_id = $auth_user ? (int) $auth_user['employee_id'] : 0;
		$status_filter = trim((string) $this->input->get('status'));
		if ($status_filter === '')
		{
			$status_filter = 'open';
		}

		$flash_message = '';
		$flash_error = '';
		if ($this->input->method(TRUE) === 'POST')
		{
			if ($this->input->post('action_type') === 'add_note')
			{
				$result = $this->Tasks_model->add_assignment_note(
					(int) $this->input->post('assignment_id'),
					$employee_id,
					(string) $this->input->post('completion_note')
				);
			}
			else
			{
				$result = $this->Tasks_model->complete_assignment(
					(int) $this->input->post('assignment_id'),
					$employee_id,
					(string) $this->input->post('completion_note')
				);
			}

			if (!empty($result['success']))
			{
				$flash_message = isset($result['message']) ? $result['message'] : 'Tarea completada.';
			}
			else
			{
				$flash_error = isset($result['message']) ? $result['message'] : 'No pudimos completar la tarea.';
			}
		}

		$assignments = $this->Tasks_model->get_assignments_for_employee($employee_id, $status_filter);
		$this->render('app/tareas', array(
			'page_title' => 'Tareas',
			'current_module' => 'tareas',
			'hide_main_menu' => TRUE,
			'status_filter' => $status_filter,
			'assignments' => $assignments,
			'flash_message' => $flash_message,
			'flash_error' => $flash_error,
		));
	}

	public function configuracion()
	{
		$this->require_permissions(array('configuracion.view', 'configuracion.tareas.view'));
		if ($this->input->method(TRUE) === 'POST')
		{
			$this->handle_configuracion_actions();
			return;
		}

		$active_tab = $this->normalize_config_tab($this->input->get('tab'));
		$rules = $this->decorate_rules($this->Tasks_model->get_rules());
		$this->render('app/configuracion_tareas', array(
			'page_title' => 'Tareas',
			'current_module' => 'configuracion',
			'hide_main_menu' => TRUE,
			'templates' => $this->Tasks_model->get_templates(),
			'rules' => $rules,
			'active_tab' => $active_tab,
			'flash_message' => $this->get_query_flash_message('success'),
			'flash_error' => $this->get_query_flash_message('error'),
		));
	}

	public function configuracion_seguimiento()
	{
		$this->require_permissions(array('configuracion.view', 'configuracion.tareas.view'));
		if ($this->input->method(TRUE) === 'POST')
		{
			$this->handle_tracking_actions();
			return;
		}

		$filters = array(
			'q' => trim((string) $this->input->get('q')),
			'employee_id' => (int) $this->input->get('employee_id'),
			'group_id' => (int) $this->input->get('group_id'),
			'status' => trim((string) $this->input->get('status')),
		);
		if ($filters['status'] === '')
		{
			$filters['status'] = 'all';
		}

		$employees = $this->Gala_read_model->get_employees_for_visor();
		$groups = $this->App_write_model->get_employee_groups(TRUE);
		$assignments = $this->decorate_assignment_tracking_rows(
			$this->Tasks_model->get_assignments_for_admin($filters),
			$employees,
			$groups,
			$filters['q']
		);

		$this->render('app/configuracion_tareas_tracking', array(
			'page_title' => 'Seguimiento de tareas',
			'current_module' => 'configuracion',
			'hide_main_menu' => TRUE,
			'filters' => $filters,
			'employees' => $employees,
			'groups' => $groups,
			'assignments' => $assignments,
			'summary' => $this->build_assignment_tracking_summary($assignments),
			'flash_message' => $this->get_query_flash_message('success'),
			'flash_error' => $this->get_query_flash_message('error'),
		));
	}

	public function cron_generar()
	{
		if (!$this->input->is_cli_request())
		{
			show_404();
		}

		$this->Tasks_model->run_migration();
		$this->Tasks_model->sync_due_assignments();
		echo 'Tareas sincronizadas correctamente.'.PHP_EOL;
	}

	public function actualizar_item()
	{
		$this->require_permission('tareas.view');
		$auth_user = $this->get_auth_user();
		$employee_id = $auth_user ? (int) $auth_user['employee_id'] : 0;
		$result = $this->Tasks_model->update_assignment_item_status(
			(int) $this->input->post('assignment_id'),
			(int) $this->input->post('assignment_item_id'),
			$employee_id,
			$this->input->post('is_completed') ? TRUE : FALSE
		);

		$this->output
			->set_content_type('application/json')
			->set_output(json_encode($result));
	}

	public function configuracion_plantilla_nueva()
	{
		$this->handle_template_form();
	}

	public function configuracion_plantilla_editar($template_id)
	{
		$this->handle_template_form((int) $template_id);
	}

	public function configuracion_regla_nueva()
	{
		$this->handle_rule_form();
	}

	public function configuracion_regla_editar($rule_id)
	{
		$this->handle_rule_form((int) $rule_id);
	}

	protected function handle_template_form($template_id = null)
	{
		$this->require_permissions(array('configuracion.view', 'configuracion.tareas.view'));
		$template = $template_id ? $this->Tasks_model->get_template((int) $template_id) : null;
		if ($template_id && !$template)
		{
			show_404();
		}

		$this->form_validation->set_rules('name', 'Nombre', 'trim|required');
		$this->form_validation->set_rules('description', 'Descripcion', 'trim');
		$this->form_validation->set_rules('items_text', 'Subtareas', 'trim');

		if ($this->input->method(TRUE) === 'POST' && $this->form_validation->run())
		{
			$saved_template_id = $this->Tasks_model->save_template(array(
				'name' => $this->input->post('name'),
				'description' => $this->input->post('description'),
				'is_active' => $this->input->post('is_active') ? 1 : 0,
			), $template_id);

			$this->Tasks_model->replace_template_items($saved_template_id, $this->parse_task_items_text($this->input->post('items_text')));
			redirect('configuracion/tareas');
		}

		$items_text = '';
		if ($template && !empty($template['assignable_items']))
		{
			$names = array();
			foreach ($template['assignable_items'] as $item)
			{
				$names[] = isset($item['name']) ? $item['name'] : '';
			}
			$items_text = implode(PHP_EOL, $names);
		}

		$this->render('app/configuracion_tarea_template_form', array(
			'page_title' => !empty($template['id']) ? 'Editar plantilla' : 'Nueva plantilla',
			'current_module' => 'configuracion',
			'hide_main_menu' => TRUE,
			'template' => $template,
			'items_text' => $items_text,
		));
	}

	protected function handle_rule_form($rule_id = null)
	{
		$this->require_permissions(array('configuracion.view', 'configuracion.tareas.view'));
		$rule = $rule_id ? $this->Tasks_model->get_rule((int) $rule_id) : null;
		if ($rule_id && !$rule)
		{
			show_404();
		}

		$templates = $this->Tasks_model->get_templates(TRUE);
		$special_dates = $this->Tasks_model->get_special_dates();
		$employees = $this->Gala_read_model->get_employees_for_visor();
		$groups = $this->App_write_model->get_employee_groups(TRUE);
		$selected_assignment_mode = (string) $this->input->post('assignment_mode');
		if ($selected_assignment_mode === '' && !empty($rule['assignment_mode']))
		{
			$selected_assignment_mode = (string) $rule['assignment_mode'];
		}
		$selected_recurrence = (string) $this->input->post('recurrence_type');
		if ($selected_recurrence === '' && !empty($rule['recurrence_type']))
		{
			$selected_recurrence = (string) $rule['recurrence_type'];
		}

		$this->form_validation->set_rules('template_id', 'Plantilla', 'required|integer');
		$this->form_validation->set_rules('title', 'Nombre de la tarea', 'trim');
		$this->form_validation->set_rules('assignment_mode', 'Modo de asignacion', 'required');
		$this->form_validation->set_rules('recurrence_type', 'Recurrencia', 'required');
		if ($selected_assignment_mode === 'group')
		{
			$this->form_validation->set_rules('group_id', 'Grupo', 'required|integer');
		}
		else
		{
			$this->form_validation->set_rules('employee_id', 'Empleado', 'required|integer');
		}

		if ($selected_recurrence === 'special_date')
		{
			$this->form_validation->set_rules('special_date_code', 'Fecha especial', 'required');
			$this->form_validation->set_rules('special_date_lead_days', 'Dias de anticipacion', 'trim|integer');
		}
		elseif ($selected_recurrence === 'one_time')
		{
			$this->form_validation->set_rules('one_time_date', 'Fecha unica', 'required');
		}
		else
		{
			$this->form_validation->set_rules('starts_on', 'Fecha base de inicio', 'required');
		}

		if ($this->input->method(TRUE) === 'POST' && $this->form_validation->run())
		{
			$saved_rule_id = $this->Tasks_model->save_rule(array(
				'title' => $this->input->post('title'),
				'template_id' => $this->input->post('template_id'),
				'assignment_mode' => $this->input->post('assignment_mode'),
				'employee_id' => $this->input->post('employee_id'),
				'group_id' => $this->input->post('group_id'),
				'group_distribution_mode' => $this->input->post('group_distribution_mode'),
				'distribution_algorithm' => $this->input->post('distribution_algorithm'),
				'recurrence_type' => $this->input->post('recurrence_type'),
				'special_date_code' => $this->input->post('special_date_code'),
				'special_date_lead_days' => $this->input->post('special_date_lead_days'),
				'one_time_date' => $this->input->post('one_time_date'),
				'starts_on' => $this->input->post('starts_on'),
				'ends_on' => $this->input->post('ends_on'),
				'requires_note_on_complete' => $this->input->post('requires_note_on_complete') ? 1 : 0,
				'is_active' => $this->input->post('is_active') ? 1 : 0,
			), $rule_id);

			$this->Tasks_model->replace_rule_excluded_items($saved_rule_id, (array) $this->input->post('ignored_item_ids'));
			redirect('configuracion/tareas');
		}

		$this->render('app/configuracion_tarea_rule_form', array(
			'page_title' => !empty($rule['id']) ? 'Editar tarea' : 'Nueva tarea',
			'current_module' => 'configuracion',
			'hide_main_menu' => TRUE,
			'rule' => $rule,
			'templates' => $templates,
			'employees' => $employees,
			'groups' => $groups,
			'special_dates' => $special_dates,
			'ignored_item_ids' => !empty($rule['excluded_item_ids']) ? array_map('intval', $rule['excluded_item_ids']) : array(),
		));
	}

	protected function parse_task_items_text($text)
	{
		$text = str_replace("\r\n", "\n", (string) $text);
		$lines = explode("\n", $text);
		$items = array();
		foreach ($lines as $line)
		{
			$raw_line = rtrim((string) $line);
			if (trim($raw_line) === '')
			{
				continue;
			}

			$name = preg_replace('/^\s*-\s*/', '', trim($raw_line));
			if ($name !== '')
			{
				$key = 'item:'.$name.':'.count($items);
				$items[$key] = array(
					'name' => $name,
					'level' => 0,
				);
			}
		}

		return array_values($items);
	}

	protected function decorate_rules($rules)
	{
		$employees_index = $this->index_rows($this->Gala_read_model->get_employees_for_visor(), 'person_id');
		$groups_index = $this->index_rows($this->App_write_model->get_employee_groups(TRUE), 'id');
		foreach ($rules as &$rule)
		{
			$rule['template_name'] = !empty($rule['template']['name']) ? $rule['template']['name'] : 'Plantilla';
			$rule['display_name'] = !empty($rule['title']) ? $rule['title'] : $rule['template_name'];
			$rule['target_label'] = 'Sin destino';
			if (isset($rule['assignment_mode']) && $rule['assignment_mode'] === 'employee' && !empty($rule['employee_id']) && isset($employees_index[(int) $rule['employee_id']]))
			{
				$rule['target_label'] = 'Empleado: '.$employees_index[(int) $rule['employee_id']]['full_name'];
			}
			elseif (!empty($rule['group_id']) && isset($groups_index[(int) $rule['group_id']]))
			{
				$rule['target_label'] = 'Grupo: '.$groups_index[(int) $rule['group_id']]['name'];
			}

			$rule['recurrence_label'] = $this->build_recurrence_label($rule);
			$rule['next_due_date'] = $this->Tasks_model->get_next_due_date_for_rule($rule);
		}
		unset($rule);

		return $rules;
	}

	protected function build_recurrence_label($rule)
	{
		switch (isset($rule['recurrence_type']) ? $rule['recurrence_type'] : 'one_time')
		{
			case 'daily':
				return 'Diaria';
			case 'weekly':
				return 'Semanal';
			case 'monthly':
				return 'Mensual';
			case 'quarterly':
				return 'Trimestral';
			case 'semiannual':
				return 'Semestral';
			case 'annual':
				return 'Anual';
			case 'special_date':
				$label = !empty($rule['special_date']['name']) ? 'Fecha especial: '.$rule['special_date']['name'] : 'Fecha especial';
				if (!empty($rule['special_date_lead_days']))
				{
					$label .= ' ('.(int) $rule['special_date_lead_days'].' dias antes)';
				}
				return $label;
			case 'one_time':
			default:
				return !empty($rule['one_time_date']) ? 'Unica: '.$rule['one_time_date'] : 'Unica';
		}
	}

	protected function index_rows($rows, $key)
	{
		$index = array();
		foreach ((array) $rows as $row)
		{
			if (isset($row[$key]))
			{
				$index[(int) $row[$key]] = $row;
			}
		}

		return $index;
	}

	protected function decorate_assignment_tracking_rows($assignments, $employees, $groups, $search = '')
	{
		$employees_index = $this->index_rows($employees, 'person_id');
		$groups_index = $this->index_rows($groups, 'id');
		$decorated = array();
		$search = trim((string) $search);

		foreach ((array) $assignments as $assignment)
		{
			$employee_id = isset($assignment['employee_id']) ? (int) $assignment['employee_id'] : 0;
			$group_id = isset($assignment['rule_group_id']) ? (int) $assignment['rule_group_id'] : 0;
			$employee_name = isset($employees_index[$employee_id]['full_name']) ? $employees_index[$employee_id]['full_name'] : 'Empleado';
			$group_name = ($group_id > 0 && isset($groups_index[$group_id]['name'])) ? $groups_index[$group_id]['name'] : '';

			if ($search !== '' && !$this->matches_tracking_search(
				$employee_name.' '.(isset($assignment['title']) ? $assignment['title'] : '').' '.$group_name,
				$search
			))
			{
				continue;
			}

			$assignment['employee_name'] = $employee_name;
			$assignment['group_name'] = $group_name;
			$assignment['notes_count'] = !empty($assignment['notes']) ? count($assignment['notes']) : 0;
			$decorated[] = $assignment;
		}

		return $decorated;
	}

	protected function build_assignment_tracking_summary($assignments)
	{
		$summary = array(
			'total' => 0,
			'pending' => 0,
			'in_progress' => 0,
			'overdue' => 0,
			'completed' => 0,
		);

		foreach ((array) $assignments as $assignment)
		{
			$summary['total']++;
			$status = isset($assignment['status']) ? (string) $assignment['status'] : 'pending';
			if (!isset($summary[$status]))
			{
				$summary[$status] = 0;
			}
			$summary[$status]++;
		}

		return $summary;
	}

	protected function handle_configuracion_actions()
	{
		$action_type = trim((string) $this->input->post('action_type'));
		$active_tab = $this->normalize_config_tab($this->input->post('tab'));
		$result = array('success' => FALSE, 'message' => 'Accion no valida.');
		if ($action_type === 'toggle_template')
		{
			$result = $this->Tasks_model->set_template_active(
				(int) $this->input->post('template_id'),
				$this->input->post('is_active') ? TRUE : FALSE
			);
		}
		elseif ($action_type === 'toggle_rule')
		{
			$result = $this->Tasks_model->set_rule_active(
				(int) $this->input->post('rule_id'),
				$this->input->post('is_active') ? TRUE : FALSE
			);
		}

		$this->redirect_with_message(
			'configuracion/tareas',
			array('tab' => $active_tab),
			isset($result['message']) ? $result['message'] : 'No pudimos actualizar el registro.',
			!empty($result['success']) ? 'success' : 'error'
		);
	}

	protected function handle_tracking_actions()
	{
		$filters = array(
			'q' => trim((string) $this->input->post('q')),
			'employee_id' => (int) $this->input->post('employee_id'),
			'group_id' => (int) $this->input->post('group_id'),
			'status' => trim((string) $this->input->post('status')),
		);
		if ($filters['status'] === '')
		{
			$filters['status'] = 'all';
		}

		$action_type = trim((string) $this->input->post('action_type'));
		$result = array('success' => FALSE, 'message' => 'Accion no valida.');
		if ($action_type === 'reactivate_assignment')
		{
			$result = $this->Tasks_model->reactivate_assignment((int) $this->input->post('assignment_id'));
		}

		$this->redirect_with_message(
			'configuracion/tareas/seguimiento',
			$filters,
			isset($result['message']) ? $result['message'] : 'No pudimos actualizar la tarea.',
			!empty($result['success']) ? 'success' : 'error'
		);
	}

	protected function redirect_with_message($path, $params, $message, $type)
	{
		$params = is_array($params) ? $params : array();
		$params['task_message'] = (string) $message;
		$params['task_message_type'] = $type === 'error' ? 'error' : 'success';
		redirect($this->build_url($path, $params));
	}

	protected function get_query_flash_message($expected_type)
	{
		$type = trim((string) $this->input->get('task_message_type'));
		if ($type !== $expected_type)
		{
			return '';
		}

		return trim((string) $this->input->get('task_message'));
	}

	protected function build_url($path, $params = array())
	{
		$clean_params = array();
		foreach ((array) $params as $key => $value)
		{
			if ($value === null || $value === '' || $value === 0 || $value === '0')
			{
				if ($key === 'status' && $value === '0')
				{
					continue;
				}
				if ($key !== 'status')
				{
					continue;
				}
			}
			$clean_params[$key] = $value;
		}

		$url = site_url($path);
		if (empty($clean_params))
		{
			return $url;
		}

		return $url.'?'.http_build_query($clean_params);
	}

	protected function matches_tracking_search($haystack, $needle)
	{
		$haystack = (string) $haystack;
		$needle = trim((string) $needle);
		if ($needle === '')
		{
			return TRUE;
		}

		if (function_exists('mb_stripos'))
		{
			return mb_stripos($haystack, $needle, 0, 'UTF-8') !== FALSE;
		}

		return stripos($haystack, $needle) !== FALSE;
	}

	protected function normalize_config_tab($tab)
	{
		$tab = trim((string) $tab);
		return $tab === 'plantillas' ? 'plantillas' : 'reglas';
	}
}
