<?php
defined('BASEPATH') OR exit('No direct script access allowed');
require_once APPPATH.'third_party/FPDF/fpdf.php';
require_once APPPATH . 'third_party/FPDI/src/autoload.php';
use setasign\Fpdi\Fpdi;

class Company extends CI_Controller {

	/**
	 * Index Page for this controller.
	 *
	 * Maps to the following URL
	 * 		http://example.com/index.php/welcome
	 *	- or -
	 * 		http://example.com/index.php/welcome/index
	 *	- or -
	 * Since this controller is set as the default controller in
	 * config/routes.php, it's displayed at http://example.com/
	 *
	 * So any other public methods not prefixed with an underscore will
	 * map to /index.php/welcome/<method_name>
	 * @see https://codeigniter.com/userguide3/general/urls.html
	 */
	public function __construct()
    {
        parent::__construct();
        $this->load->database();
        $this->load->helper(['url', 'form', 'download','date']);
        $this->load->library(['session', 'upload','zip']);
        $this->load->model('Company_model');
		
        // Ensure Composer autoload is loaded
        require_once APPPATH.'third_party/FPDI/src/Fpdi.php'; // FPDI
    } 
	public function index()
	{
		redirect('company/companies');
	}
	
	public function companies()
    {   
		$this->session->set_userdata('menu','company');
		$login_id = $this->session->userdata('id');
		$role_id = $this->session->userdata('role_id');
		if($login_id=='') {
			redirect('login');
		}
		
		// Only Super Admin can access Company master
		if (!is_super_admin()) {
			$this->session->set_flashdata('message_type', 'error');
			$this->session->set_flashdata('message_name', 'Access denied. Only Super Admin can manage companies.');
			redirect('dashboard/dashboard');
		}
		
		// Permission check - view companies
		require_permission('company.view');
		
		// Get allowed companies based on role
		$allowed_companies = get_allowed_companies();
		
		if (is_super_admin()) {
			// Super Admin sees all companies
			$this->db->select('*')
				->from('company')
				->order_by('id', 'ASC');
		} else {
			// Admin and User see only assigned companies
			if (!empty($allowed_companies)) {
				$this->db->select('*')
					->from('company')
					->where_in('id', $allowed_companies)
					->order_by('id', 'ASC');
			} else {
				// No companies assigned
				$this->db->select('*')
					->from('company')
					->where('id', 0) // Return empty
					->order_by('id', 'ASC');
			}
		}

		$query = $this->db->get();
		$business_data = $query->result_array();
		
		$sql1="select * from authority where status='1' order by id asc ";  
		
		$authority_query = $this->db->query($sql1);
		$authority_data = $authority_query->result_array();
		
		$this->load->view('templates/header');
		$this->load->view('company/all_company',array('company_list'=>$business_data,'authority_data'=>$authority_data));
		//$this->load->view('templates/footer');

	}
	public function addCompany() {
		$this->session->set_userdata('menu','company');
		$login_id = $this->session->userdata('id');
		if($login_id=='') {
			redirect('login');
		}
		
		// Only Super Admin can add companies
		if (!is_super_admin()) {
			$this->session->set_flashdata('message_type', 'error');
			$this->session->set_flashdata('message_name', 'Access denied. Only Super Admin can manage companies.');
			redirect('dashboard/dashboard');
		}
		
		// Permission check - only Super Admin can create companies
		require_permission('company.create');
		
		$sql="select * from authority where status='1' order by id asc ";  
		
		$query = $this->db->query($sql);
		$business_data = $query->result_array();
		
		// Get available templates
		$templates = $this->Permission_model->get_templates();
		
		$frequency = PAYMENT_OPTIONS;
		$this->load->view('templates/header');
		$this->load->view('company/add_company',array('authority'=>$business_data,'frequency'=>$frequency,'templates'=>$templates));
		//$this->load->view('templates/footer');
	}
	public function getTypeByAuthority() {
		$this->session->set_userdata('menu','company');
		$login_id = $this->session->userdata('id');
		if($login_id=='') {
			redirect('login');
		}
		$authority_id = $this->input->post('authority_id');

		$this->db->where('authority_id', $authority_id);
		$query = $this->db->get('sub_type');
		$result = $query->result_array();

		if ($result) {
			echo json_encode([
				'success' => true,
				'types' => $result // each row should have `id`, `type`
			]);
		} else {
			echo json_encode([
				'success' => false,
				'message' => 'No types found for this authority.'
			]);
		}
	}
	public function getFrequencyByType() {
		$this->session->set_userdata('menu','company');
		$login_id = $this->session->userdata('id');
		if($login_id=='') {
			redirect('login');
		}
		 $type_id = $this->input->post('type_id');

		$this->db->where('id', $type_id);
		$query = $this->db->get('sub_type');
		$row = $query->row_array();

		if ($row) {
			echo json_encode([
				'success' => true,
				'frequency' => $row['frequency']
			]);
		} else {
			echo json_encode([
				'success' => false,
				'message' => 'Frequency not found.'
			]);
		}
	}
	/*public function getDocumentsByType() {
		$this->load->model('Company_model');
		$type_id = $this->input->post('type_id');
		$documents = $this->Company_model->getDocumentsForType($type_id); // handle CSV IDs
		if(!empty($documents)){
			echo json_encode(['success'=>true, 'documents'=>$documents]);
		} else {
			echo json_encode(['success'=>false]);
		}
	}*/
	public function getDocumentsByType() {
		error_reporting(E_ALL);
		ini_set('display_errors', 1);
		$this->load->model('Company_model');
		$type_id = $this->input->post('type_id');
		$documents = $this->Company_model->getDocumentsForType($type_id);
		if (!empty($documents)) {
			echo json_encode(['success' => true, 'documents' => $documents]);
		} else {
			echo json_encode(['success' => false]);
		}
	}

	public function submit() {
		$company_id   = $this->input->post('company_id');
		$type_ids     = $this->input->post('type_id');
		$document_ids = $this->input->post('document_id');

		$upload_path = FCPATH . 'uploads/documents/';
		if (!is_dir($upload_path)) mkdir($upload_path, 0777, true);

		foreach ($type_ids as $rowIndex => $type_id) {
			if (empty($_FILES['document_file']['name'][$rowIndex])) continue;

			foreach ($_FILES['document_file']['name'][$rowIndex] as $docIndex => $name) {
				if ($name == '') continue;

				$_FILES['file']['name']     = $_FILES['document_file']['name'][$rowIndex][$docIndex];
				$_FILES['file']['type']     = $_FILES['document_file']['type'][$rowIndex][$docIndex];
				$_FILES['file']['tmp_name'] = $_FILES['document_file']['tmp_name'][$rowIndex][$docIndex];
				$_FILES['file']['error']    = $_FILES['document_file']['error'][$rowIndex][$docIndex];
				$_FILES['file']['size']     = $_FILES['document_file']['size'][$rowIndex][$docIndex];

				$config['upload_path']   = $upload_path;
				$config['allowed_types'] = 'pdf'; // ✅ only pdf
				$config['max_size']      = 2048;  // 2MB
				$config['file_name']     = time() . '_' . $_FILES['file']['name'];

				$this->load->library('upload', $config);

				if ($this->upload->do_upload('file')) {
					$uploadData = $this->upload->data();
					$filePath = 'uploads/documents/' . $uploadData['file_name'];

					$this->db->insert('uploaded_documents', [
						'company_id'    => $company_id,
						'type_id'       => $type_id,
						'document_id'   => $document_ids[$rowIndex][$docIndex],
						'document_name' => $_FILES['file']['name'],
						'file_path'     => $filePath
					]);
				} else {
					$error = $this->upload->display_errors();
					$this->session->set_flashdata('error', $error);
					redirect('company');
				}
			}
		}

		$this->session->set_flashdata('success', 'Documents uploaded successfully!');
		redirect('company');
	}

	public function saveCompany() {
		
		$this->session->set_userdata('menu','type');
		$login_id = $this->session->userdata('id');
		
		if($login_id=='') {
			redirect('login');
		}
		
		// Permission check - only Super Admin can create companies
		require_permission('company.create');
		
		$company_name = trim($_POST['company_name']);
		$company_person = $_POST['company_person'];
		$company_email = $_POST['company_email'];
		$short_name = $_POST['short_name'];
		$country_code = isset($_POST['country_code']) ? $_POST['country_code'] : '';
		$phone_number = $_POST['phone_number'];
		$financial_year = $_POST['financial_year'];
		$created_at = date('d-m-y');
		$co_start_date = $_POST['co_start_date'];
		$address = isset($_POST['address']) ? $_POST['address'] : '';
		$country = isset($_POST['country']) ? $_POST['country'] : '';
		$template_id = isset($_POST['template_id']) ? $_POST['template_id'] : null;
		
		// Check for duplicate company name (ignoring special characters)
		if (check_duplicate_name('company', 'company_name', $company_name, null, ['status' => '1'])) {
			$this->session->set_flashdata('message_type', 'error');
			$this->session->set_flashdata('message_name', 'Company name already exists! (A similar name with different special characters may exist)');
			redirect('company/addCompany');
			return;
		}
		
		$data = array(
			'company_name' => $company_name,
			'contact_person' => $company_person,
			'contact_email' => $company_email,
			'status' => '1',
			'created_at' => $created_at,
			'fiscal_year' => $financial_year,
			'short_name' => $short_name,
			'country_code' => $country_code,
			'phone' => $phone_number,
			'co_start_date' => $co_start_date,
			'address' => $address,
			'country' => $country
		);
		
		$this->db->insert('company', $data);
		
		// Get the new company ID
		$new_company_id = $this->db->insert_id();
		
		// Apply template if selected (items will be DISABLED by default)
		if ($template_id && $new_company_id) {
			$this->Permission_model->apply_template_to_company($new_company_id, $template_id, $login_id);
		}
		
		$this->session->set_flashdata('message_name', 'Company Created Successfully. Please activate document heads from Company Document Heads menu.');
		
		redirect('company/companies');	
	}
	public function checkCompanyName()
	{
		/*$company_name = trim($this->input->post('company_name'));
		$id = $this->input->post('id'); // in case of edit mode

		$this->db->where('company_name', $company_name);

		if (!empty($id)) {
			// Exclude current record if editing
			$this->db->where('id !=', $id);
		}

		$exists = $this->db->get('company')->num_rows() > 0;

		echo $exists ? "false" : "true"; */
		$company_name = $this->input->post('company_name');
		$id           = $this->input->post('id'); // for edit mode

		// Normalize: remove spaces + lowercase
		$normalized = strtolower(str_replace(' ', '', $company_name));

		$this->db->select('id, company_name');
		$this->db->from('company');
		$query = $this->db->get();

		$exists = false;
		foreach ($query->result() as $row) {
			$db_normalized = strtolower(str_replace(' ', '', $row->company_name));
			if ($db_normalized === $normalized) {
				if (!empty($id) && $row->id == $id) {
					continue; // ignore self in edit mode
				}
				$exists = true;
				break;
			}
		}

		echo $exists ? "false" : "true"; 
		// "true" means available, "false" means duplicate
	}
	public function deleteCompany($id)
	{
		$this->session->set_userdata('menu','company');
		$login_id = $this->session->userdata('id');
		
		if($login_id=='') {
			redirect('login');
		}
		
		// Permission check - only Super Admin can delete companies
		require_permission('company.delete');

		//Check is authoiry is mapped with any type and user
        if ($this->id_exists('uploaded_documents', $id)) {
            $this->session->set_flashdata('message_type', 'error');
            $this->session->set_flashdata('message_name', 'Delete not allowed — Company in use.');
            redirect('company/companies');
            return;
        }
		
		$query = $this->db->get_where('company', ['id' => $id]);

		if ($query->num_rows() === 0) {
			redirect('company/companies');
		} else {
			$this->db->where('id', $id)->delete('company');
			$this->session->set_flashdata('message_name', 'Company Deleted Successfully');
			$this->session->set_flashdata('message_type', 'success'); // optional: success, error, info, warning
			redirect('company/companies');
		}
	}
	
	public function editCompany($id) {
		
		$login_id = $this->session->userdata('id');
		
		if($login_id=='') {
			redirect('login');
		}
		$this->session->set_userdata('menu','company');
		
		// Permission check - edit company
		require_permission('company.edit');
		
		// Check company access
		require_company_access($id);
		
		 //Check is authoiry is mapped with any type and user
        if ($this->id_exists('uploaded_documents', $id)) {
            $this->session->set_flashdata('message_type', 'error');
            $this->session->set_flashdata('message_name', 'Edit not allowed — Company in use.');
            redirect('company/companies');
            return;
        }

		$sql = "select * from company where id='$id'";

		$type_query = $this->db->query($sql);
		$type_data = $type_query->result_array();
		
		if(empty($type_data)) {
			redirect('company/companies');
		}
		
		$this->load->view('templates/header');
		$this->load->view('company/edit_company',array('company_data'=>$type_data));		
		
	}
	public function updateCompany() {
		$login_id = $this->session->userdata('id');
		
		if($login_id=='') {
			redirect('login');
		}
		$this->session->set_userdata('menu','type');
		$id = $_POST['id'];
		
		// Permission check - edit company
		require_permission('company.edit');
		
		// Check company access
		require_company_access($id);
		
		$company_name = trim($_POST['company_name']);
		$company_person = $_POST['company_person'];
		$company_email = $_POST['company_email'];
		$short_name = $_POST['short_name'];
		$financial_year = $_POST['financial_year'];
		$country_code = isset($_POST['country_code']) ? $_POST['country_code'] : '';
		$phone_number = $_POST['phone_number'];
		$company_start_date = isset($_POST['company_start_date']) ? $_POST['company_start_date'] : '';
		$address = isset($_POST['address']) ? $_POST['address'] : '';
		$country = isset($_POST['country']) ? $_POST['country'] : '';
		$created_at = date('d-m-y');

		// Check for duplicate company name (excluding current ID)
		if (check_duplicate_name('company', 'company_name', $company_name, $id, ['status' => '1'])) {
			$this->session->set_flashdata('message_type', 'error');
			$this->session->set_flashdata('message_name', 'Company name already exists! (A similar name with different special characters may exist)');
			redirect('company/editCompany/' . $id);
			return;
		}

		$data = array(
			'company_name' => $company_name,
			'contact_person' => $company_person,
			'contact_email' => $company_email,
			'short_name' => $short_name,
			'country_code' => $country_code,
			'phone' => $phone_number,
			'fiscal_year' => $financial_year,
			'co_start_date' => $company_start_date,
			'address' => $address,
			'country' => $country
		);
		
		$this->db->where('id', $id);
		$this->db->update('company', $data);
		
		$this->session->set_flashdata('message_name', 'Company updated Successfully');
		
		redirect('company/companies');	
		
	}
	
	/*public function uploadDocuments($id) {
		$login_id = $this->session->userdata('id');
		
		if($login_id=='') {
			redirect('login');
		}
		$this->session->set_userdata('menu','company');
		$sql="select * from company where status='1' order by id asc ";  
		
		$query = $this->db->query($sql);
		$business_data = $query->result_array();
		
		$sql1="select * from authority where status='1' order by id asc ";  
		
		$authority_query = $this->db->query($sql1);
		$authority_data = $authority_query->result_array();
		
		$this->load->view('templates/layout');
		$this->load->view('company/upload_documents',array('company_list'=>$business_data,'authority_data'=>$authority_data));
	}*/
	
	public function allDocument($company_id, $type_id)
	{
		// Include FPDF & FPDI (only if not already included elsewhere)
		if (!class_exists('FPDF')) {
			require_once APPPATH . 'third_party/FPDF/fpdf.php';
		}
		if (!class_exists('\setasign\Fpdi\Fpdi')) {
			require_once APPPATH . 'third_party/FPDI/src/autoload.php';
		}
		
		$c_id = $this->db
			->select('company_id')
			->from('uploaded_documents')
			->where('id', $company_id)
			->where('is_deleted', 0)
			->get()
			->result_array();
		
		$c__id = $c_id[0]['company_id'];

		// Fetch uploaded rows for the company and type (only rows with a file_name)
		$rows = $this->db
			->select('file_path, file_name')
			->from('uploaded_documents')
			->where('company_id', (int)$c__id)
			->where('type_id', (int)$type_id)
			->where('file_name IS NOT NULL', null, false)
			->where('is_deleted', 0)
			->get()
			->result_array();
		if (empty($rows)) {
			show_error("No uploaded documents found for this company and type.");
			return;
		}

		// Build absolute paths, keep only existing files, remove duplicates
		$paths = [];
		foreach ($rows as $r) {
			// normalize and protect against leading slashes
			$relative = ltrim($r['file_path'], '/\\');
			$full = FCPATH . $relative;

			if (file_exists($full) && is_readable($full)) {
				$paths[] = $full;
			} else {
				log_message('error', "allDocument: file missing or unreadable: {$full}");
			}
		}

		$paths = array_values(array_unique($paths));

		if (empty($paths)) {
			show_error("No physical files found on server for the selected documents.");
			return;
		}

		// Instantiate FPDI
		$pdf = new \setasign\Fpdi\Fpdi();

		// Merge files (skip encrypted/invalid ones)
		foreach ($paths as $file) {
			try {
				$pageCount = $pdf->setSourceFile($file);
			} catch (\setasign\Fpdi\PdfParser\CrossReference\CrossReferenceException $e) {
				// encrypted or malformed PDF — skip it
				log_message('error', "allDocument: encrypted/invalid PDF skipped: {$file} — " . $e->getMessage());
				continue;
			} catch (\Exception $e) {
				log_message('error', "allDocument: could not read PDF {$file} — " . $e->getMessage());
				continue;
			}

			for ($pageNo = 1; $pageNo <= $pageCount; $pageNo++) {
				$templateId = $pdf->importPage($pageNo);
				$size = $pdf->getTemplateSize($templateId);
				$pdf->AddPage($size['orientation'], [$size['width'], $size['height']]);
				$pdf->useTemplate($templateId);
			}
		}

		// Final filename
		$outName = "Company_{$company_id}_Type_{$type_id}.pdf";

		// Clear any output buffering that might corrupt PDF
		if (ob_get_length()) {
			@ob_end_clean();
		}

		// Force download
		$pdf->Output($outName, 'D');
	}

	public function uploadDocuments() {
		$login_id = $this->session->userdata('id');
		
		if($login_id=='') {
			redirect('login');
		}
		$this->session->set_userdata('menu','company');
		$sql="select * from company where status='1' order by id asc ";  
		
		$query = $this->db->query($sql);
		$business_data = $query->result_array();
		
		$sql1="select * from authority where status='1' order by id asc ";  
		
		$authority_query = $this->db->query($sql1);
		$authority_data = $authority_query->result_array();
		
		$this->load->view('templates/layout');
		$this->load->view('company/upload_documents',array('company_list'=>$business_data,'authority_data'=>$authority_data));
	}
	public function viewDocuments($id) {
		$login_id = $this->session->userdata('id');
		$role_id = $this->session->userdata('role_id');

		if($login_id=='') {
			redirect('login');
		}
		
		// Check if user has access to this company
		require_company_access($id);
		
		$this->load->model('Company_model');
		$this->session->set_userdata('menu','company');
		$sql="select * from company where status='1' and id='$id' order by id asc ";  
		$company_query = $this->db->query($sql);
		$business_data = $company_query->result_array();
		$data['type_list'] = $this->Company_model->get_all_types();
		
		// Filter authorities by company-enabled authorities
		// For User role, also filter by assigned authorities
		$allowed_authorities = get_allowed_authorities();
		
		if ($role_id == '3' && !empty($allowed_authorities)) {
			// User role - filter by both company-enabled AND user-assigned authorities
			$auth_ids_str = implode(',', array_map('intval', $allowed_authorities));
			$authority_sql = "SELECT a.* FROM authority a
				INNER JOIN company_authorities ca ON ca.authority_id = a.id 
					AND ca.company_id = ? AND ca.is_enabled = TRUE
				WHERE a.status='1' AND a.id IN ({$auth_ids_str})
				ORDER BY a.authority_name ASC";
		} else {
			// Super Admin / Admin - filter by company-enabled only
			$authority_sql = "SELECT a.* FROM authority a
				INNER JOIN company_authorities ca ON ca.authority_id = a.id 
					AND ca.company_id = ? AND ca.is_enabled = TRUE
				WHERE a.status='1' 
				ORDER BY a.authority_name ASC";
		}
		$authority_query = $this->db->query($authority_sql, array($id));
		$authority_data = $authority_query->result_array();
		
		// Filter document heads by company-enabled
		// For User role, also filter by authorities they have access to
		if ($role_id == '3' && !empty($allowed_authorities)) {
			$auth_ids_str = implode(',', array_map('intval', $allowed_authorities));
			$type_sql = "SELECT st.* FROM sub_type st
				INNER JOIN company_document_heads cdh ON cdh.type_id = st.id 
					AND cdh.company_id = ? AND cdh.is_enabled = TRUE
				WHERE st.status='1' AND st.authority_id::int IN ({$auth_ids_str})
				ORDER BY st.type_name ASC";
		} else {
			$type_sql = "SELECT st.* FROM sub_type st
				INNER JOIN company_document_heads cdh ON cdh.type_id = st.id 
					AND cdh.company_id = ? AND cdh.is_enabled = TRUE
				WHERE st.status='1' 
				ORDER BY st.type_name ASC";
		}
		$type_query = $this->db->query($type_sql, array($id));
		$type_data1 = $type_query->result_array();
		//$data['company_files'] = $this->Company_model->get_all_files();
		
		$authority = $this->input->post('authority');
		$month = $this->input->post('monthly');
		$year = $this->input->post('year');
		if($year=='') {
			$year = date('Y');
		}
		
		// Get authority IDs for User role (role 3) for additional filtering
		$allowedAuthorityIds = ($role_id == '3') ? $allowed_authorities : null;
		
		// Fetch filtered data from DB
		$data['type_data'] = $this->Company_model->getFilteredDocuments($id, $authority, $month, $year, $allowedAuthorityIds);
		$this->load->view('templates/header');
		$this->load->view('company/view_documents',array('company_list'=>$business_data,'data'=>$data,'type_data1'=>$type_data1,'authority_data'=>$authority_data,'type_data'=>$data['type_data']));
	}
	public function filter()
	{
		error_reporting(1);
		$this->load->model('Company_model');
		$authority = $this->input->post('authority');
		$month = $this->input->post('monthly');
		$year = $this->input->post('year');
		$company_id = $this->input->post('company_id');
		$role_id = $this->session->userdata('role_id');
		
		//log_message('Error', 'Executed Auth: ' . $authority);
		
		// Get authority IDs for User role (role 3) for additional filtering
		$allowedAuthorityIds = null;
		if ($role_id == '3') {
			$allowedAuthorityIds = get_allowed_authorities();
		}

		// Fetch filtered data from DB
		$data['type_data'] = $this->Company_model->getFilteredDocuments($company_id, $authority, $month, $year, $allowedAuthorityIds);
			// Load only partial view
		if (empty($data['type_data'])) {
			echo "<p class='text-center text-warning'>No record found</p>";
		} else {
			$this->load->view('company/_documents_table', $data);
		}
	}
	public function addDocument() {
		$doc_id = $this->input->post('doc_id');

		// Windows safe path
		$upload_path = FCPATH . 'uploads' . DIRECTORY_SEPARATOR . 'documents' . DIRECTORY_SEPARATOR;

		// Ensure folder exists
		if (!is_dir($upload_path)) {
			mkdir($upload_path, 0777, true);
		}

		//$config['upload_path']   = $upload_path;
		//$config['upload_path'] = 'C:/xampp/htdocs/dms/uploads/documents/';
		$config['upload_path'] = $this->config->item('documents_upload_path');
		$config['allowed_types'] = 'pdf';
		$config['max_size']      = 3048;
		$config['overwrite']     = TRUE;
		
		//$this->load->library('upload', $config);
		$this->load->library('upload');
		$this->upload->initialize($config);

		if ($this->upload->do_upload('file')) {
			$uploadData = $this->upload->data();

			$data = [
				'document_name' => $uploadData['file_name'],
				'file_path' => $uploadData['file_name'],
				'uploaded_at'   => date('Y-m-d H:i:s')
			];

			$this->db->where('id', $doc_id);
			$this->db->update('uploaded_documents', $data);
			
			echo json_encode([
				"status" => "success",
				"message" => "File uploaded successfully!"
			]);
		} else {
			echo json_encode([
				"status" => "error",
				"message" => strip_tags($this->upload->display_errors())
			]);
		}
	}
	public function getDocument(){
		$doc_id = $this->input->post('doc_id', true);

		//$doc = $this->db->get_where('uploaded_documents', ['id' => $doc_id])->row_array();
		$this->db->select('ud.*, st.id as docu_id , st.document_name');
		$this->db->from('uploaded_documents ud');
		$this->db->join('documents st', 'ud.document_id = st.id', 'left');
		$this->db->where('ud.id', $doc_id);
		$this->db->where('ud.is_deleted', 0);
		$doc = $this->db->get()->row_array();
		//log_message('Error', 'SQL Query of getDocument: ' . print_r($doc));
		if($doc){
			echo json_encode([
				'status' => 'success',
				'data' => $doc
			]);
		} else {
			echo json_encode([
				'status' => 'error',
				'message' => 'Document not found.'
			]);
		}
	}
	public function updateDocument() {
		// Permission check - edit permission required
		if (!can_edit()) {
			echo json_encode([
				'status' => 'error',
				'message' => 'You do not have permission to edit documents.'
			]);
			return;
		}
		
		$doc_id = $this->input->post('doc_id', true); // this should be uploaded_documents.id
		$document_name = $this->input->post('document_name', true);

		$data = ['document_name' => $document_name];

		// Handle file upload if new file provided
		if(!empty($_FILES['file']['name'])){
			$config['upload_path']   = FCPATH . 'uploads/documents/';
			$config['allowed_types'] = 'pdf';
			$config['max_size']      = 3048;
			$config['overwrite']     = TRUE;

			$this->load->library('upload');
			$this->upload->initialize($config);

			if($this->upload->do_upload('file')){
				$uploadData = $this->upload->data();
				$data['file_name']   = $uploadData['file_name'];
				$data['file_path']   = 'uploads/documents/' . $uploadData['file_name'];
				$data['uploaded_at'] = date('Y-m-d H:i:s');
				//$data['document_month'] = date('m');
				//$data['document_year']  = date('Y');
			} else {
				echo json_encode([
					'status'=>'error',
					'message'=>strip_tags($this->upload->display_errors())
				]);
				return;
			}
		}

		// Update row
		$this->db->where('id', $doc_id);
		$this->db->update('uploaded_documents', $data);
		

		// Fetch updated row
		$doc = $this->db->get_where('uploaded_documents', ['id'=>$doc_id])->row_array();

		if ($doc) {
			echo json_encode([
				'status'=>'success',
				'message'=>'Document updated successfully!',
				'data'=>$doc
			]);
		} else {
			echo json_encode([
				'status'=>'error',
				'message'=>'Document not found',
				'data'=>null
			]);
		}
	}
	
	public function downloadDocument($doc_id){
		//$doc = $this->db->get_where('uploaded_documents', ['id' => $doc_id])->row_array();
		
		log_message('error', 'Doc ID: ' . $doc_id);
		
		if ($doc_id) {
			$filePath = FCPATH . 'uploads/documents/' . $doc_id;

			if (file_exists($filePath)) {
				$fileData = file_get_contents($filePath);
				$response = [
					'file_name' => $doc_id,
					'file_data' => base64_encode($fileData)
				];
				echo json_encode($response);
			} else {
				echo json_encode(['error' => 'File not found']);
			}
		} else {
			echo json_encode(['error' => 'Invalid document']);
		}

	}

	/**
	 * Download a single document by filename
	 * Forces browser to download the file instead of displaying it
	 * Accepts filename via URI segment or query parameter (?file=filename)
	 */
	public function downloadSingleDocument($filename = null)
	{
		// Check query parameter if URI segment is empty
		if (empty($filename)) {
			$filename = $this->input->get('file');
		}
		
		if (empty($filename)) {
			show_404();
			return;
		}

		// Sanitize filename to prevent directory traversal
		$filename = basename($filename);
		$filePath = FCPATH . 'uploads/documents/' . $filename;

		if (!file_exists($filePath)) {
			show_404();
			return;
		}

		// Get file info
		$finfo = finfo_open(FILEINFO_MIME_TYPE);
		$mimeType = finfo_file($finfo, $filePath);
		finfo_close($finfo);

		// Force download
		header('Content-Description: File Transfer');
		header('Content-Type: ' . $mimeType);
		header('Content-Disposition: attachment; filename="' . $filename . '"');
		header('Content-Transfer-Encoding: binary');
		header('Expires: 0');
		header('Cache-Control: must-revalidate');
		header('Pragma: public');
		header('Content-Length: ' . filesize($filePath));

		// Clear output buffer
		ob_clean();
		flush();

		// Read file and output
		readfile($filePath);
		exit;
	}
	
	public function fullDownload($company_id=2, $type_id=15)
	{
		// 🔹 Fetch uploaded documents from DB
		$files = $this->db->select('file_path')
			->from('uploaded_documents')
			->where('company_id', $company_id)
			->where('type_id', $type_id)
			->where('file_name IS NOT NULL', null, false) // only uploaded files
			->where('is_deleted', 0)
			->get()
			->result_array();
		
		if (empty($files)) {
			show_error("No documents found for this company and type.");
			return;
		}

		// Initialize FPDI
		$pdf = new Fpdi();

		foreach ($files as $row) {
			if($row['file_path'] !='') {
			echo $file = FCPATH . $row['file_path']; // assumes file_path is relative
			if (file_exists($file)) {
				$pageCount = $pdf->setSourceFile($file);

				// Import all pages of the file
				for ($pageNo = 1; $pageNo <= $pageCount; $pageNo++) {
					$templateId = $pdf->importPage($pageNo);
					$size = $pdf->getTemplateSize($templateId);

					$pdf->AddPage($size['orientation'], [$size['width'], $size['height']]);
					$pdf->useTemplate($templateId);
				}
			}
			}
		}

		// Force download merged file
		$pdf->Output("Company_{$company_id}_Type_{$type_id}.pdf", 'D');
	}
	/*public function submit()
	{
		echo '<pre>'; print_R($_POST);echo '</pre>';
		$company_id    = $this->input->post('company_id');
		$type_ids      = $this->input->post('type_id');
		$document_ids  = $this->input->post('document_id');
		$mandatory     = $this->input->post('mandatory'); // from mandatory_documents table
		 if (empty($type_ids) || count($type_ids) == 0) {
			$this->session->set_flashdata('error', 'Please select at least one type.');
			redirect('type');
			return;
		}
		$upload_path = FCPATH . 'uploads/documents/';
		
		if (!is_dir($upload_path)) {
			mkdir($upload_path, 0777, true);
		}

		foreach ($type_ids as $rowIndex => $type_id) {
			$docGroupIndex = $rowIndex + 1;
				if (!isset($document_ids[$docGroupIndex])) {
					continue;
				}
			foreach ($document_ids[$docGroupIndex] as $docIndex => $document_id) {
				
				$uploaded = false;
				$filePath = null;
				$originalFileName = null;

				// check if file uploaded
				if (isset($_FILES['document_file']['name'][$docGroupIndex][$docIndex]) &&
					$_FILES['document_file']['name'][$docGroupIndex][$docIndex] != '') {

					// Prepare file data
					$_FILES['file']['name']     = $_FILES['document_file']['name'][$docGroupIndex][$docIndex];
					$_FILES['file']['type']     = $_FILES['document_file']['type'][$docGroupIndex][$docIndex];
					$_FILES['file']['tmp_name'] = $_FILES['document_file']['tmp_name'][$docGroupIndex][$docIndex];
					$_FILES['file']['error']    = $_FILES['document_file']['error'][$docGroupIndex][$docIndex];
					$_FILES['file']['size']     = $_FILES['document_file']['size'][$docGroupIndex][$docIndex];

					// Upload config
					$config['upload_path']   = $upload_path;
					$config['allowed_types'] = 'pdf';
					$config['max_size']      = 2048; // 2MB
					$config['file_name']     = time() . '_' . preg_replace('/[^A-Za-z0-9_\-\.]/', '_', $_FILES['file']['name']);

					$this->load->library('upload');
					$this->upload->initialize($config);

					if ($this->upload->do_upload('file')) {
						$uploadData       = $this->upload->data();
						$fileName         = $uploadData['file_name'];
						$filePath         = 'uploads/documents/' . $fileName;
						$originalFileName = $fileName;
						$uploaded         = true;
					} else {
						$error = $this->upload->display_errors();
						log_message('error', 'File upload error: ' . $error);
					}
				}

				// ✅ Always insert a row — uploaded or not
				$data = [
					'company_id'     => $company_id,
					'type_id'        => $type_id,
					'document_id'    => $document_id,
					'document_name'  => $originalFileName,
					'file_path'      => $filePath,
					'document_month' => date('m'),
					'document_year'  => date('Y'),
					'uploaded_at'=>date('Y-m-d h:i:s')
				];
				$this->db->insert('uploaded_documents', $data);
			}
			
		}

		redirect('company/uploadDocuments');
	}*/
		
	
	public function changeProjectStatus($id) {
		$login_id = $this->session->userdata('id');
		if($login_id=='') {
			redirect('login');
		}
		$this->session->set_userdata('user_menu','Master');
		$sql="select * from projects where id='$id'";    
		$query = $this->db->query($sql);
		$business_data = $query->result_array();
		$business_data  = $business_data[0];
		
		if($business_data['status']=='1') {
			$sql="update projects set status='0' where id='$id'"; 
		} else {
			$sql="update projects set status='1' where id='$id'"; 
		}
		$query = $this->db->query($sql);
		$date = date('Y-m-d h:i:s');
		$login_id = $this->session->userdata('id');
		$sql1="insert into log_table (description,action, created_time, user_id) values('Project Status Changed','Status Changed','".$date."','".$login_id."')";
		$query1 = $this->db->query($sql1);
		$this->session->set_flashdata('message_name', 'Project Status Successfully Updated');

		redirect('project/myProjects');
	}
	
	public function sendDocumentEmail(){
		$doc_id = $this->input->post('doc_id', true);
		$recipient = $this->input->post('recipient_email', true);

		$doc = $this->db->get_where('uploaded_documents', ['id'=>$doc_id])->row_array();
		if(empty($doc['file_path'])){
			echo json_encode(['status'=>'error','message'=>'Document not found']);
			return;
		}

		$file_path = FCPATH . 'uploads/documents/' . $doc['file_path'];
		if(!file_exists($file_path)){
			echo json_encode(['status'=>'error','message'=>'File not found on server']);
			return;
		}

		$this->load->library('email');

		$this->email->from('rajeshjoshi@eighttechprojects.com','Rajesh Joshi');
		$this->email->to($recipient);
		$this->email->subject('Document: ' . $doc['document_name']);
		$this->email->message('Please find the attached document.');

		$this->email->attach($file_path);

		if($this->email->send()){
			echo json_encode(['status'=>'success','message'=>'Email sent successfully!']);
		} else {
			echo json_encode(['status'=>'error','message'=>'Failed to send email.']);
		}
	}
	
	public function changeStatus()
	{
		$id     = $this->input->post('id');
		$status = $this->input->post('status');

		//Check is authoiry is mapped with any type and user
        if ($this->id_exists('uploaded_documents', $id)) {
               echo json_encode([
				'success' => false,
				'message' => 'Deactivation not allowed — Document head in use.'
			]);
			return;
        }

		// Convert 'Active' to 0 and anything else to 1
		$new_status = ($status == '0') ? '0' : '1';

		$sql = "UPDATE company SET status='$new_status' WHERE id='$id'"; 
		$query = $this->db->query($sql);

		if ($query) {
			echo json_encode([
				'success'    => true,
				'message'    => 'Status updated successfully.',
				'new_status' => $new_status
			]);
		} else {
			echo json_encode([
				'success' => false,
				'message' => 'Failed to update status.'
			]);
		}
	}

	/**
	 * Check if a document can be deleted (pre-validation for master/sub)
	 */
	public function checkDocumentDeletable(){
		$doc_id = $this->input->post('doc_id', true);
		
		$doc = $this->db->get_where('uploaded_documents', ['id' => $doc_id])->row_array();
		if(!$doc){
			echo json_encode(['can_delete' => false, 'message' => 'Document not found']);
			return;
		}

		$this->load->model('DocumentGroup_model');
		
		$document_id = $doc['document_id'];
		$company_id = $doc['company_id'];
		$type_id = $doc['type_id'];
		$month = $doc['document_month'];
		$year = $doc['document_year'];

		// Get document role
		$docRole = $this->DocumentGroup_model->getDocumentRole($document_id);

		// If this is a master document, check if it has uploaded sub documents
		if ($docRole['is_master']) {
			$canDelete = $this->DocumentGroup_model->canDeleteMasterDocument(
				$document_id, $company_id, $type_id, $month, $year
			);
			
			if (!$canDelete['can_delete']) {
				echo json_encode([
					'can_delete' => false,
					'message' => $canDelete['reason'],
					'is_master' => true,
					'sub_count' => $canDelete['sub_count']
				]);
				return;
			}
		}

		echo json_encode([
			'can_delete' => true,
			'is_master' => $docRole['is_master'],
			'is_sub' => $docRole['is_sub']
		]);
	}
	
	public function deleteDocument(){
		// Permission check - delete permission required
		if (!can_delete()) {
			echo json_encode(['status' => 'error', 'message' => 'You do not have permission to delete documents.']);
			return;
		}
		
		$doc_id = $this->input->post('doc_id', true);
		
		// Get file path if you want to remove the file from uploads
		$doc = $this->db->get_where('uploaded_documents', ['id' => $doc_id])->row_array();
		if(!$doc){
			echo json_encode(['status'=>'error','message'=>'Document not found']);
			return;
		}

		// Load DocumentGroup model for master/sub validation
		$this->load->model('DocumentGroup_model');
		
		$document_id = $doc['document_id'];
		$company_id = $doc['company_id'];
		$type_id = $doc['type_id'];
		$month = $doc['document_month'];
		$year = $doc['document_year'];

		// Get document role (master, sub, or neither)
		$docRole = $this->DocumentGroup_model->getDocumentRole($document_id);

		// If this is a master document, check if it has uploaded sub documents
		if ($docRole['is_master']) {
			$canDelete = $this->DocumentGroup_model->canDeleteMasterDocument(
				$document_id, $company_id, $type_id, $month, $year
			);
			
			if (!$canDelete['can_delete']) {
				echo json_encode([
					'status' => 'error',
					'message' => $canDelete['reason'],
					'is_master' => true,
					'sub_count' => $canDelete['sub_count']
				]);
				return;
			}

			// Master has no subs, clean up child_document_mandatory
			$this->DocumentGroup_model->cleanupOnMasterDocumentDelete(
				$document_id, $company_id, $type_id, $month, $year
			);
		}

		// If this is a sub document, clean up child_document_mandatory
		if ($docRole['is_sub']) {
			$this->DocumentGroup_model->cleanupOnSubDocumentDelete(
				$document_id, $company_id, $type_id, $month, $year
			);
		}

		// Soft delete the document
		$data['is_deleted'] = 1;
		$data['deleted_at'] = date('Y-m-d H:i:s');
		$this->db->where('id', $doc_id);
		$this->db->update('uploaded_documents', $data);
		
		echo json_encode(['status'=>'success','message'=>'Document deleted successfully!']);
	}
	
	public function newDocuments($id) {
		$microtime = microtime(true); // Current time in seconds with microseconds
		$datetime = date('Y-m-d H:i:s') . sprintf('.%03d', ($microtime - floor($microtime)) * 1000);
		log_message('debug', 'Entered New Document Method for Company ID ' .$datetime);

		$login_id = $this->session->userdata('id');
		$role_id = $this->session->userdata('role_id');
		
		if($login_id=='') {
			redirect('login');
		}
		
		// Check if user has access to this company
		require_company_access($id);
		
		$this->load->model('Company_model');
		$this->session->set_userdata('menu','company');
		$sql="select * from company where status='1' and id='$id' order by id asc ";  
		$company_query = $this->db->query($sql);
		$business_data = $company_query->result_array();
		$data['type_list'] = $this->Company_model->get_all_types();
		
		// Wrap in an associative array to pass to view
		$companies_data = [
			'company_list' => $business_data
		];

		// Get user's allowed authorities for filtering
		$allowed_authorities = get_allowed_authorities();
		$auth_filter = '';
		
		// For User role, filter by assigned authorities
		if ($role_id == '3' && !empty($allowed_authorities)) {
			$auth_ids_str = implode(',', array_map('intval', $allowed_authorities));
			$auth_filter = " AND a.id IN ({$auth_ids_str})";
		}

		// Filter authorities by company-enabled authorities (and user-assigned for User role)
		$authority_sql = "SELECT a.* FROM authority a
			INNER JOIN company_authorities ca ON ca.authority_id = a.id 
				AND ca.company_id = ? AND ca.is_enabled = TRUE
			WHERE a.status='1' {$auth_filter}
			ORDER BY a.authority_name ASC";
		$authority_query = $this->db->query($authority_sql, array($id));
		$authority_data = $authority_query->result_array();
		
		// Filter by enabled document heads for this company (and user's authorities for User role)
		$auth_type_filter = '';
		if ($role_id == '3' && !empty($allowed_authorities)) {
			$auth_ids_str = implode(',', array_map('intval', $allowed_authorities));
			$auth_type_filter = " AND st.authority_id::int IN ({$auth_ids_str})";
		}
		
		$type_sql="SELECT DISTINCT ud.type_id, st.type_name, st.alias_name
					FROM public.uploaded_documents AS ud
					JOIN public.sub_type AS st ON ud.type_id = st.id
					INNER JOIN public.company_document_heads AS cdh ON cdh.type_id = st.id 
						AND cdh.company_id = $id AND cdh.is_enabled = TRUE
					WHERE ud.is_deleted = '0' AND st.status='1' AND ud.company_id= $id {$auth_type_filter}
					ORDER BY st.type_name";

		$type_query = $this->db->query($type_sql);
		$type_data1 = $type_query->result_array();
		//$data['company_files'] = $this->Company_model->get_all_files();
		
		$authority = $this->input->post('authority');
		$month = $this->input->post('monthly');
		$year = $this->input->post('year');
		if($year=='') {
			$year = date('Y');
		}
		
		// Get authority IDs for User role (role 3) for additional filtering
		$allowedAuthorityIds = ($role_id == '3') ? $allowed_authorities : null;
		
		// Fetch filtered data from DB
		$data['type_data'] = $this->Company_model->getFilteredDocuments($id, $authority, $month, $year, $allowedAuthorityIds);
		$this->load->view('templates/header',$companies_data);
		$this->load->view('company/new_documents',array('company_list'=>$business_data,'data'=>$data,'type_data1'=>$type_data1,'authority_data'=>$authority_data,'type_data'=>$data['type_data']));
		$microtime = microtime(true); // Current time in seconds with microseconds
		$datetimeExit = date('Y-m-d H:i:s') . sprintf('.%03d', ($microtime - floor($microtime)) * 1000);
		log_message('debug', 'Exited New Document Method for Company ID ' . $datetimeExit);
	}
	
	public function getDocumentsByAuthority() {
		$authority_ids = $this->input->post('authority_ids');
		$company_id = $this->input->post('company_id');
		$years = $this->input->post('years'); // New: year filter

		log_message('debug', 'Authority IDs: ' . print_r($authority_ids, TRUE));
		log_message('debug', 'Company ID: ' . $company_id);
		log_message('debug', 'Years: ' . print_r($years, TRUE));

		// Load model
		$this->load->model('Company_model');

		// Pass both authority_ids and years to the model
		if (empty($authority_ids) && empty($years)) {
			// No filters - load all documents
			$documents = $this->Company_model->getAllDocuments($company_id);
		} elseif (empty($authority_ids) && !empty($years)) {
			// Only year filter
			$documents = $this->Company_model->getAllDocuments($company_id, $years);
		} elseif (!empty($authority_ids) && empty($years)) {
			// Only authority filter
			$documents = $this->Company_model->getDocuments($authority_ids, $company_id);
		} else {
			// Both filters
			$documents = $this->Company_model->getDocuments($authority_ids, $company_id, $years);
		}

		header('Content-Type: application/json');
		echo json_encode($documents);
    }
	
	public function reminderSent(){
		//exit('in ReminderSent function');
	}

	public function send_due_reminders()
    {
		//$this->load->model('Company_model');
        //$this->Company_model->send_reminders();
		$this->load->model('Company_Model');
			$reminder_data = $this->Company_model->getReminders();

			foreach ($reminder_data as $row) {
				//echo $row['document_name'];
				//echo "</br>";
				switch ($row['reminder_type']) {
					case 'today':
						//echo 'today'.$row['document_name'];
						$pending_docs = $this->Company_model->getUnuploadedDocuments($row['document_name']);
						// Send "Due Today" email
						break;
					case '1_day':
						//echo 'one day'.$row['document_name'];
						$pending_docs = $this->Company_model->getUnuploadedDocuments($row['document_name']);
						// Send "Due Tomorrow" email
						break;
					case '5_days':
						//echo 'five days'.$row['document_name'];
						$pending_docs = $this->Company_model->getUnuploadedDocuments($row['document_name']);
						// Send "Due in 5 Days" email
						break;
					case '10_days':
						//echo 'Ten days'.$row['document_name'];
						$pending_docs= $this->Company_model->getUnuploadedDocuments($row['document_name']);
						// Send "Due in 10 Days" email
						break;
				}
				/*echo '<pre>';
				print_r($row['reminder_type']);
				echo '<pre>';
				print_r($pending_docs);*/

				if (!empty($row['reminder_type']) && $row['reminder_type'] == '10_days'){
					echo 'Mail sent for 10 days';
				}
				if (!empty($row['reminder_type']) && $row['reminder_type'] == '5_days'){
					echo 'Mail sent for 5 days';
				}
				if (!empty($row['reminder_type']) && $row['reminder_type'] == '1_day'){
					echo 'Mail sent for 1 days';
				}
				if (!empty($row['reminder_type']) && $row['reminder_type'] == 'today'){
					echo 'Mail sent for todays';
				}
			}
			

			/*echo '<pre>';
			print_r($pending_docs_one_days);

			echo '<pre>';
			print_r($pending_docs_five_days);

			echo '<pre>';
			print_r($pending_docs_ten_days);*/

			exit;
        $this->load->model('Company_model');
        $this->Company_model->send_reminders();
		echo "Reminder email(s) sent.";
    }

    /**
     * Download all documents under a given Authority (Type)
     * Example: /DocumentTree/download_all/3
     */
    public function download_all($type_id,$company_id) {
        //echo $type_id.'   '.$company_id;exit;
		//echo '<pre>'; print_R($_REQUEST);exit;
        $docs = $this->Company_model->getDocumentsZip($type_id,$company_id);
        $this->_create_zip($docs, "Authority_{$type_id}",'type');
    }

    /**
     * Download all documents under a specific Year for an Authority
     * Example: /DocumentTree/download_year/3/2025
     */
    public function download_year($type_id, $company_id, $year) {
        $docs = $this->Company_model->getDocumentsZip($type_id, $company_id, $year);
        $this->_create_zip($docs, "Authority_{$type_id}_{$year}",'year');
    }

    /**
     * Download all documents under a specific Month of a given Year and Authority
     * Example: /DocumentTree/download_month/3/2025/January
     */
    public function download_month($type_id, $company_id, $year, $month) {
        $monthNumber = get_month_number($month);
        $docs = $this->Company_model->getDocumentsZip($type_id, $company_id, $year, $monthNumber);
		$fileName = get_monthly_document_filename($type_id, $year, $month);
        $this->_create_zip($docs, $fileName,'month');
    }

    /**
     * Download all documents for a specific Year across ALL authorities (Year View)
     * Example: /company/download_year_all/1/2025
     */
    public function download_year_all($company_id, $year) {
        // Get all documents for this company and year (null type_id means all authorities)
        $docs = $this->Company_model->getDocumentsZip(null, $company_id, $year, null);
        // Use 'year-all' level for a single ZIP containing all authorities
        $this->_create_zip($docs, "{$year}_DOC", 'year-all');
    }

	private function _create_zip($docs, $zipName = 'Documents', $level = 'type')
	{
		$this->load->library('zip');
		$this->zip->clear_data();

		$baseDir = FCPATH . 'temp_zip/';
		$outputDir = FCPATH . 'output/';

		// 🔹 Clean old temp folder if exists
		if (is_dir($baseDir)) {
			$this->delete_directory($baseDir);
		}
		mkdir($baseDir, 0777, true);
		if (!is_dir($outputDir)) mkdir($outputDir, 0777, true);

		// 🔹 Group documents by authority → year → month
		
		$grouped = [];
		foreach ($docs as $item) {
			$grouped[$item->authority][$item->year][$item->month][] = [
				'file_name' => $item->file_name,
				'doc_name'  => $item->doc_name
			];
		}

		// 🔹 For year-all level, we create a single ZIP with all authorities inside
		if ($level == 'year-all') {
			$zipFolderPath = "$baseDir{$zipName}/";
			$zipFileName = "{$zipName}.zip";
			
			if (!is_dir($zipFolderPath)) {
				mkdir($zipFolderPath, 0777, true);
			}
		}

		// 🔹 Loop through authorities
		foreach ($grouped as $authority => $years) {

			// Determine ZIP structure based on level
			if ($level == 'type') {
				$zipFolderPath = "$baseDir$authority/";
				$zipFileName = "{$authority}.zip";
			}

			foreach ($years as $year => $months) {

				// For year-level (single authority), ZIP per year
				if ($level == 'year') {
					$zipFolderPath = "$baseDir{$authority}_{$year}/";
					$zipFileName = "{$authority}_{$year}.zip";
				}

				foreach ($months as $month => $docsList) {

					if ($level == 'type') {
						$monthDir = "$zipFolderPath$year/$month/";
					} elseif ($level == 'year') {
						$monthDir = "$zipFolderPath$month/";
					} elseif ($level == 'year-all') {
						// For year-all: Authority folder / Month folder
						$authorityClean = preg_replace('/[^A-Za-z0-9\s]+/', '_', $authority);
						$monthDir = "$baseDir{$zipName}/{$authorityClean}/{$month}/";
					} else {
						$monthDir = "$baseDir$authority/$year/$month/";
					}

					if (!is_dir($monthDir)) {
						mkdir($monthDir, 0777, true);
					}

					// 🔹 Build merged PDF file
					$pdfFiles = [];
					foreach ($docsList as $doc) {
						$filePath = FCPATH . 'uploads/documents/' . $doc['file_name'];
						if (file_exists($filePath)) {
							$pdfFiles[] = $filePath;
						} else {
							log_message('error', "Missing PDF: {$filePath}");
						}
					}

					$name = preg_replace('/[^A-Za-z0-9]+/', '_', strtolower($authority));
					$mergedName = "{$name}_{$year}_{$month}.pdf";
                	$mergedPdfPath = $monthDir . $mergedName;

					// Merge actual files
					if (!empty($pdfFiles)) {
						$this->merge_pdfs($pdfFiles, $mergedPdfPath);
					} else {
						log_message('error', "No valid PDFs to merge for {$authority} - {$year} - {$month}");
						continue;
					}

					// 🔹 If this is month-level → directly download the merged file
					if ($level == 'month') {
						header('Content-Type: application/pdf');
						header('Content-Disposition: attachment; filename="' . basename($mergedPdfPath) . '"');
						readfile($mergedPdfPath);
						exit;
					}
				}

				// For year-level (single authority), zip each year separately
				if ($level == 'year') {
					$this->zip->clear_data();
					$this->zip->read_dir($zipFolderPath, FALSE);
					$zipFilePath = $outputDir . $zipFileName;
					$this->zip->archive($zipFilePath);
					$this->zip->download($zipFileName);
				}
			}

			// For type-level, zip after all years processed
			if ($level == 'type') {
				$this->zip->clear_data();
				$this->zip->read_dir($zipFolderPath, FALSE);
				$zipFilePath = $outputDir . $zipFileName;
				$this->zip->archive($zipFilePath);
				$this->zip->download($zipFileName);
			}
		}

		// 🔹 For year-all level, zip everything at the end (after processing all authorities)
		if ($level == 'year-all') {
			$zipFolderPath = "$baseDir{$zipName}/";
			$zipFileName = "{$zipName}.zip";
			
			$this->zip->clear_data();
			$this->zip->read_dir($zipFolderPath, FALSE);
			$zipFilePath = $outputDir . $zipFileName;
			$this->zip->archive($zipFilePath);
			$this->zip->download($zipFileName);
		}
	}

	private function merge_pdfs($files, $outputPath)
	{
		// 1. Prepare files for the command line
		// Quoting paths is CRITICAL for security and to handle spaces in names.
		$input_files_quoted = array_map(function($f) {
			return '"' . $f . '"';
		}, $files);
		
		$input_files_string = implode(' ', $input_files_quoted);

		$gs_path = 'C:\Program Files\gs\gs10.06.0\bin\gswin64c.exe';
		// 2. Define the command
		// Use the full path to 'gs' if it's not in your system's PATH.
		// -q: Quiet mode | -dNOPAUSE -dBATCH: Non-interactive | -sDEVICE=pdfwrite: Output PDF
		//$command = "gs -q -dNOPAUSE -dBATCH -sDEVICE=pdfwrite -sOutputFile=\"{$outputPath}\" {$input_files_string}";
		$command = "\"{$gs_path}\" -q -dNOPAUSE -dBATCH -sDEVICE=pdfwrite -sOutputFile=\"{$outputPath}\" {$input_files_string}";

		// 3. Execute the command
		$startTime = microtime(true);
		$output = shell_exec($command);
		$duration = microtime(true) - $startTime;

		// 4. Check for success
		if (!file_exists($outputPath) || filesize($outputPath) === 0) {
			log_message('error', "Ghostscript merge FAILED (Duration: {$duration}s). Command: {$command}");
			log_message('error', "Ghostscript output: " . $output);
			// Throw an exception to stop execution gracefully
			throw new Exception("PDF Merge Failed. Check Ghostscript installation/permissions.");
		} else {
			log_message('info', "Ghostscript merge successful (Duration: {$duration}s). Output: {$outputPath}");
		}
	}

	private function merge_pdfs_with_FPDI($files, $outputPath)
	{
		$pdf = new Fpdi();

		foreach ($files as $filePath) {
			if (!file_exists($filePath)) continue;

			try {
				$pageCount = $pdf->setSourceFile($filePath);
				for ($pageNo = 1; $pageNo <= $pageCount; $pageNo++) {
					$tplIdx = $pdf->importPage($pageNo);
					$size = $pdf->getTemplateSize($tplIdx);
					$pdf->AddPage($size['orientation'], [$size['width'], $size['height']]);
					$pdf->useTemplate($tplIdx);
				}
			} catch (Exception $e) {
				log_message('error', "PDF merge failed for {$filePath}: " . $e->getMessage());
			}
		}

		$pdf->Output($outputPath, 'F');
	}

	/**
	 * Helper function to recursively delete old temp folder
	 */
	private function delete_directory($dir)
	{
		if (!file_exists($dir)) return true;
		if (!is_dir($dir)) return unlink($dir);
		foreach (scandir($dir) as $item) {
			if ($item == '.' || $item == '..') continue;
			$this->delete_directory($dir . DIRECTORY_SEPARATOR . $item);
		}
		return rmdir($dir);
	}

	/**
     * Download all documents under a specific Month of a given Year and Authority
     * Example: /DocumentTree/view_documents/3/2025/January
     */
    public function view_documents($type_id, $company_id, $year, $month) {
        $monthNumber = get_month_number($month);
        
        $docs = $this->Company_model->getDocumentsZip($type_id, $company_id, $year, $monthNumber);
		log_message('debug', "October PDF: ". print_r($docs, true));
        
		if (empty($docs)) {
        show_error("No documents found for {$month} {$year}.", 404);
        return;
		}

		$pdfFiles = [];
		foreach ($docs as $doc) {
			
			//$name = pathinfo($f, PATHINFO_FILENAME);
			//$name = preg_replace('/[^A-Za-z0-9]+/', '_', strtolower($doc['doc_name']));
			//$name = preg_replace('/[^A-Za-z0-9]+/', '_', strtolower($authority));
			//$fileBaseNames[] = $name;

			$filePath = FCPATH . 'uploads/documents/' . $doc->file_name;
			if (file_exists($filePath)) {
				$pdfFiles[] = $filePath;  // ✅ store full path, not just filename
				//$type_name = $doc->authority;
				$type_name_raw = $docs[0]->authority ?? 'Document';

				$type_name = preg_replace('/[^A-Za-z0-9_-]/', '_', $type_name_raw);
			} else {
				log_message('error', "Missing PDF: {$filePath}");
			}
		}

		// Ensure temp directory exists
		$outputDir = FCPATH . 'uploads/temp/';
		if (!is_dir($outputDir)) {
			mkdir($outputDir, 0755, true);
		}
		// Define merged PDF path
		$outputPath = $outputDir . "{$type_name}_{$year}_{$monthNumber}.pdf";

		// Merge the files using your existing helper
		$this->merge_pdfs($pdfFiles, $outputPath);

		// Return the public URL to AJAX
		$fileUrl = base_url("uploads/temp/" . basename($outputPath));
		redirect($fileUrl);
    }

	// 🔹 Private helper function to check if a record exists
    private function id_exists($table, $id)
    {
        return $this->db->where('company_id', $id)
                        ->where('is_deleted', '0')
                        ->limit(1)
                        ->count_all_results($table) > 0;
    }
    
    /**
     * Send document notification email for month level
     */
    public function sendDocumentNotification()
    {
        // Validate AJAX request
        if (!$this->input->is_ajax_request()) {
            echo json_encode(['status' => 'error', 'message' => 'Invalid request']);
            return;
        }
        
        $email = $this->input->post('email');
        $additionalMessage = $this->input->post('additional_message');
        $authorityName = $this->input->post('authority_name');
        $companyId = $this->input->post('company_id');
        $month = $this->input->post('month');
        $year = $this->input->post('year');
        $period = $this->input->post('period');
        $uploadLink = $this->input->post('upload_link');
        $authorityId = $this->input->post('authority_id'); // This is actually the type_id (document head)
        
        // Validate email
        if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
            echo json_encode(['status' => 'error', 'message' => 'Invalid email address']);
            return;
        }
        
        // Get company name
        $company = $this->db->where('id', $companyId)->get('company')->row();
        $companyName = $company ? $company->company_name : 'Unknown Company';
        
        // Convert month name to number if needed (e.g., "December" -> "12", "01" -> "01")
        $monthNum = $this->_convertMonthToNumber($month);
        
        log_message('debug', "sendDocumentNotification: month input='$month', converted='$monthNum'");
        
        // First, query for uploaded documents to determine email type
        $this->db->select('id, file_name')
                 ->where('company_id', $companyId)
                 ->where('document_month', $monthNum)
                 ->where('document_year', $year)
                 ->where('is_deleted', 0);
        
        // Add type_id filter if authority_id is provided (authority_id = type_id in this context)
        if (!empty($authorityId)) {
            $this->db->where('type_id', $authorityId);
        }
        
        $docs = $this->db->get('uploaded_documents')->result();
        $docCount = count($docs);
        
        log_message('debug', "sendDocumentNotification query: company_id=$companyId, type_id=$authorityId, month=$monthNum, year=$year, found $docCount documents");
        
        // Load email library with config
        $this->load->config('email');
        $this->load->library('email');
        
        // Configure email
        $config = array(
            'protocol' => $this->config->item('protocol'),
            'smtp_host' => $this->config->item('smtp_host'),
            'smtp_port' => $this->config->item('smtp_port'),
            'smtp_user' => $this->config->item('smtp_user'),
            'smtp_pass' => $this->config->item('smtp_pass'),
            'smtp_crypto' => $this->config->item('smtp_crypto'),
            'mailtype' => 'html',
            'charset' => 'utf-8',
            'newline' => "\r\n"
        );
        
        $this->email->initialize($config);
        $this->email->set_newline("\r\n");
        
        // Build email content based on whether documents are found
        $this->email->from($this->config->item('from_email'), $this->config->item('from_name'));
        $this->email->to($email);
        
        if ($docCount > 0) {
            // Documents found - send sharing email
            $this->email->subject("Documents Shared: {$companyName} - {$authorityName} - {$period}");
            
            $message = "
            <html>
            <head>
                <style>
                    body { font-family: Arial, sans-serif; line-height: 1.6; color: #333; }
                    .container { max-width: 600px; margin: 0 auto; padding: 20px; }
                    .header { background: #1e3a5f; color: #fff; padding: 5px; text-align: center; border-radius: 8px 8px 0 0; }
                    .content { background: #f9fafb; padding: 20px; border: 1px solid #e5e7eb; }
                    .info-box { background: white; padding: 15px; border-radius: 8px; margin: 15px 0; border-left: 4px solid #3b82f6;  }
                    .message-box { background: #fff3cd; padding: 15px; border-radius: 8px; margin: 15px 0; border-left: 4px solid #ffc107; }
					.footer { text-align: center; padding: 15px; color: #6b7280; font-size: 12px; }
                </style>
            </head>
            <body>
                <div class='container'>
                    <div class='header'>
                        <h2 style='margin:0;'>Documents Shared</h2>
                    </div>
                    <div class='content'>
                        <p>Hello,</p>
                        <p>Document(s) have been shared with you for:</p>
                        
                        <div class='info-box'>
                            <strong>Company:</strong> {$companyName}<br>
                            <strong>Document Head:</strong> {$authorityName}<br>
                            <strong>Period:</strong> {$period}
                        </div>
                        
                        
                        " . ($additionalMessage ? "<p><strong>Message:</strong><br>" . nl2br(htmlspecialchars($additionalMessage)) . "</p>" : "") . "
                    </div>
                    <div class='footer'>
                        <p>This is an automated message from Document Management System.</p>
                    </div>
                </div>
            </body>
            </html>";
        } else {
            // No documents - send reminder email
            $this->email->subject("Document Reminder: {$authorityName} - {$period}");
            
            $message = "
            <html>
            <head>
                <style>
                    body { font-family: Arial, sans-serif; line-height: 1.6; color: #333; }
                    .container { max-width: 600px; margin: 0 auto; padding: 20px; }
                    .header { background: linear-gradient(135deg, #3b82f6 0%, #2563eb 100%); color: white; padding: 20px; border-radius: 8px 8px 0 0; }
                    .content { background: #f9fafb; padding: 20px; border: 1px solid #e5e7eb; }
                    .info-box { background: white; padding: 15px; border-radius: 6px; margin: 10px 0; border-left: 4px solid #3b82f6; }
                    .btn { display: inline-block; background: #3b82f6; color: white; padding: 12px 24px; text-decoration: none; border-radius: 6px; margin-top: 15px; }
                    .footer { text-align: center; padding: 15px; color: #6b7280; font-size: 12px; }
                </style>
            </head>
            <body>
                <div class='container'>
                    <div class='header'>
                        <h2 style='margin:0;'>Document Reminder</h2>
                    </div>
                    <div class='content'>
                        <p>Hello,</p>
                        <p>This is a reminder to upload the pending documents for:</p>
                        
                        <div class='info-box'>
                            <strong>Company:</strong> {$companyName}<br>
                            <strong>Document Head:</strong> {$authorityName}<br>
                            <strong>Period:</strong> {$period}
                        </div>
                        <div class='message-box'>
							<p><strong>Message:</strong></p>
							<p>" . ($additionalMessage ? "<p><strong>Message:</strong><br>" . nl2br(htmlspecialchars($additionalMessage)) . "</p>" : "") . "</p>
						</div>
                        <p>Please click the button below to upload the required documents:</p>
                        
                        <a href='{$uploadLink}' class='btn'>Upload Documents</a>
                    </div>
                    <div class='footer'>
                        <p>This is an automated message from Document Management System.</p>
                    </div>
                </div>
            </body>
            </html>";
        }
        
        $this->email->message($message);
        
        $attachCount = 0;
        $pdfFiles = [];
        $mergedFile = null;
        
        // Collect valid PDF files
        foreach ($docs as $doc) {
            if (!empty($doc->file_name)) {
                $filePath = FCPATH . 'uploads/documents/' . $doc->file_name;
                if (file_exists($filePath)) {
                    $pdfFiles[] = $filePath;
                }
            }
        }
        
        // If multiple files, try to merge them into a single PDF
        if (count($pdfFiles) > 1) {
            $mergeSuccess = false;
            
            try {
                $this->load->library('pdfmergerlib');
                
                // Create temp directory if not exists
                $outputDir = FCPATH . 'uploads/temp/';
                if (!is_dir($outputDir)) {
                    mkdir($outputDir, 0755, true);
                }
                
                $mergedFile = $outputDir . 'merged_' . $companyId . '_' . $monthNum . '_' . $year . '_' . time() . '.pdf';
                $mergeResult = $this->pdfmergerlib->merge($pdfFiles, $mergedFile);
                
                if ($mergeResult && file_exists($mergedFile) && filesize($mergedFile) > 0) {
                    $this->email->attach($mergedFile);
                    $attachCount = 1;
                    $mergeSuccess = true;
                    log_message('debug', 'PDF merge successful: ' . $mergedFile);
                } else {
                    log_message('error', 'PDF merge returned false or file not created');
                }
            } catch (Exception $e) {
                log_message('error', 'PDF merge exception: ' . $e->getMessage());
            }
            
            // Fallback: attach individual files if merge failed
            if (!$mergeSuccess) {
                log_message('debug', 'Falling back to individual file attachments');
                $mergedFile = null; // Don't try to clean up non-existent file
                foreach ($pdfFiles as $file) {
                    $this->email->attach($file);
                    $attachCount++;
                }
            }
        } elseif (count($pdfFiles) == 1) {
            // Single file - attach as is
            $this->email->attach($pdfFiles[0]);
            $attachCount = 1;
        }
        
        log_message('debug', "sendDocumentNotification: attachCount=$attachCount, pdfFiles=" . count($pdfFiles));
        
        if ($this->email->send()) {
            $message = 'Email sent successfully';
            if ($attachCount > 0) {
                if (count($pdfFiles) > 1 && $mergedFile && file_exists($mergedFile)) {
                    $message .= " with merged PDF (" . count($pdfFiles) . " documents)";
                    // Clean up merged file after sending
                    @unlink($mergedFile);
                } else {
                    $message .= " with {$attachCount} document(s) attached";
                }
            }
            echo json_encode(['status' => 'success', 'message' => $message]);
        } else {
            // Clean up merged file if email failed
            if ($mergedFile && file_exists($mergedFile)) {
                @unlink($mergedFile);
            }
            log_message('error', 'Email failed: ' . $this->email->print_debugger(['headers', 'subject', 'body']));
            echo json_encode(['status' => 'error', 'message' => 'Failed to send email. Please try again.']);
        }
    }
    
    /**
     * Share document via email at document level
     */
    public function shareDocumentEmail()
    {
        // Validate AJAX request
        if (!$this->input->is_ajax_request()) {
            echo json_encode(['status' => 'error', 'message' => 'Invalid request']);
            return;
        }
        
        $email = $this->input->post('email');
        $additionalMessage = $this->input->post('additional_message');
        $documentName = $this->input->post('document_name');
        $documentId = $this->input->post('document_id');
        $fileUrl = $this->input->post('file_url');
        
        // Validate email
        if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
            echo json_encode(['status' => 'error', 'message' => 'Invalid email address']);
            return;
        }
        
        // Load email library with config
        $this->load->config('email');
        $this->load->library('email');
        
        // Configure email
        $config = array(
            'protocol' => $this->config->item('protocol'),
            'smtp_host' => $this->config->item('smtp_host'),
            'smtp_port' => $this->config->item('smtp_port'),
            'smtp_user' => $this->config->item('smtp_user'),
            'smtp_pass' => $this->config->item('smtp_pass'),
            'smtp_crypto' => $this->config->item('smtp_crypto'),
            'mailtype' => 'html',
            'charset' => 'utf-8',
            'newline' => "\r\n"
        );
        
        $this->email->initialize($config);
        $this->email->set_newline("\r\n");
        
        // Build email content
        $this->email->from($this->config->item('from_email'), $this->config->item('from_name'));
        $this->email->to($email);
        $this->email->subject("Document Shared: {$documentName}");
        
        $message = "
        <html>
        <head>
            <style>
                body { font-family: Arial, sans-serif; line-height: 1.6; color: #333; }
                .container { max-width: 600px; margin: 0 auto; padding: 20px; }
                .header { background: #1e3a5f; color: #fff; padding: 5px; text-align: center; border-radius: 8px 8px 0 0; }
				.content { background: #f9fafb; padding: 20px; border: 1px solid #e5e7eb; }
                .info-box { background: white; padding: 15px; border-radius: 6px; margin: 10px 0; border-left: 4px solid #10b981; }
                .btn { display: inline-block; background: #10b981; color: white; padding: 12px 24px; text-decoration: none; border-radius: 6px; margin-top: 15px; }
                .footer { text-align: center; padding: 15px; color: #6b7280; font-size: 12px; }
            </style>
        </head>
        <body>
            <div class='container'>
                <div class='header'>
                    <h2 style='margin:0;'>Document Shared</h2>
                </div>
                <div class='content'>
                    <p>Hello,</p>
                    <p>Document(s) have been shared with you for:</p>
                    
                    <div class='info-box'>
                        <strong>Document:</strong> {$documentName}
                    </div>
                    
                    " . ($additionalMessage ? "<p><strong>Message:</strong><br>" . nl2br(htmlspecialchars($additionalMessage)) . "</p>" : "") . "
                    
                    <p>Click the button below to view/download the document:</p>
                    
                    <a href='{$fileUrl}' class='btn'>View Document</a>
                </div>
                <div class='footer'>
                    <p>This is an automated message from Document Management System.</p>
                </div>
            </div>
        </body>
        </html>";
        
        $this->email->message($message);
        
        // Attach the document file if it exists
        $attached = false;
        $attachedFileName = '';
        
        if (!empty($documentId)) {
            // Get file path from database using document_id
            $doc = $this->db->where('id', $documentId)->get('uploaded_documents')->row();
            
            if ($doc && !empty($doc->file_name)) {
                $filePath = FCPATH . 'uploads/documents/' . $doc->file_name;
                
                if (file_exists($filePath)) {
                    $this->email->attach($filePath);
                    $attached = true;
                    $attachedFileName = $doc->file_name;
                } else {
                    log_message('error', 'Document file not found: ' . $filePath);
                }
            } else {
                log_message('error', 'Document not found in database for ID: ' . $documentId);
            }
        } else {
            log_message('error', 'No document_id provided for email attachment');
        }
        
        if ($this->email->send()) {
            $message = 'Document shared successfully';
            if ($attached) {
                $message .= ' with attachment: ' . $attachedFileName;
            }
            echo json_encode(['status' => 'success', 'message' => $message]);
        } else {
            log_message('error', 'Email failed: ' . $this->email->print_debugger(['headers', 'subject', 'body']));
            echo json_encode(['status' => 'error', 'message' => 'Failed to send email. Please try again.']);
        }
    }
    
    /**
     * Convert month name or number to two-digit number format
     * @param string $month - Month name (e.g., "December", "Jan") or number (e.g., "12", "1", "01")
     * @return string - Two-digit month number (e.g., "12", "01")
     */
    private function _convertMonthToNumber($month)
    {
        // If already a number, just pad it
        if (is_numeric($month)) {
            return str_pad($month, 2, '0', STR_PAD_LEFT);
        }
        
        // Month name to number mapping
        $months = [
            'january' => '01', 'jan' => '01',
            'february' => '02', 'feb' => '02',
            'march' => '03', 'mar' => '03',
            'april' => '04', 'apr' => '04',
            'may' => '05',
            'june' => '06', 'jun' => '06',
            'july' => '07', 'jul' => '07',
            'august' => '08', 'aug' => '08',
            'september' => '09', 'sep' => '09', 'sept' => '09',
            'october' => '10', 'oct' => '10',
            'november' => '11', 'nov' => '11',
            'december' => '12', 'dec' => '12'
        ];
        
        $key = strtolower(trim($month));
        
        if (isset($months[$key])) {
            return $months[$key];
        }
        
        // If no match, return padded original (might be already numeric string)
        return str_pad($month, 2, '0', STR_PAD_LEFT);
    }
}