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

use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Writer\Xlsx;

class Dashboard extends CI_Controller {

	public function __construct()
    {
        parent::__construct();
        $this->load->database();
        $this->load->helper(['url', 'form', 'download', 'security']);
        $this->load->library(['session', 'upload','zip']);
        $this->load->model('Dashboard_model');
        
        // Check authentication for all methods except public ones
        $this->_check_auth();
    }
    
    /**
     * Check authentication for protected routes
     */
    private function _check_auth()
    {
        $login_id = $this->session->userdata('id');
        if (empty($login_id)) {
            // For AJAX requests, return JSON error
            if ($this->input->is_ajax_request()) {
                echo json_encode(['success' => false, 'message' => 'Session expired']);
                exit;
            }
            redirect('login');
        }
    }
    
    /**
     * Validate company access for current user
     */
    private function _validate_company_access($company_ids)
    {
        $login_id = $this->session->userdata('id');
        $role_id = $this->session->userdata('role_id');
        
        if (empty($role_id)) {
            $role_id = $this->Dashboard_model->getUserRole($login_id);
        }
        
        // Admins have access to all
        if ($this->Dashboard_model->isAdmin($role_id)) {
            return true;
        }
        
        // Get allowed companies for user
        $allowed = $this->Dashboard_model->getUserAllowedCompanyIds($login_id, $role_id);
        
        // Check if all requested companies are allowed
        foreach ($company_ids as $company_id) {
            if (!in_array($company_id, $allowed)) {
                return false;
            }
        }
        
        return true;
    }
    
    /**
     * Encrypt filter parameters for secure URL
     */
    private function _encrypt_filter($companies, $year)
    {
        $data = json_encode([
            'companies' => $companies,
            'year' => $year,
            'ts' => time() // Timestamp to prevent replay
        ]);
        
        $key = $this->config->item('encryption_key');
        $encrypted = base64_encode(openssl_encrypt($data, 'AES-256-CBC', $key, 0, substr(md5($key), 0, 16)));
        
        // Make URL safe
        return rtrim(strtr($encrypted, '+/', '-_'), '=');
    }
    
    /**
     * Decrypt filter parameters from URL
     */
    private function _decrypt_filter($encrypted)
    {
        try {
            // Reverse URL-safe encoding
            $encrypted = base64_decode(strtr($encrypted, '-_', '+/'));
            
            $key = $this->config->item('encryption_key');
            $decrypted = openssl_decrypt($encrypted, 'AES-256-CBC', $key, 0, substr(md5($key), 0, 16));
            
            if ($decrypted === false) {
                return null;
            }
            
            $data = json_decode($decrypted, true);
            
            // Optional: Check timestamp to prevent old links (e.g., 24 hours)
            // if (isset($data['ts']) && (time() - $data['ts']) > 86400) {
            //     return null;
            // }
            
            return $data;
        } catch (Exception $e) {
            log_message('error', 'Filter decryption failed: ' . $e->getMessage());
            return null;
        }
    }
    
    /**
     * Generate encrypted URL for dashboard filters
     * Called via AJAX from the view
     */
    public function getEncryptedUrl()
    {
        $companies = $this->input->post('companies');
        $year = $this->input->post('year');
        
        if (is_string($companies)) {
            $companies = array_filter(array_map('intval', explode(',', $companies)));
        }
        
        $encrypted = $this->_encrypt_filter($companies, $year);
        
        echo json_encode([
            'success' => true,
            'url' => site_url('dashboard/dashboard?f=' . $encrypted)
        ]);
    }
    
    /**
     * Generate encrypted URL for upload page
     * Called via AJAX from the dashboard view
     */
    public function getEncryptedUploadUrl()
    {
        $company_id = $this->input->post('company_id');
        $authority_id = $this->input->post('authority_id');
        $type_id = $this->input->post('type_id');
        $month = $this->input->post('month');
        $year = $this->input->post('year');
        $readonly = $this->input->post('readonly');
        $from = $this->input->post('from');
        
        $data = json_encode([
            'company_id' => (int)$company_id,
            'authority_id' => (int)$authority_id,
            'type_id' => (int)$type_id,
            'month' => $month,
            'year' => (int)$year,
            'readonly' => $readonly,
            'from' => $from,
            'ts' => time()
        ]);
        
        $key = $this->config->item('encryption_key');
        $encrypted = base64_encode(openssl_encrypt($data, 'AES-256-CBC', $key, 0, substr(md5($key), 0, 16)));
        
        // Make URL safe
        $encrypted = rtrim(strtr($encrypted, '+/', '-_'), '=');
        
        echo json_encode([
            'success' => true,
            'url' => site_url('upload/index/' . $company_id . '?p=' . $encrypted)
        ]);
    }
    
	/**
	 * 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 index()
	{
		redirect('dashboard/dashboard');
	}
	
	public function dashboard()
    {   
		$this->session->set_userdata('menu','Dashboard');
		$login_id = $this->session->userdata('id');
		if($login_id=='') {
			redirect('login');
		}

		// Get user role information
		$role_id = $this->session->userdata('role_id');
		if (empty($role_id)) {
			$role_id = $this->Dashboard_model->getUserRole($login_id);
		}
		$role_name = $this->Dashboard_model->getRoleName($role_id);
		// Use isSuperAdmin for access control - only Super Admin has unrestricted access
		$is_super_admin = $this->Dashboard_model->isSuperAdmin($role_id);

		// Get companies that user is allowed to access based on role
		$allowedCompanies = $this->Dashboard_model->getUserAllowedCompanies($login_id, $role_id);
		$allowedCompanyIds = $this->Dashboard_model->getUserAllowedCompanyIds($login_id, $role_id);

		// Check for encrypted filter parameter first
		$encryptedFilter = $this->input->get('f');
		$filterYear = null;
		$requestedCompanyIds = null;
		
		if ($encryptedFilter) {
			// Decrypt the filter parameter
			$decrypted = $this->_decrypt_filter($encryptedFilter);
			if ($decrypted) {
				// Don't cast to int - 'all' is a valid string value
				$filterYear = isset($decrypted['year']) ? $decrypted['year'] : null;
				$requestedCompanyIds = isset($decrypted['companies']) ? $decrypted['companies'] : null;
			}
		}
		
		// Fallback to plain parameters (for backward compatibility during transition)
		/*if ($filterYear === null) {
			$filterYear = sanitize_input($this->input->get('year'), 'int');
		}*/

		if ($filterYear === null) {
			$filterYear = $this->input->get('year'); // do NOT cast to int
		}

		$currentYear = date('Y');
		
		// Default to 'all' to show records from all years (based on each company's start date)
		if (!$filterYear || ($filterYear !== 'all' && (!is_numeric($filterYear) || $filterYear < 2020 || $filterYear > $currentYear))) {
			$filterYear = 'all'; // Default to all years
		}

		if ($requestedCompanyIds === null && $this->input->get('companies')) {
			$rawCompanyIds = $this->input->get('companies');
			$requestedCompanyIds = array_filter(
				array_map('intval', explode(',', $rawCompanyIds)),
				function($id) { return $id > 0; }
			);
		}
		
		// Validate that requested companies are within allowed companies
		if ($requestedCompanyIds !== null && !$is_super_admin) {
			// For non-super-admin users (Admin and User), filter out any companies they don't have access to
			$requestedCompanyIds = array_intersect($requestedCompanyIds, $allowedCompanyIds ?: []);
			if (empty($requestedCompanyIds)) {
				$requestedCompanyIds = $allowedCompanyIds; // Default to all allowed companies
			}
		}
		
		// Determine final company filter to use
		// For super admin: null means all, or specific selection
		// For admin/user: must be within allowed companies
		$companyIds = $requestedCompanyIds;
		if (!$is_super_admin && $companyIds === null) {
			// Non-super-admin with no filter: use their allowed companies
			$companyIds = $allowedCompanyIds;
		}

		// LAZY LOADING: Only load favourite tab data on initial page load
		// Other tabs will be loaded via AJAX when user clicks on them
		$favourites = $this->Dashboard_model->getAllFavourites($login_id, $companyIds);

		$authorityIds = null;
		if ($role_id == '3') {
			$authorityIds = get_allowed_authorities();
		}
		
		log_message('error', 'DASHBOARD CONTROLLER → authorityIds: ' . json_encode($authorityIds));
		// Get counts (lightweight query for dashboard cards)
		$counts = $this->Dashboard_model->getDashboardCounts($login_id, $companyIds, $authorityIds, $filterYear);

		log_message('error', 'DASHBOARD CONTROLLER → counts: ' . $counts['upcomimg']);

		$data = [
			'counts' => $counts,
			'favourites' => $favourites,
			// Empty arrays for other tabs - will be loaded via AJAX
			'pending_documents' => [],
			'overdue_documents' => [],
			'upcoming_documents' => [],
			'show_documents' => [],
			// Lazy loading flag
			'lazy_loading' => true,
			'companies' => $allowedCompanies, // Only show allowed companies in filter
			'allowed_company_ids' => $allowedCompanyIds,
			'selected_companies' => $requestedCompanyIds,
			'selected_year' => $filterYear,
			'current_month' => date('F Y'),
			'next_month' => date('F Y', strtotime('+1 month')),
			// Role information
			'user_role_id' => $role_id,
			'user_role_name' => $role_name,
			'is_admin' => $this->Dashboard_model->isAdmin($role_id),
			'is_super_admin' => $is_super_admin,
			// Permission flags
			'can_view' => can_view(),
			'can_edit' => can_edit(),
			'can_delete' => can_delete()
		];

		$this->load->view('templates/header');
		$this->load->view('dashboard', $data);
		$this->load->view('templates/footer');
	}
	/**
	 * Toggle favourite status for a document
	 */
	public function toggleFavourite()
	{
		$login_id = $this->session->userdata('id');
		if (!$login_id) {
			echo json_encode(['success' => false, 'message' => 'Not logged in']);
			return;
		}

		$upload_id = $this->input->post('upload_id');
		if (!$upload_id) {
			echo json_encode(['success' => false, 'message' => 'Invalid upload ID']);
			return;
		}

		$result = $this->Dashboard_model->toggleFavourite($upload_id, $login_id);
		echo json_encode(['success' => true, 'data' => $result]);
	}

	/**
	 * Add document to favourites (without toggle - only adds)
	 */
	public function addToFavourite()
	{
		$login_id = $this->session->userdata('id');
		if (!$login_id) {
			echo json_encode(['success' => false, 'message' => 'Not logged in']);
			return;
		}

		$upload_id = $this->input->post('upload_id');
		if (!$upload_id) {
			echo json_encode(['success' => false, 'message' => 'Invalid upload ID']);
			return;
		}

		$result = $this->Dashboard_model->addToFavourite($upload_id, $login_id);
		echo json_encode(['success' => true, 'data' => $result]);
	}

	/**
	 * Add month-level favourite (groups all documents for a month)
	 */
	public function addMonthFavourite()
	{
		$login_id = $this->session->userdata('id');
		if (!$login_id) {
			echo json_encode(['success' => false, 'message' => 'Not logged in']);
			return;
		}

		$company_id = $this->input->post('company_id');
		$type_id = $this->input->post('type_id');
		$authority_id = $this->input->post('authority_id');
		$year = $this->input->post('year');
		$month = $this->input->post('month');

		if (!$company_id || !$type_id || !$year || !$month) {
			echo json_encode(['success' => false, 'message' => 'Missing required parameters']);
			return;
		}

		$result = $this->Dashboard_model->addMonthFavourite($login_id, $company_id, $type_id, $authority_id, $year, $month);
		echo json_encode($result);
	}

	/**
	 * Remove month-level favourite
	 */
	public function removeMonthFavourite()
	{
		$login_id = $this->session->userdata('id');
		if (!$login_id) {
			echo json_encode(['success' => false, 'message' => 'Not logged in']);
			return;
		}

		$favourite_id = $this->input->post('favourite_id');
		if (!$favourite_id) {
			echo json_encode(['success' => false, 'message' => 'Invalid favourite ID']);
			return;
		}

		$result = $this->Dashboard_model->removeMonthFavourite($favourite_id, $login_id);
		echo json_encode(['success' => $result, 'message' => $result ? 'Removed from favourites' : 'Failed to remove']);
	}

	/**
	 * Get favourite count and limit status
	 */
	public function getFavouriteStatus()
	{
		$login_id = $this->session->userdata('id');
		if (!$login_id) {
			echo json_encode(['success' => false, 'message' => 'Not logged in']);
			return;
		}

		$count = $this->Dashboard_model->getFavouriteCount($login_id);
		$max_limit = 10;
		$can_add = $count < $max_limit;

		echo json_encode([
			'success' => true,
			'count' => $count,
			'max_limit' => $max_limit,
			'can_add' => $can_add,
			'remaining' => $max_limit - $count
		]);
	}

	/**
	 * Download month-level favourite as ZIP with merged PDF
	 */
	public function downloadMonthFavourite()
	{
		$login_id = $this->session->userdata('id');
		if (!$login_id) {
			show_error('Not logged in', 403);
			return;
		}

		$company_id = $this->input->get('company_id');
		$type_id = $this->input->get('type_id');
		$year = $this->input->get('year');
		$month = $this->input->get('month');

		if (!$company_id || !$type_id || !$year || !$month) {
			show_error('Missing parameters', 400);
			return;
		}

		// Get all documents for this month
		$documents = $this->Dashboard_model->getMonthFavouriteDocuments($company_id, $type_id, $year, $month);

		if (empty($documents)) {
			show_error('No documents found', 404);
			return;
		}

		// Create ZIP file
		$zipFileName = "documents_{$documents[0]['company_name']}_{$documents[0]['type_name']}_{$year}_{$month}.zip";
		$zipFilePath = sys_get_temp_dir() . '/' . $zipFileName;

		$zip = new ZipArchive();
		if ($zip->open($zipFilePath, ZipArchive::CREATE | ZipArchive::OVERWRITE) !== TRUE) {
			show_error('Cannot create ZIP file', 500);
			return;
		}

		// Add each document to ZIP
		foreach ($documents as $doc) {
			$filePath = FCPATH . $doc['file_path'];
			if (file_exists($filePath)) {
				$zip->addFile($filePath, $doc['file_name']);
			}
		}

		$zip->close();

		// Send ZIP to browser
		header('Content-Type: application/zip');
		header('Content-Disposition: attachment; filename="' . $zipFileName . '"');
		header('Content-Length: ' . filesize($zipFilePath));
		header('Cache-Control: no-cache, must-revalidate');
		
		readfile($zipFilePath);
		
		// Clean up
		unlink($zipFilePath);
		exit;
	}

	/**
	 * Get tab data via AJAX (for lazy loading)
	 */
	public function getTabData()
	{
		$login_id = $this->session->userdata('id');
		if (!$login_id) {
			echo json_encode(['success' => false, 'message' => 'Not logged in']);
			return;
		}

		$tab = $this->input->post('tab');
		$filterYear = $this->input->post('year');
		$companyIdsRaw = $this->input->post('companies');
		
		// Parse company IDs
		$companyIds = null;
		if (!empty($companyIdsRaw)) {
			if (is_string($companyIdsRaw)) {
				$companyIds = array_filter(array_map('intval', explode(',', $companyIdsRaw)));
			} elseif (is_array($companyIdsRaw)) {
				$companyIds = array_filter(array_map('intval', $companyIdsRaw));
			}
		}
		
		// Get role info for company access validation
		$role_id = $this->session->userdata('role_id');
		if (empty($role_id)) {
			$role_id = $this->Dashboard_model->getUserRole($login_id);
		}
		// Only Super Admin has unrestricted company access
		$is_super_admin = $this->Dashboard_model->isSuperAdmin($role_id);
		
		// Non-super-admin users (Admin and User): must use their allowed companies
		if (!$is_super_admin) {
			$allowedCompanyIds = $this->Dashboard_model->getUserAllowedCompanyIds($login_id, $role_id);
			if (empty($companyIds)) {
				// No filter specified - use all allowed companies
				$companyIds = $allowedCompanyIds;
			} else {
				// Filter specified - ensure it's within allowed companies
				$companyIds = array_intersect($companyIds, $allowedCompanyIds ?: []);
				if (empty($companyIds)) {
					$companyIds = $allowedCompanyIds;
				}
			}
		}
		
		// Validate year
		$currentYear = date('Y');
		if (empty($filterYear) || ($filterYear !== 'all' && (!is_numeric($filterYear) || $filterYear < 2020 || $filterYear > $currentYear))) {
			$filterYear = $currentYear;
		}
		
		// Get authority IDs for User role (role 3) for additional filtering
		$authorityIds = null;
		if ($role_id == '3') {
			$authorityIds = get_allowed_authorities();
		}
		
		$data = [];

		switch ($tab) {
			case 'favourite':
				$data = $this->Dashboard_model->getAllFavourites($login_id, $companyIds);
				break;
			case 'pending':
				$data = $this->Dashboard_model->getPendingDocuments($companyIds, $filterYear, $authorityIds);
				break;
			case 'overdue':
				$data = $this->Dashboard_model->getOverdueDocuments($companyIds, $filterYear, $authorityIds);
				break;
			case 'upcoming':
				$data = $this->Dashboard_model->getUpcomingDocuments($companyIds, $filterYear, $authorityIds);
				break;
			case 'uploaded':
				$data = $this->Dashboard_model->getUploadedDocumentsGrouped($companyIds, $filterYear, $authorityIds);
				break;
			default:
				echo json_encode(['success' => false, 'message' => 'Invalid tab']);
				return;
		}

		echo json_encode(['success' => true, 'data' => $data, 'tab' => $tab]);
	}

	/**
	 * Get dashboard counts via AJAX
	 */
	public function getCounts()
	{
		$login_id = $this->session->userdata('id');
		if (!$login_id) {
			echo json_encode(['success' => false, 'message' => 'Not logged in']);
			return;
		}

		// Get user role and allowed companies
		$role_id = $this->session->userdata('role_id');
		if (empty($role_id)) {
			$role_id = $this->Dashboard_model->getUserRole($login_id);
		}
		
		// Get the company IDs the user is allowed to access
		$is_super_admin = $this->Dashboard_model->isSuperAdmin($role_id);
		$companyIds = null;
		
		if (!$is_super_admin) {
			// Admin and User: only their assigned companies
			$companyIds = $this->Dashboard_model->getUserAllowedCompanyIds($login_id, $role_id);
		}
		
		// Get authority IDs for User role (role 3)
		$authorityIds = null;
		if ($role_id == '3') {
			$authorityIds = get_allowed_authorities();
		}

		$counts = $this->Dashboard_model->getDashboardCounts($login_id, $companyIds, $authorityIds);
		echo json_encode(['success' => true, 'data' => $counts]);
	}

	public function faq() {
		$this->load->view('templates/layout');
		$this->load->view('faq');
		$this->load->view('templates/footer');
	}
	public function home() {
		$this->load->view('home');
	}
	public function userAccess() {
		$this->session->set_userdata('menu','access');
		$login_id = $this->session->userdata('id');
		if($login_id=='') {
			redirect('login');
		}
		
		$query = "select * from role where status='1'";
		$select_query = $this->db->query($query);	
		$role_data = $select_query->result_array();
		$this->load->view('templates/layout');
		$this->load->view('user_access',array('role_data'=>$role_data));
	}
	/*public function saveAccess() {
		$this->session->set_userdata('menu','access');
		$login_id = $this->session->userdata('id');
		if($login_id=='') {
			redirect('login');
		}
		$role_id = $_POST['role_id'];
		$view = implode(',',$_POST['view']);
		$edit = implode(',',$_POST['edit']);
		
		$user_query = "insert into user_priviledges (user_id, view, edit) values('$role_id','$view','$edit'	)";
		$user_sql = $this->db->query($user_query);
		
		$log_query ="insert into log_table(description, action, created_time, user_id) values('New User Added Successfully','New User Added','$created_date','$login_id')";
		$log_insert = $this->db->query($log_query);

		echo '<pre>'; print_r($_POST);exit;
	}*/

    // Logout function
	public function logout()
    {
        $session = session();
        $session->destroy();
        return redirect()->to('login');
    }
	
	public function changePassword() {
		$login_id = $this->session->userdata('id');
		if($login_id=='') {
			redirect('login');
		}
		$this->load->view('templates/layout');
		$this->load->view('change_password');
	}
	public function agree() {
		$login_id = $this->session->userdata('id');
		if($login_id=='') {
			redirect('login');
		}
		$id = $this->session->userdata('id');
		$sql="update users set verified = '1' where id= '$id'";
		$query = $this->db->query($sql);
		echo true;
	}
	public function getRoleAccess()
	{
		$role_id = $this->input->post('role_id');

		$access = $this->db->get_where('user_priviledges', ['role_id' => $role_id])->row();

		$view = [];
		$edit = [];

		if ($access) {
			if (!empty($access->view)) {
				$view = explode(',', str_replace(' ', '', $access->view));
			}
			if (!empty($access->edit)) {
				$edit = explode(',', str_replace(' ', '', $access->edit));
			}
		}

		echo json_encode(['view' => $view, 'edit' => $edit]);
	}
	public function saveAccess()
	{
		$role_id = $this->input->post('role_id');
		$view = $this->input->post('view');
		$edit = $this->input->post('edit');

		$view_str = is_array($view) ? implode(',', $view) : '';
		$edit_str = is_array($edit) ? implode(',', $edit) : '';

		$data = [
			'role_id' => $role_id,
			'view' => $view_str,
			'edit' => $edit_str
		];

		$existing = $this->db->get_where('role_access', ['role_id' => $role_id])->row();
		if ($existing) {
			$this->db->where('role_id', $role_id)->update('role_access', $data);
		} else {
			$this->db->insert('role_access', $data);
		}

		$this->session->set_flashdata('success', 'Access saved successfully!');
		redirect('dashboard/access');
	}
	public function updateSingleAccess()
	{
		$role_id = $this->input->post('role_id');
		$module = $this->input->post('module');
		$access_type = $this->input->post('access_type'); // view or edit
		$value = $this->input->post('value'); // 1 or 0

		$row = $this->db->get_where('user_priviledges', ['role_id' => $role_id])->row();

		$updated = [];

		if ($row) {
			$access_arr = explode(',', $row->$access_type);
			$access_arr = array_map('trim', $access_arr);

			if ($value == 1 && !in_array($module, $access_arr)) {
				$access_arr[] = $module;
			} elseif ($value == 0 && in_array($module, $access_arr)) {
				$access_arr = array_diff($access_arr, [$module]);
			}

			$updated[$access_type] = implode(',', $access_arr);
			$this->db->where('role_id', $role_id)->update('user_priviledges', $updated);
		} else {
			$updated = [
				'role_id' => $role_id,
				$access_type => $value ? $module : ''
			];
			$this->db->insert('user_priviledges', $updated);
		}

		echo 'success';
	}
	
	public function export_documents_excel()
	{
		// Get tab parameter to determine which data to export
		$tab = $this->input->get('tab') ?? 'uploaded';
		$companyName = $this->input->get('company') ?? 'Company';
		$companyName = preg_replace('/[^a-zA-Z0-9\s]/', '', $companyName); // Sanitize for filename
		$companyName = str_replace(' ', '_', trim($companyName));
		
		// Get selected year from parameter
		$selectedYear = $this->input->get('year') ?? date('Y');
		if ($selectedYear === 'all') {
			$selectedYear = 'all_years';
		}
		
		// Get user session data
		$login_id = $this->session->userdata('id');
		$role_id = $this->session->userdata('role_id');
		$company_id = $this->session->userdata('company_id');
		$companyIds = !empty($company_id) ? [$company_id] : null;
		$filterYear = date('Y');
		
		// Get authority IDs for User role (role 3)
		$authorityIds = null;
		if ($role_id == '3') {
			$authorityIds = get_allowed_authorities();
		}
		
		// Get data based on tab
		$data = [];
		$headers = [];
		$tabTitle = '';
		
		switch ($tab) {
			case 'favourite':
				$data = $this->Dashboard_model->getAllFavourites($login_id, $companyIds);
				$headers = ['S.No', 'Company', 'Authority', 'Document Head', 'Document', 'Frequency', 'Year', 'Month'];
				$tabTitle = 'Favourites';
				break;
			case 'pending':
				$data = $this->Dashboard_model->getPendingDocuments($companyIds, $filterYear, $authorityIds);
				$headers = ['S.No', 'Company', 'Authority', 'Document Head', 'Frequency', 'Period', 'Due Date', 'Status'];
				$tabTitle = 'Pending';
				break;
			case 'overdue':
				$data = $this->Dashboard_model->getOverdueDocuments($companyIds, $filterYear, $authorityIds);
				$headers = ['S.No', 'Company', 'Authority', 'Document Head', 'Frequency', 'Period', 'Due Date', 'Status'];
				$tabTitle = 'Overdue';
				break;
			case 'upcoming':
				$data = $this->Dashboard_model->getUpcomingDocuments($companyIds, $filterYear, $authorityIds);
				$headers = ['S.No', 'Company', 'Authority', 'Document Head', 'Frequency', 'Period', 'Due Date', 'Status'];
				$tabTitle = 'Upcoming';
				break;
			default: // uploaded
				$data = $this->_getUploadedDocuments();
				$headers = ['S.No', 'Company', 'Authority', 'Document Type', 'Year', 'Month', 'Documents', 'Uploaded Date', 'Frequency'];
				$tabTitle = 'Uploaded';
				break;
		}
		
		if (ob_get_length()) ob_end_clean();
		ini_set('zlib.output_compression', 'Off');
		
		$spreadsheet = new Spreadsheet();
		$sheet = $spreadsheet->getActiveSheet();

		// Set header row
		$sheet->fromArray($headers, NULL, 'A1');

		// Bold header row
		$lastCol = chr(64 + count($headers)); // A=65, so +64 maps 1->A, 2->B, etc.
		$sheet->getStyle('A1:' . $lastCol . '1')->getFont()->setBold(true);

		// Fill data based on tab type
		$row = 2;
		foreach ($data as $doc) {
			$doc = (array)$doc; // Convert to array if object
			
			switch ($tab) {
				case 'favourite':
					$monthNum = (int)($doc['document_month'] ?? 0);
					$monthName = ($monthNum >= 1 && $monthNum <= 12) ? date('F', mktime(0, 0, 0, $monthNum, 1)) : '';
					$sheet->setCellValue("A$row", $row-1);
					$sheet->setCellValue("B$row", $doc['company_name'] ?? '');
					$sheet->setCellValue("C$row", $doc['authority_name'] ?? '');
					$sheet->setCellValue("D$row", $doc['type_name'] ?? '');
					$sheet->setCellValue("E$row", $doc['document_name'] ?? '');
					$sheet->setCellValue("F$row", $doc['frequency'] ?? '');
					$sheet->setCellValue("G$row", $doc['document_year'] ?? '');
					$sheet->setCellValue("H$row", $monthName);
					break;
				case 'pending':
				case 'overdue':
				case 'upcoming':
					$periodMonth = (int)($doc['doc_period_month'] ?? $doc['overdue_month'] ?? 0);
					$periodYear = $doc['doc_period_year'] ?? $doc['overdue_year'] ?? '';
					$periodMonthName = ($periodMonth >= 1 && $periodMonth <= 12) ? date('M', mktime(0, 0, 0, $periodMonth, 1)) : '';
					$dueDate = $doc['due_date'] ?? '';
					$sheet->setCellValue("A$row", $row-1);
					$sheet->setCellValue("B$row", $doc['company_name'] ?? '');
					$sheet->setCellValue("C$row", $doc['authority_name'] ?? '');
					$sheet->setCellValue("D$row", $doc['type_name'] ?? '');
					$sheet->setCellValue("E$row", $doc['frequency'] ?? '');
					$sheet->setCellValue("F$row", $periodMonthName . ' ' . $periodYear);
					$sheet->setCellValue("G$row", $dueDate);
					$sheet->setCellValue("H$row", ucfirst($tab));
					break;
				default: // uploaded
					$documentList = !empty($doc['documents']) ? implode(', ', $doc['documents']) : '';
					$monthNum = (int)($doc['document_month'] ?? 0);
					$monthName = ($monthNum >= 1 && $monthNum <= 12) ? date('F', mktime(0, 0, 0, $monthNum, 1)) : $doc['document_month'];
					$sheet->setCellValue("A$row", $row-1);
					$sheet->setCellValue("B$row", $doc['company_name'] ?? '');
					$sheet->setCellValue("C$row", $doc['authority_name'] ?? '');
					$sheet->setCellValue("D$row", $doc['type_name'] ?? '');
					$sheet->setCellValue("E$row", $doc['document_year'] ?? '');
					$sheet->setCellValue("F$row", $monthName);
					$sheet->setCellValue("G$row", $documentList);
					$sheet->setCellValue("H$row", $doc['uploaded_date'] ?? '');
					$sheet->setCellValue("I$row", $doc['frequency'] ?? '');
					break;
			}
			$row++;
		}
		
		// Auto-size columns
		foreach (range('A', $lastCol) as $col) {
			$sheet->getColumnDimension($col)->setAutoSize(true);
		}

		// Set filename: tab_companyname_year.xlsx
		$filename = strtolower($tabTitle) . '_' . $companyName . '_' . $selectedYear . '.xlsx';

		// Send headers to browser
		header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
		header('Content-Disposition: attachment; filename="' . $filename . '"');
		header('Cache-Control: max-age=0');

		$writer = new Xlsx($spreadsheet);
		$writer->save('php://output');
		exit;
	}

	private function _getUploadedDocuments(){
		//Total uploaded documents with Document Names, Type Names and related Authoritys name
		$this->db->select('
			DISTINCT c.company_name,
			st.type_name,
			a.authority_name,
			d.document_name,
			st.frequency,
			ud.document_year,
			ud.document_month,
			ud.uploaded_at
		', FALSE);  // FALSE to prevent CI from escaping DISTINCT

		$this->db->from('uploaded_documents ud');
		$this->db->join('company c', 'ud.company_id = c.id', 'left');
		$this->db->join('sub_type st', 'ud.type_id = st.id', 'left');
		$this->db->join('authority a', 'CAST(st.authority_id AS INT) = a.id', 'left');
		$this->db->join('documents d', 'ud.document_id = d.id', 'left');
		$this->db->where('ud.is_deleted', 0);

		// ✅ Add ORDER BY fields (must be in SELECT list for DISTINCT)
		$this->db->order_by('c.company_name', 'ASC');
		$this->db->order_by('st.type_name', 'ASC');
		$this->db->order_by('ud.document_year', 'DESC');
		$this->db->order_by('ud.document_month', 'DESC');

		$query = $this->db->get();
		$resultDocComplete = $query->result();

		$groupedData = [];

		if (!empty($resultDocComplete)) {
			foreach ($resultDocComplete as $doc) {

				$key = $doc->company_name . '|' . $doc->authority_name . '|' . $doc->type_name . '|' . $doc->document_year . '|' . $doc->document_month;

				if (!isset($groupedData[$key])) {
					$groupedData[$key] = [
						'company_name' => $doc->company_name,
						'authority_name' => $doc->authority_name,
						'type_name' => $doc->type_name,
						'document_year' => $doc->document_year,
						'document_month' => $doc->document_month,
						'documents' => [],
						'uploaded_date' => $doc->uploaded_at,
						'frequency' =>$doc->frequency,
					];
				}
				$groupedData[$key]['documents'][] = $doc->document_name;
			}
		}
		return $groupedData;
	}

	/**
	 * View merged PDF for a document group
	 * Merges all uploaded PDFs for a specific type/company/month/year in document_name sequence
	 */
	public function viewMergedPdf()
	{
		$login_id = $this->session->userdata('id');
		if (!$login_id) {
			show_error('Not logged in', 403);
			return;
		}

		$type_id = $this->input->get('type_id');
		$company_id = $this->input->get('company_id');
		$month = $this->input->get('month');
		$year = $this->input->get('year');

		if (!$type_id || !$company_id || !$month || !$year) {
			show_error('Missing required parameters', 400);
			return;
		}

		// Get document sequence from sub_type
		$this->db->select('document_name');
		$this->db->where('id', $type_id);
		$subType = $this->db->get('sub_type')->row();

		if (!$subType || empty($subType->document_name)) {
			show_error('Document type not found', 404);
			return;
		}

		// Parse document sequence (comma-separated document IDs)
		$docSequence = array_map('trim', explode(',', $subType->document_name));

		// Get all uploaded documents for this group
		$this->db->select('ud.id, ud.file_path, ud.document_id, d.document_name');
		$this->db->from('uploaded_documents ud');
		$this->db->join('documents d', 'ud.document_id = d.id', 'left');
		$this->db->where('ud.type_id', $type_id);
		$this->db->where('ud.company_id', $company_id);
		$this->db->where('CAST(NULLIF(TRIM(ud.document_month::text), \'\') AS INTEGER) =', (int)$month, false);
		$this->db->where('CAST(NULLIF(TRIM(ud.document_year::text), \'\') AS INTEGER) =', (int)$year, false);
		$this->db->where('ud.is_deleted', 0);
		$uploadedDocs = $this->db->get()->result_array();

		if (empty($uploadedDocs)) {
			show_error('No documents found', 404);
			return;
		}

		// Sort documents based on sequence in sub_type.document_name
		$sortedDocs = [];
		foreach ($docSequence as $docId) {
			foreach ($uploadedDocs as $doc) {
				if ($doc['document_id'] == $docId) {
					$sortedDocs[] = $doc;
					break;
				}
			}
		}

		// Add any documents not in sequence (fallback)
		foreach ($uploadedDocs as $doc) {
			$found = false;
			foreach ($sortedDocs as $sorted) {
				if ($sorted['document_id'] == $doc['document_id']) {
					$found = true;
					break;
				}
			}
			if (!$found) {
				$sortedDocs[] = $doc;
			}
		}

		// Collect file paths
		$filePaths = [];
		foreach ($sortedDocs as $doc) {
			if (!empty($doc['file_path'])) {
				$fullPath = FCPATH . $doc['file_path'];
				if (file_exists($fullPath)) {
					// Check if it's a PDF
					$ext = strtolower(pathinfo($fullPath, PATHINFO_EXTENSION));
					if ($ext === 'pdf') {
						$filePaths[] = $fullPath;
					}
				}
			}
		}

		if (empty($filePaths)) {
			show_error('No PDF files found to merge', 404);
			return;
		}

		// If only one PDF, just display it
		if (count($filePaths) === 1) {
			header('Content-Type: application/pdf');
			header('Content-Disposition: inline; filename="document.pdf"');
			readfile($filePaths[0]);
			return;
		}

		// Merge PDFs
		$this->load->library('PdfMergerLib');
		
		// Create temp output file
		$outputFile = FCPATH . 'uploads/temp/merged_' . $type_id . '_' . $company_id . '_' . $month . '_' . $year . '_' . time() . '.pdf';
		
		// Ensure temp directory exists
		$tempDir = FCPATH . 'uploads/temp/';
		if (!is_dir($tempDir)) {
			mkdir($tempDir, 0755, true);
		}

		$merged = $this->pdfmergerlib->merge($filePaths, $outputFile);

		if ($merged && file_exists($outputFile)) {
			// Output the merged PDF
			header('Content-Type: application/pdf');
			header('Content-Disposition: inline; filename="merged_documents.pdf"');
			header('Content-Length: ' . filesize($outputFile));
			readfile($outputFile);
			
			// Clean up temp file after sending
			@unlink($outputFile);
		} else {
			show_error('Failed to merge PDF files', 500);
		}
	}

	/**
	 * Send notification email via SMTP
	 */
	public function sendNotificationEmail()
	{
		$login_id = $this->session->userdata('id');
		if (!$login_id) {
			echo json_encode(['success' => false, 'message' => 'Not logged in']);
			return;
		}

		// Get POST data
		$recipient = $this->input->post('recipient');
		$type_name = $this->input->post('type_name');
		$company_name = $this->input->post('company_name');
		$month = $this->input->post('month');
		$year = $this->input->post('year');
		$type_id = $this->input->post('type_id');
		$company_id = $this->input->post('company_id');
		$authority_id = $this->input->post('authority_id');
		$dueDay    = $this->input->post('due_day');
		$dueMonth = $this->input->post('due_month');
		$dueYear  = $this->input->post('due_year');
		$dueReason = $this->input->post('due_reason');

		if ($dueDay && $dueMonth && $dueYear) {
			// ✅ Use dashboard-calculated final date
			$finalDueDate = sprintf('%02d-%02d-%04d', $dueDay, $dueMonth, $dueYear);
		} else {
			// 🔁 Fallback for older callers
			$finalDueDate = sprintf('01-%02d-%04d', $month, $year);
		}

		// Validate recipient email
		if (empty($recipient) || !filter_var($recipient, FILTER_VALIDATE_EMAIL)) {
			echo json_encode(['success' => false, 'message' => 'Please enter a valid email address']);
			return;
		}

		// Get pending documents for this type
		$this->db->select('d.document_name');
		$this->db->from('mandatory_documents md');
		$this->db->join('documents d', 'md.document_id = d.id');
		$this->db->where('md.type_id', $type_id);
		$pendingDocs = $this->db->get()->result_array();

		// Check which are not uploaded
		$notUploadedDocs = [];
		foreach ($pendingDocs as $doc) {
			$this->db->where('type_id', $type_id);
			$this->db->where('company_id', $company_id);
			$this->db->where('CAST(NULLIF(TRIM(document_month::text), \'\') AS INTEGER) =', (int)$month, false);
			$this->db->where('CAST(NULLIF(TRIM(document_year::text), \'\') AS INTEGER) =', (int)$year, false);
			$this->db->where('is_deleted', 0);
			$this->db->like('file_name', $doc['document_name']);
			$count = $this->db->count_all_results('uploaded_documents');
			
			if ($count == 0) {
				$notUploadedDocs[] = $doc['document_name'];
			}
		}

		// Build month name
		$monthNames = ['', 'January', 'February', 'March', 'April', 'May', 'June', 
		               'July', 'August', 'September', 'October', 'November', 'December'];
		$monthName = $monthNames[(int)$month] ?? $month;

		// Build upload URL
		$uploadUrl = base_url('upload/index/' . $company_id) . 
			'?authority_id=' . $authority_id . 
			'&type_id=' . $type_id . 
			'&month=' . str_pad($month, 2, '0', STR_PAD_LEFT) . 
			'&year=' . $year .
			'&readonly=1&from=notification';

		$today = new DateTime('today');

		// Get due day from sub_type
		/*$dueDay = (int)$this->db
			->select('frequency_start_date')
			->where('id', $type_id)
			->get('sub_type')
			->row()
			->frequency_start_date;

		// Safety fallback
		if ($dueDay < 1 || $dueDay > 31) {
			$dueDay = 1;
		}*/

		// Build due date
		$dueDate =DateTime::createFromFormat('d-m-Y', $finalDueDate);
		
		if ($dueDate < $today) {
			$notificationStatus = 'Overdue';
		} elseif ($dueDate->format('Y-m') === $today->format('Y-m')) {
			$notificationStatus = 'Current';
		} else {
			$notificationStatus = 'Upcoming';
		}

		// Build email content
		//$subject = 'Document Pending: ' . $type_name . ' - ' . $monthName . ' ' . $year;
		$subject = '[' . strtoupper($notificationStatus) . ']' . $company_name . ' - '
         . $type_name . ' - ' . $monthName . ' ' . $year;
	
		 $dueDateFormatted = date(
			'd M Y',
			DateTime::createFromFormat('d-m-Y', $finalDueDate)->getTimestamp()
		);

		$dueReason = trim((string) $dueReason);
		$isPublicHolidayAdjustment = $dueReason !== '' && stripos($dueReason, 'sunday') === false;

		$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: #f8f9fa; padding: 20px; border: 1px solid #ddd; }
				.info-box { background: #fff; padding: 15px; border-radius: 8px; margin: 15px 0; border-left: 4px solid #3b82f6; }
				.pending-docs { background: #fee2e2; padding: 15px; border-radius: 8px; margin: 15px 0; }
				.pending-docs h4 { color: #dc2626; margin-top: 0; }
				.pending-docs ul { margin: 0; padding-left: 20px; }
				.btn { display: inline-block; background: #3b82f6; color: #fff; padding: 12px 24px; text-decoration: none; border-radius: 6px; margin-top: 15px; }
				.btn:hover { background: #2563eb; }
				.footer { text-align: center; padding: 20px; color: #666; font-size: 12px; }
			</style>
		</head>
		<body>
			<div class="container">
				<div class="header">
					<h2>Document Reminder</h2>
				</div>
				<div class="content">
					<p>Hello,</p>
					<p>Please upload the document(s) for the details as below.</p>
					
					<div class="info-box">
						<p><strong>Company:</strong> ' . htmlspecialchars($company_name) . '</p>
						<p><strong>Document Head:</strong> ' . htmlspecialchars($type_name) . '</p>
						<p><strong>Period:</strong> ' . $monthName . ' ' . $year . '</p>
						<p><strong>Due Date: ' . $dueDateFormatted . '</strong></p>';
						if ($isPublicHolidayAdjustment) {
							$message .= '
							<p style="
								margin-top:6px;
								font-size:13px;
								color:#92400e;
								background:#fef3c7;
								padding:6px 10px;
								border-radius:4px;
								display:inline-block;
							">
								ℹ️ ' . htmlspecialchars($dueReason) . '
							</p>
							';
						}
						$message .= '
						<p><strong>Status:</strong> 
						<span style="color: ' . (
							$notificationStatus === 'Overdue' ? '#dc2626' :
							($notificationStatus === 'Current' ? '#ca8a04' : '#2563eb')
						) . '; font-weight: bold;">
							' . $notificationStatus . '
						</span>
						</p>
					</div>';
		
		if (!empty($notUploadedDocs)) {
			$message .= '
					<div class="pending-docs">
						<h4>Documents:</h4>
						<ul>';
			foreach ($notUploadedDocs as $docName) {
				$message .= '<li>' . htmlspecialchars($docName) . '</li>';
			}
			$message .= '
						</ul>
					</div>';
		}
		
		/*$message .= '
					<p>Please upload the required documents by clicking the button below:</p>
					<p style="text-align: center;">
						<a href="' . $uploadUrl . '" class="btn">Upload Documents</a>
					</p>
					<p><small>Note: You will need to login if not already logged in.</small></p>
				</div>
				<div class="footer">
					<p>This is an automated message from Document Management System.</p>
				</div>
			</div>
		</body>
		</html>';*/

		if ($notificationStatus !== 'Upcoming') {

			$ctaText = $notificationStatus === 'Overdue'
				? 'Upload Immediately'
				: 'Upload Documents';
		
			$message .= '
				<p>Please upload the required documents by clicking the button below:</p>
				<p style="text-align: center;">
					<a href="' . $uploadUrl . '" class="btn">' . $ctaText . '</a>
				</p>
				<p><small>Note: You will need to login if not already logged in.</small></p>
			';
		
		} else {
		
			$message .= '
				<p style="margin-top: 15px; color: #2563eb;">
					<strong>Note:</strong> This is an upcoming compliance.
					You can upload the documents once the period becomes active.
				</p>
			';
		}
		
		// Load email config
		$this->config->load('email');
		
		// Email configuration array
		$emailConfig = 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'),
			'smtp_timeout'=> $this->config->item('smtp_timeout'),
			'mailtype'    => $this->config->item('mailtype'),
			'charset'     => $this->config->item('charset'),
			'wordwrap'    => $this->config->item('wordwrap'),
			'newline'     => $this->config->item('newline')
		);

		// Load and initialize email library
		$this->load->library('email');
		$this->email->initialize($emailConfig);

		// Get from address
		$fromEmail = $this->config->item('smtp_user'); // Use SMTP user as sender
		$fromName = $this->config->item('from_name') ?: 'Document Management System';

		$this->email->from($fromEmail, $fromName);
		$this->email->to($recipient);
		$this->email->subject($subject);
		$this->email->message($message);

		// Attach uploaded documents for this type/company/month/year
		$uploadedDocs = $this->db->select('file_name')
		                         ->where('type_id', $type_id)
		                         ->where('company_id', $company_id)
		                         ->where('document_month', str_pad($month, 2, '0', STR_PAD_LEFT))
		                         ->where('document_year', $year)
		                         ->where('is_deleted', 0)
		                         ->get('uploaded_documents')
		                         ->result();
		
		$attachCount = 0;
		foreach ($uploadedDocs as $doc) {
			if (!empty($doc->file_name)) {
				$filePath = FCPATH . 'uploads/documents/' . $doc->file_name;
				if (file_exists($filePath)) {
					$this->email->attach($filePath);
					$attachCount++;
				}
			}
		}

		// Try to send
		try {
			if ($this->email->send()) {
				$msg = 'Email sent successfully to ' . $recipient;
				if ($attachCount > 0) {
					$msg .= ' with ' . $attachCount . ' document(s) attached';
				}
				echo json_encode([
					'success' => true, 
					'message' => $msg
				]);
			} else {
				$error = $this->email->print_debugger(['headers', 'subject', 'body']);
				//log_message('error', 'Email send failed: ' . $error);
				echo json_encode([
					'success' => false, 
					'message' => 'Failed to send email. Check SMTP settings or use Gmail App Password.',
					'debug' => strip_tags($error)
				]);
			}
		} catch (Exception $e) {
			//log_message('error', 'Email exception: ' . $e->getMessage());
			echo json_encode([
				'success' => false, 
				'message' => 'Email error: ' . $e->getMessage()
			]);
		}
	}

	/**
	 * Send reminder email (from Favourite/Uploaded tabs)
	 */
	public function send_reminder_email()
	{
		$mergedFile = null;
		$login_id = $this->session->userdata('id');
		if (!$login_id) {
			echo json_encode(['success' => false, 'message' => 'Not logged in']);
			return;
		}

		// Get POST data
		$recipient = $this->input->post('recipient');
		$subject = $this->input->post('subject');
		$customMessage = $this->input->post('message');
		$company_id = $this->input->post('company_id');
		$type_id = $this->input->post('type_id');
		$month = $this->input->post('month');
		$year = $this->input->post('year');

		// Validate recipient email
		if (empty($recipient) || !filter_var($recipient, FILTER_VALIDATE_EMAIL)) {
			echo json_encode(['success' => false, 'message' => 'Please enter a valid email address']);
			return;
		}

		// Get company info
		$company = $this->db->where('id', $company_id)->get('company')->row();
		$company_name = $company ? $company->company_name : 'Unknown Company';

		// Get type info
		$type = $this->db->where('id', $type_id)->get('sub_type')->row();
		$type_name = $type ? $type->type_name : 'Document';

		$docSequence = [];

		if ($type && !empty($type->document_name)) {
			// Convert "1,4,2,5" → [1,4,2,5]
			$docSequence = array_map('intval', explode(',', $type->document_name));
		}

		$this->load->helper('document');

		$fileBaseName = get_monthly_document_filename($type_name, $year, $month);
		$mergedFile   = null;
		$attachCount  = 0;

		//log_message('debug', '[EMAIL] Base filename resolved: ' . $fileBaseName);

		// Load email config
		$this->config->load('email');
		
		// Email configuration array
		$emailConfig = 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'),
			'smtp_timeout'=> $this->config->item('smtp_timeout'),
			'mailtype'    => $this->config->item('mailtype'),
			'charset'     => $this->config->item('charset'),
			'wordwrap'    => $this->config->item('wordwrap'),
			'newline'     => $this->config->item('newline')
		);

		// Load and initialize email library
		$this->load->library('email');
		$this->email->initialize($emailConfig);

		// Get from address
		$fromEmail = $this->config->item('smtp_user');
		$fromName = $this->config->item('from_name') ?: 'Document Management System';

		// Build email content
		$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: #f8f9fa; padding: 20px; border: 1px solid #ddd; }
				.info-box { background: #fff; 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: 20px; color: #666; font-size: 12px; }
			</style>
		</head>
		<body>
			<div class="container">
				<div class="header">
					<h2>Document Shared</h2>
				</div>
				<div class="content">
					<p>Hello,</p>
					<p>Document(s) have been shared with you for:</p>
					<div class="info-box">
						<p><strong>Company:</strong> ' . htmlspecialchars($company_name) . '</p>
						<p><strong>Document Head:</strong> ' . htmlspecialchars($type_name) . '</p>
						<p><strong>Period:</strong> ' . htmlspecialchars($month) . ' ' . htmlspecialchars($year) . '</p>
					</div>';
		
		if (!empty($customMessage)) {
			$message .= '
					<div class="message-box">
						<p><strong>Message:</strong></p>
						<p>' . nl2br(htmlspecialchars($customMessage)) . '</p>
					</div>';
		}
		
		$message .= '
				</div>
				<div class="footer">
					<p>This is an automated message from Document Management System.</p>
				</div>
			</div>
		</body>
		</html>';

		$this->email->from($fromEmail, $fromName);
		$this->email->to($recipient);
		$this->email->subject($subject ?: 'Document Shared: ' . $company_name . ' - ' .$type_name . ' - ' . $month . ' ' . $year);
		$this->email->message($message);

		// Get upload_id if sending specific document (from Favourite tab)
		$upload_id = $this->input->post('upload_id');
		
		$attachCount = 0;
		
		if (!empty($upload_id)) {

			// ---------- SINGLE DOCUMENT ----------
			$doc = $this->db->select('document_id,file_name')
							->where('id', $upload_id)
							->where('is_deleted', 0)
							->get('uploaded_documents')
							->row();
		
			if ($doc && !empty($doc->file_name)) {
		
				$filePath = FCPATH . 'uploads/documents/' . $doc->file_name;
		
				if (file_exists($filePath)) {
		
					$extension  = pathinfo($doc->file_name, PATHINFO_EXTENSION);
					$attachName = $fileBaseName . '.' . $extension;
		
					/*log_message('debug', '[EMAIL] Attaching single file');
					log_message('debug', '[EMAIL] Source: ' . $filePath);
					log_message('debug', '[EMAIL] As name: ' . $attachName);*/
		
					$this->email->attach($filePath, 'attachment', $attachName);
					$attachCount = 1;
		
				} else {
					log_message('error', '[EMAIL] Single file missing: ' . $filePath);
				}
			}
		
		} else {
		
			// ---------- MONTHLY DOCUMENTS ----------
			$monthNum = $this->_getMonthNumber($month);
		
			if ($monthNum) {
		
				$uploadedDocs = $this->db->select('document_id,file_name')
										 ->where('type_id', $type_id)
										 ->where('company_id', $company_id)
										 ->where('document_month', str_pad($monthNum, 2, '0', STR_PAD_LEFT))
										 ->where('document_year', $year)
										 ->where('is_deleted', 0)
										 ->get('uploaded_documents')
										 ->result();
		

				if (!empty($docSequence)) {

					usort($uploadedDocs, function ($a, $b) use ($docSequence) {

						$posA = array_search((int)$a->document_id, $docSequence);
						$posB = array_search((int)$b->document_id, $docSequence);

						// Documents not in sequence go to the end
						$posA = ($posA === false) ? PHP_INT_MAX : $posA;
						$posB = ($posB === false) ? PHP_INT_MAX : $posB;

						return $posA <=> $posB;
					});
				}

				$pdfFiles = [];
		
				foreach ($uploadedDocs as $doc) {
					if (!empty($doc->file_name)) {
						$path = FCPATH . 'uploads/documents/' . $doc->file_name;
						if (file_exists($path)) {
							$pdfFiles[] = $path;
						}
					}
				}
		
				//log_message('debug', '[EMAIL] Monthly PDF count found: ' . count($pdfFiles));
		
				// ---------- MERGE if multiple ----------
				if (count($pdfFiles) > 1) {
		
					$this->load->library('pdfmergerlib');
		
					$outputDir = FCPATH . 'uploads/temp/';
					if (!is_dir($outputDir)) {
						mkdir($outputDir, 0755, true);
					}
		
					$mergedFile = $outputDir . $fileBaseName . '.pdf';
		
					//log_message('debug', '[EMAIL] Merging PDFs into: ' . $mergedFile);
		
					try {
						$this->pdfmergerlib->merge($pdfFiles, $mergedFile);
		
						if (file_exists($mergedFile)) {
							$this->email->attach($mergedFile);
							$attachCount = count($pdfFiles);
		
							//log_message('debug', '[EMAIL] Merged PDF attached');
						}
		
					} catch (Exception $e) {
		
						//log_message('error', '[EMAIL] PDF merge failed: ' . $e->getMessage());
		
						foreach ($pdfFiles as $file) {
							$this->email->attach($file);
							$attachCount++;
						}
					}
		
				} else {
		
					// ---------- ZERO or ONE ----------
					foreach ($pdfFiles as $file) {
						$this->email->attach($file);
						$attachCount++;
					}
				}
			}
		}
		
		// Try to send
		try {
			if ($this->email->send()) {
				$msg = 'Email sent successfully to ' . $recipient;
				if (isset($attachCount) && $attachCount > 0) {
					$msg .= ' with ' . $attachCount . ' document(s) attached';
				}
				echo json_encode([
					'success' => true, 
					'message' => $msg
				]);

			} else {
				$error = $this->email->print_debugger(['headers', 'subject', 'body']);
				//log_message('error', 'Reminder email send failed: ' . $error);
				echo json_encode([
					'success' => false, 
					'message' => 'Failed to send email. Please try again.'
				]);
			}
		} catch (Exception $e) {
			//log_message('error', 'Reminder email exception: ' . $e->getMessage());
			echo json_encode([
				'success' => false, 
				'message' => 'Email error: ' . $e->getMessage()
			]);
		} finally {

			if (!empty($mergedFile) && file_exists($mergedFile)) {
				unlink($mergedFile);
				//log_message('debug', '[EMAIL] Temp merged file deleted: ' . $mergedFile);
			}			
		}
	}

	/**
	 * Helper to convert month name to number
	 */
	private function _getMonthNumber($monthName)
	{
		$months = [
			'january' => 1, 'february' => 2, 'march' => 3, 'april' => 4,
			'may' => 5, 'june' => 6, 'july' => 7, 'august' => 8,
			'september' => 9, 'october' => 10, 'november' => 11, 'december' => 12,
			'jan' => 1, 'feb' => 2, 'mar' => 3, 'apr' => 4,
			'jun' => 6, 'jul' => 7, 'aug' => 8, 'sep' => 9,
			'oct' => 10, 'nov' => 11, 'dec' => 12
		];
		
		$key = strtolower(trim($monthName));
		return isset($months[$key]) ? $months[$key] : (is_numeric($monthName) ? (int)$monthName : null);
	}

}