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

class SubActivities extends CI_Controller
{
    public function __construct()
    {
        parent::__construct();
        header('Access-Control-Allow-Origin: *');
        header('Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept, Access-Control-Request-Method');
        header('Access-Control-Allow-Methods: GET, POST, OPTIONS, PUT, DELETE');
        // Avoid preflight requests
        $method = $_SERVER['REQUEST_METHOD'];
        if ($method == "OPTIONS") {
            die();
        }

        $this->load->helper('form');
        $this->load->library('upload');
    }

    /**
     * Create a new sub-activity.
     * @return JSON response
     */
    public function add_sub_activity()
    {
        // Get form data from JSON input
        $json_data = json_decode(@file_get_contents('php://input'), true);
        $parent_activity_id = $json_data['parent_activity_id'];
        $code = $json_data['code'] ?? 0.0;
        $name = $json_data['name'];
        $status = $json_data['status'] ?? 'Not Started';
        $created_at = $json_data['created_at'] ?? date('Y-m-d H:i:s');
        $location = $json_data['location'];
        $inCharges = $json_data['inCharges'] ?? null; // List of user IDs (array or string)
        $user_id = $json_data['user_id'];
        $months = $json_data['months'] ?? []; // Array of month names
        $team_id = $json_data['team_id'] ?? null; // Optional team ID

        // Validate required fields
        if (empty($user_id) || empty($parent_activity_id) || empty($name)) {
            return $this->output
                ->set_content_type('application/json')
                ->set_status_header(400) // Bad Request
                ->set_output(json_encode(array(
                    'success' => false,
                    'message' => 'INVALID_INPUT'
                )));
        }

        // Validate user exists
        $this->db->where('id', $user_id);
        $user_exists = $this->db->get('users')->num_rows() > 0;
        if (!$user_exists) {
            return $this->output
                ->set_content_type('application/json')
                ->set_status_header(400) // Bad Request
                ->set_output(json_encode(array(
                    'success' => false,
                    'message' => 'INVALID_USER_ID'
                )));
        }

        // Validate parent activity exists and is active
        $this->db->where('id', $parent_activity_id);
        $this->db->where('is_active', 1);
        $parent_activity = $this->db->get('activities')->row_array();
        if (empty($parent_activity)) {
            return $this->output
                ->set_content_type('application/json')
                ->set_status_header(400) // Bad Request
                ->set_output(json_encode(array(
                    'success' => false,
                    'message' => 'INVALID_PARENT_ACTIVITY'
                )));
        }

        // Validate status
        if (!in_array($status, ['Not Started', 'In Progress', 'Finalised'])) {
            return $this->output
                ->set_content_type('application/json')
                ->set_status_header(400) // Bad Request
                ->set_output(json_encode(array(
                    'success' => false,
                    'message' => 'INVALID_STATUS'
                )));
        }

        // Validate code (numeric, defaults to 0.0 if not provided)
        $code = floatval($code);

        // Validate team_id if provided
        if ($team_id) {
            $this->db->where('id', $team_id);
            $this->db->where('is_active', 1);
            $team_exists = $this->db->get('teams')->num_rows() > 0;
            if (!$team_exists) {
                return $this->output
                    ->set_content_type('application/json')
                    ->set_status_header(400) // Bad Request
                    ->set_output(json_encode(array(
                        'success' => false,
                        'message' => 'INVALID_TEAM_ID'
                    )));
            }
        }

        // Parse and validate inCharges
        $inCharges_array = [];
        if ($inCharges !== null) {
            $parsed_ids = json_decode($inCharges, true);
            if (is_array($parsed_ids)) {
                $inCharges_array = array_filter(array_map('intval', $parsed_ids));
            } else {
                $ids = explode(',', str_replace(['[', ']', '"'], '', $inCharges));
                $inCharges_array = array_filter(array_map('trim', $ids), 'strlen');
                $inCharges_array = array_map('intval', $inCharges_array);
            }
            if (!empty($inCharges_array)) {
                $this->db->where_in('id', $inCharges_array);
                $this->db->where('is_active', 1);
                $users_exist = $this->db->get('users')->num_rows() === count($inCharges_array);
                if (!$users_exist) {
                    return $this->output
                        ->set_content_type('application/json')
                        ->set_status_header(400) // Bad Request
                        ->set_output(json_encode(array(
                            'success' => false,
                            'message' => 'INVALID_INCHARGE_IDS'
                        )));
                }
            }
        }

        // Validate months
        $valid_months = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'];
        if (!empty($months) && !is_array($months)) {
            $months = explode(',', $months);
        }
        $months = array_filter(array_map('trim', (array)$months), function($month) use ($valid_months) {
            return in_array($month, $valid_months);
        });
        if (empty($months)) {
            $months = [];
        }

        // Validate created_at
        $created_at = date('Y-m-d H:i:s', strtotime($created_at)) ?: date('Y-m-d H:i:s');

        // Prepare data for insertion
        $data = [
            'parent_activity_id' => $parent_activity_id,
            'code' => $code,
            'name' => $name,
            'status' => $status,
            'location' => $location,
            'team_id' => $team_id,
            'inCharges' => !empty($inCharges_array) ? json_encode($inCharges_array) : json_encode([]),
            'created_by' => $user_id,
            'updated_by' => $user_id,
            'created_at' => $created_at,
            'is_active' => 1
        ];

        // Start transaction
        $this->db->trans_start();

        // Insert the sub-activity
        $insert = $this->db->insert('sub_activities', $data);
        if (!$insert) {
            $this->db->trans_rollback();
            log_message('error', "Failed to insert sub-activity: " . $this->db->error()['message']);
            return $this->output
                ->set_content_type('application/json')
                ->set_status_header(400)
                ->set_output(json_encode(array(
                    'success' => false,
                    'message' => 'SUB_ACTIVITY_NOT_CREATED - ' . $this->db->error()['message']
                )));
        }

        $sub_activity_id = $this->db->insert_id();

        // Insert sub-activity months
        if (!empty($months)) {
            $month_data = array_map(function($month) use ($sub_activity_id, $user_id) {
                return [
                    'sub_activity_id' => $sub_activity_id,
                    'month' => $month,
                    'created_by' => $user_id,
                    'updated_by' => $user_id
                ];
            }, $months);

            $this->db->insert_batch('sub_activity_months', $month_data);
            if ($this->db->affected_rows() === FALSE) {
                $this->db->trans_rollback();
                log_message('error', "Failed to insert sub-activity months: " . $this->db->error()['message']);
                return $this->output
                    ->set_content_type('application/json')
                    ->set_status_header(400)
                    ->set_output(json_encode(array(
                        'success' => false,
                        'message' => 'SUB_ACTIVITY_MONTHS_NOT_CREATED - ' . $this->db->error()['message']
                    )));
            }
        }

        // Commit transaction
        $this->db->trans_complete();

        if ($this->db->trans_status() === FALSE) {
            log_message('error', "Transaction failed: " . $this->db->error()['message']);
            return $this->output
                ->set_content_type('application/json')
                ->set_status_header(400)
                ->set_output(json_encode(array(
                    'success' => false,
                    'message' => 'TRANSACTION_FAILED - ' . $this->db->error()['message']
                )));
        }

        // Prepare inCharges details for response
        $inCharges_details = [];
        if (!empty($inCharges_array)) {
            $this->db->select('id, first_name, image as avatar');
            $this->db->where_in('id', $inCharges_array);
            $this->db->where('is_active', 1);
            $users = $this->db->get('users')->result_array();
            foreach ($users as $user) {
                $inCharges_details[] = [
                    'id' => (string)$user['id'],
                    'first_name' => $user['first_name'],
                    'avatar' => $user['avatar'] ?? ''
                ];
            }
        }

        $team_response = [
            'name' => $team_id ? $this->db->where('id', $team_id)->get('teams')->row()->name : 'Sub-Activity Team',
            'members' => $inCharges_details
        ];

        $response_data = [
            'id' => (string)$sub_activity_id,
            'progress' => '0',
            'name' => $name,
            'code' => $code,
            'months' => $months,
            'team' => $team_response,
            'status' => $status,
            'created_at' => $created_at,
            'location' => $location,
            'outputs' => ['status' => 'Not Started', 'comments' => [], 'planned' => 0, 'achieved' => 0, 'list' => []],
            'comments' => [],
            'comments_count' => '0',
            'products' => [],
            'outputProducts' => [],
            'attachments' => []
        ];

        return $this->output
            ->set_content_type('application/json')
            ->set_status_header(201)
            ->set_output(json_encode(array(
                'success' => true,
                'message' => 'SUB_ACTIVITY_CREATED_SUCCESSFULLY',
                'data' => $response_data
            )));
    }
    
    
    

    /**
     * Update an existing sub-activity.
     * @param int $id
     * @return JSON response
     */
    // public function edit_sub_activity($id)
    // {
    //     // Get form data from JSON input
    //     $json_data = json_decode(@file_get_contents('php://input'), true);
    //     $parent_activity_id = $json_data['parent_activity_id'];
    //     $name = $json_data['name'];
    //     $code = $json_data['code'];
    //     $progress = $json_data['progress'] ?? 0;
    //     $status = $json_data['status'];
    //     $location = $json_data['location'];
    //     $inCharges = $json_data['inCharges'] ?? null;
    //     $user_id = $json_data['user_id'];
    //     $months = $json_data['months'] ?? [];
    //     $team_id = $json_data['team_id'] ?? null;

    //     // Validate required fields
    //     if (empty($user_id)) {
    //         return $this->output
    //             ->set_content_type('application/json')
    //             ->set_status_header(400)
    //             ->set_output(json_encode(array(
    //                 'success' => false,
    //                 'message' => 'INVALID_INPUT'
    //             )));
    //     }

    //     // Validate user exists
    //     $this->db->where('id', $user_id);
    //     $user_exists = $this->db->get('users')->num_rows() > 0;
    //     if (!$user_exists) {
    //         return $this->output
    //             ->set_content_type('application/json')
    //             ->set_status_header(400)
    //             ->set_output(json_encode(array(
    //                 'success' => false,
    //                 'message' => 'INVALID_USER_ID'
    //             )));
    //     }

    //     // Validate sub-activity exists and is active
    //     $this->db->where('id', $id);
    //     $this->db->where('is_active', 1);
    //     $sub_activity = $this->db->get('sub_activities')->row_array();
    //     if (empty($sub_activity)) {
    //         return $this->output
    //             ->set_content_type('application/json')
    //             ->set_status_header(400)
    //             ->set_output(json_encode(array(
    //                 'success' => false,
    //                 'message' => 'SUB_ACTIVITY_NOT_FOUND_OR_ALREADY_DELETED'
    //             )));
    //     }

    //     // Validate parent activity if provided
    //     if ($parent_activity_id) {
    //         $this->db->where('id', $parent_activity_id);
    //         $this->db->where('is_active', 1);
    //         $parent_activity = $this->db->get('activities')->row_array();
    //         if (empty($parent_activity)) {
    //             return $this->output
    //                 ->set_content_type('application/json')
    //                 ->set_status_header(400)
    //                 ->set_output(json_encode(array(
    //                     'success' => false,
    //                     'message' => 'INVALID_PARENT_ACTIVITY'
    //                 )));
    //         }
    //     } else {
    //         $parent_activity_id = $sub_activity['parent_activity_id'];
    //     }

    //     // Validate status
    //     if ($status && !in_array($status, ['Not Started', 'In Progress', 'Finalised'])) {
    //         return $this->output
    //             ->set_content_type('application/json')
    //             ->set_status_header(400)
    //             ->set_output(json_encode(array(
    //                 'success' => false,
    //                 'message' => 'INVALID_STATUS'
    //             )));
    //     }

    //     // Validate code
    //     $code = $code !== null ? floatval($code) : $sub_activity['code'];

    //     // Validate progress
    //     $progress = $progress !== null && is_numeric($progress) ? (string)$progress : $sub_activity['progress'];

    //     // Validate team_id
    //     if ($team_id) {
    //         $this->db->where('id', $team_id);
    //         $this->db->where('is_active', 1);
    //         $team_exists = $this->db->get('teams')->num_rows() > 0;
    //         if (!$team_exists) {
    //             return $this->output
    //                 ->set_content_type('application/json')
    //                 ->set_status_header(400)
    //                 ->set_output(json_encode(array(
    //                     'success' => false,
    //                     'message' => 'INVALID_TEAM_ID'
    //                 )));
    //         }
    //     }

    //     // Parse and validate inCharges
    //     $inCharges_array = [];
    //     if ($inCharges !== null) {
    //         $parsed_ids = json_decode($inCharges, true);
    //         if (is_array($parsed_ids)) {
    //             $inCharges_array = array_filter(array_map('intval', $parsed_ids));
    //         } else {
    //             $ids = explode(',', str_replace(['[', ']', '"'], '', $inCharges));
    //             $inCharges_array = array_filter(array_map('trim', $ids), 'strlen');
    //             $inCharges_array = array_map('intval', $inCharges_array);
    //         }
    //         if (!empty($inCharges_array)) {
    //             $this->db->where_in('id', $inCharges_array);
    //             $this->db->where('is_active', 1);
    //             $users_exist = $this->db->get('users')->num_rows() === count($inCharges_array);
    //             if (!$users_exist) {
    //                 return $this->output
    //                     ->set_content_type('application/json')
    //                     ->set_status_header(400)
    //                     ->set_output(json_encode(array(
    //                         'success' => false,
    //                         'message' => 'INVALID_INCHARGE_IDS'
    //                     )));
    //             }
    //         }
    //     } else {
    //         $existing_inCharges = json_decode($sub_activity['inCharges'], true) ?: [];
    //         $inCharges_array = array_filter(array_map('intval', $existing_inCharges));
    //     }

    //     // Validate months
    //     $valid_months = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'];
    //     if (!empty($months) && !is_array($months)) {
    //         $months = explode(',', $months);
    //     }
    //     $months = array_filter(array_map('trim', (array)$months), function($month) use ($valid_months) {
    //         return in_array($month, $valid_months);
    //     });
    //     if (empty($months)) {
    //         $this->db->select('month');
    //         $this->db->where('sub_activity_id', $id);
    //         $this->db->where('is_active', 1);
    //         $existing_months = $this->db->get('sub_activity_months')->result_array();
    //         $months = array_column($existing_months, 'month');
    //     }

    //     // Prepare data for update
    //     $data = [];
    //     if ($name) $data['name'] = $name;
    //     if ($code !== null) $data['code'] = $code;
    //     if ($progress !== null) $data['progress'] = $progress;
    //     if ($status) $data['status'] = $status;
    //     if ($location) $data['location'] = $location;
    //     if ($parent_activity_id) $data['parent_activity_id'] = $parent_activity_id;
    //     if ($team_id !== null) $data['team_id'] = $team_id;
    //     if (!empty($inCharges_array)) $data['inCharges'] = json_encode($inCharges_array);

    //     $data['updated_by'] = $user_id;
    //     $data['updated_at'] = date('Y-m-d H:i:s');

    //     // Start transaction
    //     $this->db->trans_start();

    //     // Update the sub-activity
    //     $this->db->where('id', $id);
    //     $update = $this->db->update('sub_activities', $data);
    //     if (!$update) {
    //         $this->db->trans_rollback();
    //         log_message('error', "Failed to update sub-activity: " . $this->db->error()['message']);
    //         return $this->output
    //             ->set_content_type('application/json')
    //             ->set_status_header(400)
    //             ->set_output(json_encode(array(
    //                 'success' => false,
    //                 'message' => 'SUB_ACTIVITY_NOT_UPDATED - ' . $this->db->error()['message']
    //             )));
    //     }

    //     // Handle sub-activity months
    //     if (!empty($months)) {
    //         $this->db->select('month');
    //         $this->db->where('sub_activity_id', $id);
    //         $this->db->where('is_active', 1);
    //         $existing_active_months = $this->db->get('sub_activity_months')->result_array();
    //         $existing_active_months = array_column($existing_active_months, 'month');

    //         $new_months = array_diff($months, $existing_active_months);
    //         if (!empty($new_months)) {
    //             $month_data = array_map(function($month) use ($id, $user_id) {
    //                 return [
    //                     'sub_activity_id' => $id,
    //                     'month' => $month,
    //                     'created_by' => $user_id,
    //                     'updated_by' => $user_id
    //                 ];
    //             }, $new_months);
    //             $this->db->insert_batch('sub_activity_months', $month_data);
    //             if ($this->db->affected_rows() === FALSE) {
    //                 $this->db->trans_rollback();
    //                 log_message('error', "Failed to insert sub-activity months: " . $this->db->error()['message']);
    //                 return $this->output
    //                     ->set_content_type('application/json')
    //                     ->set_status_header(400)
    //                     ->set_output(json_encode(array(
    //                         'success' => false,
    //                         'message' => 'SUB_ACTIVITY_MONTHS_NOT_UPDATED - ' . $this->db->error()['message']
    //                     )));
    //             }
    //         }

    //         $months_to_delete = array_diff($existing_active_months, $months);
    //         if (!empty($months_to_delete)) {
    //             $this->db->where('sub_activity_id', $id);
    //             $this->db->where_in('month', $months_to_delete);
    //             $this->db->set('is_active', 0);
    //             $this->db->set('deleted_at', date('Y-m-d H:i:s'));
    //             $this->db->set('updated_by', $user_id);
    //             $this->db->set('updated_at', date('Y-m-d H:i:s'));
    //             $this->db->update('sub_activity_months');
    //         }

    //         $soft_deleted_months = array_intersect($months, array_column($this->db->where('sub_activity_id', $id)->where('is_active', 0)->get('sub_activity_months')->result_array(), 'month'));
    //         if (!empty($soft_deleted_months)) {
    //             $this->db->where('sub_activity_id', $id);
    //             $this->db->where_in('month', $soft_deleted_months);
    //             $this->db->set('is_active', 1);
    //             $this->db->set('deleted_at', NULL);
    //             $this->db->set('updated_by', $user_id);
    //             $this->db->set('updated_at', date('Y-m-d H:i:s'));
    //             $this->db->update('sub_activity_months');
    //         }
    //     } else {
    //         $this->db->where('sub_activity_id', $id);
    //         $this->db->where('is_active', 1);
    //         $this->db->set('is_active', 0);
    //         $this->db->set('deleted_at', date('Y-m-d H:i:s'));
    //         $this->db->set('updated_by', $user_id);
    //         $this->db->set('updated_at', date('Y-m-d H:i:s'));
    //         $this->db->update('sub_activity_months');
    //     }

    //     // Commit transaction
    //     $this->db->trans_complete();

    //     if ($this->db->trans_status() === FALSE) {
    //         log_message('error', "Transaction failed: " . $this->db->error()['message']);
    //         return $this->output
    //             ->set_content_type('application/json')
    //             ->set_status_header(400)
    //             ->set_output(json_encode(array(
    //                 'success' => false,
    //                 'message' => 'TRANSACTION_FAILED - ' . $this->db->error()['message']
    //             )));
    //     }

    //     // Fetch updated sub-activity
    //     $this->db->where('id', $id);
    //     $updated_sub_activity = $this->db->get('sub_activities')->row_array();

    //     $this->db->select('month');
    //     $this->db->where('sub_activity_id', $id);
    //     $this->db->where('is_active', 1);
    //     $current_months = $this->db->get('sub_activity_months')->result_array();
    //     $months = array_column($current_months, 'month');

    //     $inCharges_details = [];
    //     if (!empty($inCharges_array)) {
    //         $this->db->select('id, first_name, image as avatar');
    //         $this->db->where_in('id', $inCharges_array);
    //         $this->db->where('is_active', 1);
    //         $users = $this->db->get('users')->result_array();
    //         foreach ($users as $user) {
    //             $inCharges_details[] = [
    //                 'id' => (string)$user['id'],
    //                 'first_name' => $user['first_name'],
    //                 'avatar' => $user['avatar'] ?? ''
    //             ];
    //         }
    //     }

    //     $team_response = [
    //         'name' => $team_id ? $this->db->where('id', $team_id)->get('teams')->row()->name : 'Sub-Activity Team',
    //         'members' => $inCharges_details
    //     ];

    //     $response_data = [
    //         'id' => (string)$updated_sub_activity['id'],
    //         'progress' => (string)$updated_sub_activity['progress'],
    //         'name' => $updated_sub_activity['name'],
    //         'code' => floatval($updated_sub_activity['code']),
    //         'months' => $months,
    //         'team' => $team_response,
    //         'status' => $updated_sub_activity['status'],
    //         'created_at' => $updated_sub_activity['created_at'],
    //         'location' => $updated_sub_activity['location'],
    //         'outputs' => ['status' => 'Not Started', 'comments' => [], 'planned' => 0, 'achieved' => 0, 'list' => []], // Placeholder
    //         'comments' => [],
    //         'comments_count' => (string)$updated_sub_activity['comments_count'],
    //         'products' => [], // To be implemented with get_sub_activity_products
    //         'outputProducts' => [], // To be implemented with get_sub_activity_output_products
    //         'attachments' => [] // To be implemented with get_attachments_for_sub_activity
    //     ];

    //     return $this->output
    //         ->set_content_type('application/json')
    //         ->set_status_header(200)
    //         ->set_output(json_encode(array(
    //             'success' => true,
    //             'message' => 'SUB_ACTIVITY_UPDATED_SUCCESSFULLY',
    //             'data' => $response_data
    //         )));
    // }
    
       public function edit_sub_activity($id)
    {
        // Get form data from JSON input
        $json_data = json_decode(@file_get_contents('php://input'), true);
        $parent_activity_id = $json_data['parent_activity_id'] ?? null;
        $name = $json_data['name'] ?? null;
        $code = $json_data['code'] ?? null;
        $progress = $json_data['progress'] ?? null;
        $status = $json_data['status'] ?? null;
        $location = $json_data['location'] ?? null;
        $inCharges = $json_data['inCharges'] ?? null;
        $user_id = $json_data['user_id'];
        $months = $json_data['months'] ?? [];
        $team_id = $json_data['team_id'] ?? null;

        // Validate required fields
        if (empty($user_id)) {
            return $this->output
                ->set_content_type('application/json')
                ->set_status_header(400)
                ->set_output(json_encode(array(
                    'success' => false,
                    'message' => 'INVALID_INPUT'
                )));
        }

        // Validate user exists
        $this->db->where('id', $user_id);
        $this->db->where('is_active', 1);
        $user_exists = $this->db->get('users')->num_rows() > 0;
        if (!$user_exists) {
            return $this->output
                ->set_content_type('application/json')
                ->set_status_header(400)
                ->set_output(json_encode(array(
                    'success' => false,
                    'message' => 'INVALID_USER_ID'
                )));
        }

        // Validate sub-activity exists and is active
        $this->db->where('id', $id);
        $this->db->where('is_active', 1);
        $sub_activity = $this->db->get('sub_activities')->row_array();
        if (empty($sub_activity)) {
            return $this->output
                ->set_content_type('application/json')
                ->set_status_header(400)
                ->set_output(json_encode(array(
                    'success' => false,
                    'message' => 'SUB_ACTIVITY_NOT_FOUND_OR_ALREADY_DELETED'
                )));
        }
        
        $parent_activity_id =  $sub_activity['parent_activity_id'];

        // Validate parent activity if provided
        if ($parent_activity_id) {
            $this->db->where('id', $parent_activity_id);
            $this->db->where('is_active', 1);
            $parent_activity = $this->db->get('activities')->row_array();
            if (empty($parent_activity)) {
                return $this->output
                    ->set_content_type('application/json')
                    ->set_status_header(400)
                    ->set_output(json_encode(array(
                        'success' => false,
                        'message' => 'INVALID_PARENT_ACTIVITY'
                    )));
            }
        } else {
            $parent_activity_id = $sub_activity['parent_activity_id'];
        }

        // Validate status
        if ($status && !in_array($status, ['Not Started', 'In Progress', 'Finalised'])) {
            return $this->output
                ->set_content_type('application/json')
                ->set_status_header(400)
                ->set_output(json_encode(array(
                    'success' => false,
                    'message' => 'INVALID_STATUS'
                )));
        }

        // Validate code
        $code = $code !== null ? floatval($code) : $sub_activity['code'];

        // Validate progress
        $progress = $progress !== null && is_numeric($progress) ? (string)$progress : $sub_activity['progress'];

        // Validate team_id
        if ($team_id) {
            $this->db->where('id', $team_id);
            $this->db->where('is_active', 1);
            $team_exists = $this->db->get('teams')->num_rows() > 0;
            if (!$team_exists) {
                return $this->output
                    ->set_content_type('application/json')
                    ->set_status_header(400)
                    ->set_output(json_encode(array(
                        'success' => false,
                        'message' => 'INVALID_TEAM_ID'
                    )));
            }
        }

        // Parse and validate inCharges
        $inCharges_array = [];
        if ($inCharges !== null) {
            $parsed_ids = json_decode($inCharges, true);
            if (is_array($parsed_ids)) {
                $inCharges_array = array_filter(array_map('intval', $parsed_ids));
            } else {
                $ids = explode(',', str_replace(['[', ']', '"'], '', $inCharges));
                $inCharges_array = array_filter(array_map('trim', $ids), 'strlen');
                $inCharges_array = array_map('intval', $inCharges_array);
            }
            if (!empty($inCharges_array)) {
                $this->db->where_in('id', $inCharges_array);
                $this->db->where('is_active', 1);
                $users_exist = $this->db->get('users')->num_rows() === count($inCharges_array);
                if (!$users_exist) {
                    return $this->output
                        ->set_content_type('application/json')
                        ->set_status_header(400)
                        ->set_output(json_encode(array(
                            'success' => false,
                            'message' => 'INVALID_INCHARGE_IDS'
                        )));
                }
            }
        } else {
            $existing_inCharges = json_decode($sub_activity['inCharges'], true) ?: [];
            $inCharges_array = array_filter(array_map('intval', $existing_inCharges));
        }

        // Validate months
        $valid_months = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'];
        if (!empty($months) && !is_array($months)) {
            $months = explode(',', $months);
        }
        $months = array_filter(array_map('trim', (array)$months), function($month) use ($valid_months) {
            return in_array($month, $valid_months);
        });

        // Prepare data for update
        $data = [];
        if ($name !== null) $data['name'] = $name;
        if ($code !== null) $data['code'] = $code;
        if ($progress !== null) $data['progress'] = $progress;
        if ($status !== null) $data['status'] = $status;
        if ($location !== null) $data['location'] = $location;
        if ($parent_activity_id !== null) $data['parent_activity_id'] = $parent_activity_id;
        if ($team_id !== null) $data['team_id'] = $team_id;
        if (!empty($inCharges_array)) $data['inCharges'] = json_encode($inCharges_array);

        $data['updated_by'] = $user_id;
        $data['updated_at'] = date('Y-m-d H:i:s');

        // Start transaction
        $this->db->trans_start();

        // Update the sub-activity
        $this->db->where('id', $id);
        $update = $this->db->update('sub_activities', $data);
        if (!$update) {
            $this->db->trans_rollback();
            log_message('error', "Failed to update sub-activity: " . $this->db->error()['message']);
            return $this->output
                ->set_content_type('application/json')
                ->set_status_header(400)
                ->set_output(json_encode(array(
                    'success' => false,
                    'message' => 'SUB_ACTIVITY_NOT_UPDATED - ' . $this->db->error()['message']
                )));
        }

        // Handle sub-activity months: Replace all existing months with submitted months
        // Step 1: Delete all months not in the submitted list
        if (!empty($months)) {
            $this->db->where('sub_activity_id', $id);
            $this->db->where_not_in('month', $months);
            $this->db->delete('sub_activity_months');
            if ($this->db->affected_rows() === false && $this->db->error()['code'] != 0) {
                $this->db->trans_rollback();
                log_message('error', "Failed to delete unsubmitted sub-activity months: " . $this->db->error()['message']);
                return $this->output
                    ->set_content_type('application/json')
                    ->set_status_header(400)
                    ->set_output(json_encode(array(
                        'success' => false,
                        'message' => 'SUB_ACTIVITY_MONTHS_NOT_DELETED - ' . $this->db->error()['message']
                    )));
            }
        } else {
            // If no months are submitted, delete all months
            $this->db->where('sub_activity_id', $id);
            $this->db->delete('sub_activity_months');
            if ($this->db->affected_rows() === false && $this->db->error()['code'] != 0) {
                $this->db->trans_rollback();
                log_message('error', "Failed to delete all sub-activity months: " . $this->db->error()['message']);
                return $this->output
                    ->set_content_type('application/json')
                    ->set_status_header(400)
                    ->set_output(json_encode(array(
                        'success' => false,
                        'message' => 'SUB_ACTIVITY_MONTHS_NOT_DELETED - ' . $this->db->error()['message']
                    )));
            }
        }

        // Step 2: Fetch existing months to check for records to restore or skip
        $this->db->select('month, created_by, created_at, is_active');
        $this->db->where('sub_activity_id', $id);
        $existing_months = $this->db->get('sub_activity_months')->result_array();
        $existing_month_map = array_column($existing_months, null, 'month');

        // Step 3: Process submitted months
        if (!empty($months)) {
            $month_data = [];
            $months_to_restore = [];

            foreach ($months as $month) {
                if (isset($existing_month_map[$month])) {
                    // Month exists (active or soft-deleted)
                    if ($existing_month_map[$month]['is_active'] == 0) {
                        // Soft-deleted month, mark for restoration
                        $months_to_restore[] = $month;
                    }
                    // Else, month is already active, no action needed
                } else {
                    // New month, prepare for insertion
                    $month_data[] = [
                        'sub_activity_id' => $id,
                        'month' => $month,
                        'created_by' => $user_id,
                        'updated_by' => $user_id,
                        'created_at' => date('Y-m-d H:i:s'),
                        'updated_at' => date('Y-m-d H:i:s'),
                        'is_active' => 1
                    ];
                }
            }

            // Step 4: Restore soft-deleted months
            if (!empty($months_to_restore)) {
                $this->db->where('sub_activity_id', $id);
                $this->db->where_in('month', $months_to_restore);
                $this->db->set('is_active', 1);
                $this->db->set('deleted_at', null);
                $this->db->set('updated_by', $user_id);
                $this->db->set('updated_at', date('Y-m-d H:i:s'));
                $this->db->update('sub_activity_months');
                if ($this->db->affected_rows() === false && $this->db->error()['code'] != 0) {
                    $this->db->trans_rollback();
                    log_message('error', "Failed to restore sub-activity months: " . $this->db->error()['message']);
                    return $this->output
                        ->set_content_type('application/json')
                        ->set_status_header(400)
                        ->set_output(json_encode(array(
                            'success' => false,
                            'message' => 'SUB_ACTIVITY_MONTHS_NOT_RESTORED - ' . $this->db->error()['message']
                        )));
                }
            }

            // Step 5: Insert new months
            if (!empty($month_data)) {
                $this->db->insert_batch('sub_activity_months', $month_data);
                if ($this->db->affected_rows() === false) {
                    $this->db->trans_rollback();
                    log_message('error', "Failed to insert sub-activity months: " . $this->db->error()['message']);
                    return $this->output
                        ->set_content_type('application/json')
                        ->set_status_header(400)
                        ->set_output(json_encode(array(
                            'success' => false,
                            'message' => 'SUB_ACTIVITY_MONTHS_NOT_UPDATED - ' . $this->db->error()['message']
                        )));
                }
            }
        }

        // Commit transaction
        $this->db->trans_complete();

        if ($this->db->trans_status() === false) {
            log_message('error', "Transaction failed: " . $this->db->error()['message']);
            return $this->output
                ->set_content_type('application/json')
                ->set_status_header(400)
                ->set_output(json_encode(array(
                    'success' => false,
                    'message' => 'TRANSACTION_FAILED - ' . $this->db->error()['message']
                )));
        }

        // Fetch updated sub-activity
        $this->db->where('id', $id);
        $updated_sub_activity = $this->db->get('sub_activities')->row_array();

        // Fetch current active months
        $this->db->select('month');
        $this->db->where('sub_activity_id', $id);
        $this->db->where('is_active', 1);
        $current_months = $this->db->get('sub_activity_months')->result_array();
        $months = array_column($current_months, 'month');

        // Prepare inCharges details
        $inCharges_details = [];
        if (!empty($inCharges_array)) {
            $this->db->select('id, first_name, image as avatar');
            $this->db->where_in('id', $inCharges_array);
            $this->db->where('is_active', 1);
            $users = $this->db->get('users')->result_array();
            foreach ($users as $user) {
                $inCharges_details[] = [
                    'id' => (string)$user['id'],
                    'first_name' => $user['first_name'],
                    'avatar' => $user['avatar'] ?? ''
                ];
            }
        }

        $team_response = [
            'name' => $updated_sub_activity['team_id'] ? $this->db->where('id', $updated_sub_activity['team_id'])->get('teams')->row()->name : 'Sub-Activity Team',
            'members' => $inCharges_details
        ];

        // Fetch related data for response
        $outputs = $this->get_sub_activity_outputs($id);
        $products = $this->get_sub_activity_products($id);
        $output_products = $this->get_sub_activity_output_products($id);
        $attachments = $this->get_attachments_for_sub_activity($id);
        $attachments = array_filter($attachments);
        $comments = $this->get_comments('sub_activity', $id);

        // Construct response
        $response_data = [
            'id' => (string)$updated_sub_activity['id'],
            'progress' => (string)$updated_sub_activity['progress'],
            'name' => $updated_sub_activity['name'],
            'code' => floatval($updated_sub_activity['code']),
            'months' => $months,
            'team' => $team_response,
            'status' => $updated_sub_activity['status'],
            'created_at' => $updated_sub_activity['created_at'],
            'location' => $updated_sub_activity['location'],
            'outputs' => [
                'status' => $outputs['status'],
                'comments' => $outputs['comments'],
                'planned' => (string)$outputs['planned'],
                'achieved' => (string)$outputs['achieved'],
                'list' => $outputs['list']
            ],
            'comments' => $comments,
            'comments_count' => (string)$updated_sub_activity['comments_count'],
            'products' => $products,
            'outputProducts' => $output_products,
            'attachments' => $attachments
        ];

        return $this->output
            ->set_content_type('application/json')
            ->set_status_header(200)
            ->set_output(json_encode(array(
                'success' => true,
                'message' => 'SUB_ACTIVITY_UPDATED_SUCCESSFULLY',
                'data' => $response_data
            )));
    }

    /**
     * Get all sub-activities for a given activity.
     * @return JSON response
     */
    public function get_all_sub_activities($activity_id)
    {
        // Validate user_id
        $user_id = $this->input->get('user_id');
        if (empty($user_id)) {
            return $this->output
                ->set_content_type('application/json')
                ->set_status_header(400)
                ->set_output(json_encode(array(
                    'success' => false,
                    'message' => 'INVALID_USER_ID'
                )));
        }

        // Validate user exists
        $this->db->where('id', $user_id);
        $user_exists = $this->db->get('users')->num_rows() > 0;
        if (!$user_exists) {
            return $this->output
                ->set_content_type('application/json')
                ->set_status_header(400)
                ->set_output(json_encode(array(
                    'success' => false,
                    'message' => 'INVALID_USER_ID'
                )));
        }

        // Validate parent activity exists
        $this->db->where('id', $activity_id);
        $this->db->where('is_active', 1);
        $activity = $this->db->get('activities')->row_array();
        if (empty($activity)) {
            return $this->output
                ->set_content_type('application/json')
                ->set_status_header(400)
                ->set_output(json_encode(array(
                    'success' => false,
                    'message' => 'ACTIVITY_NOT_FOUND'
                )));
        }

        // Get all sub-activities
        $this->db->select('id, parent_activity_id, code, name, progress, status, created_at, location, team_id, inCharges, comments_count, created_by, updated_by, updated_at, is_active, deleted_at');
        $this->db->where('parent_activity_id', $activity_id);
        $this->db->where('is_active', 1);
        $sub_activities = $this->db->get('sub_activities')->result_array();

        $response_data = [
            'activity_id' => (string)$activity_id,
            'sub_activities' => []
        ];

        foreach ($sub_activities as $sub_activity) {
            $inCharges_array = json_decode($sub_activity['inCharges'], true) ?: [];
            $inCharges_array = array_filter(array_map('intval', $inCharges_array));

            $inCharges_details = [];
            if (!empty($inCharges_array)) {
                $this->db->select('id, first_name, image as avatar');
                $this->db->where_in('id', $inCharges_array);
                $this->db->where('is_active', 1);
                $users = $this->db->get('users')->result_array();
                foreach ($users as $user) {
                    $inCharges_details[] = [
                        'id' => (string)$user['id'],
                        'first_name' => $user['first_name'],
                        'avatar' => $user['avatar'] ?? ''
                    ];
                }
            }

            $team_response = [
                'name' => $sub_activity['team_id'] ? $this->db->where('id', $sub_activity['team_id'])->get('teams')->row()->name : 'Sub-Activity Team',
                'members' => $inCharges_details
            ];

            $sub_activity_data = [
                'id' => (string)$sub_activity['id'],
                'progress' => (string)$sub_activity['progress'],
                'name' => $sub_activity['name'],
                'code' => floatval($sub_activity['code']),
                'months' => $this->get_sub_activity_months($sub_activity['id']),
                'team' => $team_response,
                'status' => $sub_activity['status'],
                'created_at' => $sub_activity['created_at'],
                'location' => $sub_activity['location'],
                'outputs' => ['status' => 'Not Started', 'comments' => [], 'planned' => 0, 'achieved' => 0, 'list' => []], // Placeholder
                'comments' => [],
                'comments_count' => (string)$sub_activity['comments_count'],
                'products' => [], // To be implemented
                'outputProducts' => [], // To be implemented
                'attachments' => [] // To be implemented
            ];
            $response_data['sub_activities'][] = $sub_activity_data;
        }

        return $this->output
            ->set_content_type('application/json')
            ->set_status_header(200)
            ->set_output(json_encode(array(
                'success' => true,
                'message' => 'SUB_ACTIVITIES_RETRIEVED_SUCCESSFULLY',
                'data' => $response_data
            )));
    }

    /**
     * Get details of a single sub-activity.
     * @param int $id
     * @return JSON response
     */
    // public function get_sub_activity($id)
    // {
    //     // Validate user_id
    //     $user_id = $this->input->get('user_id') ?? $this->session->userdata('user_id');
    //     if (empty($user_id)) {
    //         return $this->output
    //             ->set_content_type('application/json')
    //             ->set_status_header(400)
    //             ->set_output(json_encode(array(
    //                 'success' => false,
    //                 'message' => 'INVALID_USER_ID'
    //             )));
    //     }

    //     // Validate user exists
    //     $this->db->where('id', $user_id);
    //     $user_exists = $this->db->get('users')->num_rows() > 0;
    //     if (!$user_exists) {
    //         return $this->output
    //             ->set_content_type('application/json')
    //             ->set_status_header(400)
    //             ->set_output(json_encode(array(
    //                 'success' => false,
    //                 'message' => 'INVALID_USER_ID'
    //             )));
    //     }

    //     // Get the sub-activity
    //     $this->db->select('id, parent_activity_id, code, name, progress, status, created_at, location, team_id, inCharges, comments_count, created_by, updated_by, updated_at, is_active, deleted_at');
    //     $this->db->where('id', $id);
    //     $this->db->where('is_active', 1);
    //     $sub_activity = $this->db->get('sub_activities')->row_array();

    //     if (empty($sub_activity)) {
    //         return $this->output
    //             ->set_content_type('application/json')
    //             ->set_status_header(400)
    //             ->set_output(json_encode(array(
    //                 'success' => false,
    //                 'message' => 'SUB_ACTIVITY_NOT_FOUND'
    //             )));
    //     }

    //     $inCharges_array = json_decode($sub_activity['inCharges'], true) ?: [];
    //     $inCharges_array = array_filter(array_map('intval', $inCharges_array));

    //     $inCharges_details = [];
    //     if (!empty($inCharges_array)) {
    //         $this->db->select('id, first_name, image as avatar');
    //         $this->db->where_in('id', $inCharges_array);
    //         $this->db->where('is_active', 1);
    //         $users = $this->db->get('users')->result_array();
    //         foreach ($users as $user) {
    //             $inCharges_details[] = [
    //                 'id' => (string)$user['id'],
    //                 'first_name' => $user['first_name'],
    //                 'avatar' => $user['avatar'] ?? ''
    //             ];
    //         }
    //     }

    //     $team_response = [
    //         'name' => $sub_activity['team_id'] ? $this->db->where('id', $sub_activity['team_id'])->get('teams')->row()->name : 'Sub-Activity Team',
    //         'members' => $inCharges_details
    //     ];

    //     $sub_activity_data = [
    //         'id' => (string)$sub_activity['id'],
    //         'progress' => (string)$sub_activity['progress'],
    //         'name' => $sub_activity['name'],
    //         'code' => floatval($sub_activity['code']),
    //         'months' => $this->get_sub_activity_months($sub_activity['id']),
    //         'team' => $team_response,
    //         'status' => $sub_activity['status'],
    //         'created_at' => $sub_activity['created_at'],
    //         'location' => $sub_activity['location'],
    //         'outputs' => ['status' => 'Not Started', 'comments' => [], 'planned' => 0, 'achieved' => 0, 'list' => []], // Placeholder
    //         'comments' => [],
    //         'comments_count' => (string)$sub_activity['comments_count'],
    //         'products' => [], // To be implemented
    //         'outputProducts' => [], // To be implemented
    //         'attachments' => [] // To be implemented
    //     ];

    //     return $this->output
    //         ->set_content_type('application/json')
    //         ->set_status_header(200)
    //         ->set_output(json_encode(array(
    //             'success' => true,
    //             'message' => 'SUB_ACTIVITY_RETRIEVED_SUCCESSFULLY',
    //             'data' => $sub_activity_data
    //         )));
    // }
    
//     public function get_sub_activity($id)
//     {
//     // Validate user_id
//     $user_id = $this->input->get('user_id') ?? $this->session->userdata('user_id');
//     if (empty($user_id)) {
//         return $this->output
//             ->set_content_type('application/json')
//             ->set_status_header(400)
//             ->set_output(json_encode(array(
//                 'success' => false,
//                 'message' => 'INVALID_USER_ID'
//             )));
//     }

//     // Validate user exists
//     $this->db->where('id', $user_id);
//     $user_exists = $this->db->get('users')->num_rows() > 0;
//     if (!$user_exists) {
//         return $this->output
//             ->set_content_type('application/json')
//             ->set_status_header(400)
//             ->set_output(json_encode(array(
//                 'success' => false,
//                 'message' => 'INVALID_USER_ID'
//             )));
//     }

//     // Get the sub-activity
//     $this->db->select('id, parent_activity_id, code, name, progress, status, created_at, location, team_id, inCharges, comments_count, created_by, updated_by, updated_at, is_active, deleted_at');
//     $this->db->where('id', $id);
//     $this->db->where('is_active', 1);
//     $sub_activity = $this->db->get('sub_activities')->row_array();

//     if (empty($sub_activity)) {
//         return $this->output
//             ->set_content_type('application/json')
//             ->set_status_header(400)
//             ->set_output(json_encode(array(
//                 'success' => false,
//                 'message' => 'SUB_ACTIVITY_NOT_FOUND'
//             )));
//     }

//     $inCharges_array = json_decode($sub_activity['inCharges'], true) ?: [];
//     $inCharges_array = array_filter(array_map('intval', $inCharges_array));

//     $inCharges_details = [];
//     if (!empty($inCharges_array)) {
//         $this->db->select('id, first_name, image as avatar');
//         $this->db->where_in('id', $inCharges_array);
//         $this->db->where('is_active', 1);
//         $users = $this->db->get('users')->result_array();
//         foreach ($users as $user) {
//             $inCharges_details[] = [
//                 'id' => (string)$user['id'],
//                 'first_name' => $user['first_name'],
//                 'avatar' => $user['avatar'] ?? ''
//             ];
//         }
//     }

//     $team_response = [
//         'name' => $sub_activity['team_id'] ? ($this->db->where('id', $sub_activity['team_id'])->get('teams')->row()->name ?? 'Sub-Activity Team') : 'Sub-Activity Team',
//         'members' => $inCharges_details
//     ];

//     // Get outputs
//     $this->db->where('sub_activity_id', $id);
//     $this->db->where('is_active', 1);
//     $outputs = $this->db->get('sub_activity_outputs')->result_array();
//     $outputs_data = [
//         'status' => $sub_activity['status'], // Use sub-activity status
//         'comments' => [], // No direct comments table in schema
//         'planned' => count($outputs),
//         'achieved' => array_sum(array_column($outputs, 'achieved')), // Sum of achieved values
//         'list' => array_map(function($output) {
//             return [
//                 'id' => (string)$output['id'],
//                 'description' => $output['description'],
//                 'target' => (string)$output['target'],
//                 'achieved' => (string)$output['achieved'],
//                 'created_at' => $output['created_at']
//             ];
//         }, $outputs)
//     ];

//     // Get comments (schema has comments_count but no comments table)
//     $comments = [];
//     // If there's a separate comments table not shown, query it here
//     // Example: $this->db->where('sub_activity_id', $id)->get('sub_activity_comments')->result_array();

//     // Get products
//     $this->db->where('sub_activity_id', $id);
//     $this->db->where('is_active', 1);
//     $products = $this->db->get('sub_activity_products')->result_array();
//     $products_data = array_map(function($product) {
//         $this->db->where('product_id', $product['id']);
//         $this->db->where('is_active', 1);
//         $files = $this->db->get('sub_activity_product_files')->result_array();
        
//         return [
//             'id' => (string)$product['id'],
//             'name' => $product['name'],
//             'type' => $this->db->where('id', $product['prod_type'])->get('product_types')->row()->name ?? 'Unknown',
//             'files' => array_map(function($file) {
//                 return [
//                     'id' => (string)$file['id'],
//                     'file_name' => $file['file_name'],
//                     'file_path' => $file['file_path'],
//                     'created_at' => $file['created_at']
//                 ];
//             }, $files),
//             'date_submitted' => $product['date_submitted']
//         ];
//     }, $products);

//     // Get output products (not directly in schema, assuming subset of products or separate logic)
//     $output_products = [];
//     // If output products are meant to be products tied to outputs, we could filter products based on some logic
//     // For now, left empty as schema doesn't define this explicitly
//     // Example if linked: $this->db->where('sub_activity_id', $id)->where('output_related', 1)->get('sub_activity_products');

//     // Get attachments
//     $this->db->where('sub_activity_id', $id);
//     $this->db->where('is_active', 1);
//     $attachments = $this->db->get('attachments')->result_array();
//     $attachments_data = array_map(function($attachment) {
//         $this->db->where('attachment_id', $attachment['id']);
//         $this->db->where('is_active', 1);
//         $files = $this->db->get('attachment_files')->result_array();
        
//         return [
//             'id' => (string)$attachment['id'],
//             'title' => $attachment['title'],
//             'description' => $attachment['description'],
//             'files' => array_map(function($file) {
//                 return [
//                     'id' => (string)$file['id'],
//                     'file_name' => $file['file_name'],
//                     'file_path' => $file['file_path'],
//                     'created_at' => $file['created_at']
//                 ];
//             }, $files),
//             'created_at' => $attachment['created_at']
//         ];
//     }, $attachments);

//     $sub_activity_data = [
//         'id' => (string)$sub_activity['id'],
//         'progress' => (string)$sub_activity['progress'],
//         'name' => $sub_activity['name'],
//         'code' => floatval($sub_activity['code']),
//         'months' => $this->get_sub_activity_months($sub_activity['id']),
//         'team' => $team_response,
//         'status' => $sub_activity['status'],
//         'created_at' => $sub_activity['created_at'],
//         'location' => $sub_activity['location'],
//         'outputs' => $outputs_data,
//         'comments' => $comments,
//         'comments_count' => (string)$sub_activity['comments_count'],
//         'products' => $products_data,
//         'outputProducts' => $output_products,
//         'attachments' => $attachments_data
//     ];

//     return $this->output
//         ->set_content_type('application/json')
//         ->set_status_header(200)
//         ->set_output(json_encode(array(
//             'success' => true,
//             'message' => 'SUB_ACTIVITY_RETRIEVED_SUCCESSFULLY',
//             'data' => $sub_activity_data
//         )));
// }  


public function get_sub_activity($id)
{
    // Validate user_id
    $user_id = $this->input->get('user_id') ?? $this->session->userdata('user_id');
    if (empty($user_id)) {
        return $this->output
            ->set_content_type('application/json')
            ->set_status_header(400)
            ->set_output(json_encode(array(
                'success' => false,
                'message' => 'INVALID_USER_ID'
            )));
    }

    // Validate user exists
    $this->db->where('id', $user_id);
    $user_exists = $this->db->get('users')->num_rows() > 0;
    if (!$user_exists) {
        return $this->output
            ->set_content_type('application/json')
            ->set_status_header(400)
            ->set_output(json_encode(array(
                'success' => false,
                'message' => 'INVALID_USER_ID'
            )));
    }

    // Get the sub-activity
    $this->db->select('id, parent_activity_id, code, name, progress, status, created_at, location, team_id, inCharges, comments_count, created_by, updated_by, updated_at, is_active, deleted_at');
    $this->db->where('id', $id);
    $this->db->where('is_active', 1);
    $sub_activity = $this->db->get('sub_activities')->row_array();

    if (empty($sub_activity)) {
        return $this->output
            ->set_content_type('application/json')
            ->set_status_header(400)
            ->set_output(json_encode(array(
                'success' => false,
                'message' => 'SUB_ACTIVITY_NOT_FOUND'
            )));
    }

    // Fetch inCharges details
    $inCharges_array = json_decode($sub_activity['inCharges'], true) ?: [];
    $inCharges_array = array_filter(array_map('intval', $inCharges_array));

    $inCharges_details = [];
    if (!empty($inCharges_array)) {
        $this->db->select('id, first_name, image as avatar');
        $this->db->where_in('id', $inCharges_array);
        $this->db->where('is_active', 1);
        $users = $this->db->get('users')->result_array();
        foreach ($users as $user) {
            $inCharges_details[] = [
                'id' => (string)$user['id'],
                'first_name' => $user['first_name'],
                'avatar' => $user['avatar'] ?? ''
            ];
        }
    }

    $team_response = [
        'name' => $sub_activity['team_id'] ? $this->db->where('id', $sub_activity['team_id'])->get('teams')->row()->name ?? 'Sub-Activity Team' : 'Sub-Activity Team',
        'members' => $inCharges_details
    ];

    // Fetch related data using helper methods
    $months = $this->get_sub_activity_months($sub_activity['id']);
    $outputs = $this->get_sub_activity_outputs($sub_activity['id']);
    $products = $this->get_sub_activity_products($sub_activity['id']);
    $output_products = $this->get_sub_activity_output_products($sub_activity['id']);
    $comments = [];
    $attachments = $this->get_attachments_for_sub_activity($sub_activity['id']);
    $attachments = array_filter($attachments); // Remove any null entries from get_attachment_data

    // Construct the final response
    $sub_activity_data = [
        'id' => (string)$sub_activity['id'],
        'progress' => (string)$sub_activity['progress'],
        'name' => $sub_activity['name'],
        'code' => floatval($sub_activity['code']),
        'months' => $months,
        'team' => $team_response,
        'status' => $sub_activity['status'],
        'created_at' => $sub_activity['created_at'],
        'location' => $sub_activity['location'],
        'outputs' => [
            'status' => $outputs['status'],
            'comments' => $comments, // Use sub-activity comments for the overview
            'planned' => (string)$outputs['planned'],
            'achieved' => (string)$outputs['achieved'],
            'list' => $outputs['list']
        ],
        'comments' => $comments,
        'comments_count' => (string)$sub_activity['comments_count'],
        'products' => $products,
        'outputProducts' => $output_products,
        'attachments' => $attachments
    ];

    return $this->output
        ->set_content_type('application/json')
        ->set_status_header(200)
        ->set_output(json_encode(array(
            'success' => true,
            'message' => 'SUB_ACTIVITY_RETRIEVED_SUCCESSFULLY',
            'data' => $sub_activity_data
        )));
}

    // Helper function to get months for a sub-activity
    private function get_sub_activity_months($sub_activity_id)
    {
        $this->db->select('month');
        $this->db->where('sub_activity_id', $sub_activity_id);
        $this->db->where('is_active', 1);
        $months = $this->db->get('sub_activity_months')->result_array();

        $month_order = [
            'January' => 1, 'February' => 2, 'March' => 3, 'April' => 4,
            'May' => 5, 'June' => 6, 'July' => 7, 'August' => 8,
            'September' => 9, 'October' => 10, 'November' => 11, 'December' => 12
        ];

        $month_names = array_column($months, 'month');
        usort($month_names, function($a, $b) use ($month_order) {
            return $month_order[$a] - $month_order[$b];
        });

        return $month_names;
    }
    
    
    
    
private function get_sub_activity_outputs($sub_activity_id)
{
    $this->db->select('id, title, status, planned, achieved, comments');
    $this->db->where('sub_activity_id', $sub_activity_id);
    $this->db->where('is_active', 1); // Assuming soft delete with is_active
    $outputs = $this->db->get('sub_activity_outputs')->result_array();

    $output_data = [
        'status' => 'Not Started', // Default or aggregate status
        'comments' => [],
        'planned' => 0,
        'achieved' => 0,
        'list' => []
    ];

    foreach ($outputs as $output) {
        $output_data['list'][] = [
            'id' => (string)$output['id'], // Convert to string to match your response
            'title' => $output['title'],
            'status' => $output['status'],
            'progress' => [
                'planned' => (int)$output['planned'],
                'achieved' => (int)$output['achieved']
            ],
            'comments' => $output['comments'] ?? ''
        ];
    }

    // Aggregate status, planned, and achieved
    if (!empty($outputs)) {
        $output_data['status'] = $this->aggregate_output_status($outputs);
        $output_data['planned'] = array_sum(array_column($outputs, 'planned'));
        $output_data['achieved'] = array_sum(array_column($outputs, 'achieved'));
        $output_data['comments'] = array_unique(array_filter(array_column($outputs, 'comments')));
    }

    return $output_data;
}
  
  public function add_sub_activity_follow_up_activity()
{
    // Get form data from JSON input
    $json_data = json_decode(@file_get_contents('php://input'), true);
    $parent_sub_activity_id = $json_data['parent_sub_activity_id'];
    $code = $json_data['code'] ?? 0.0; // Already handled as float, will be cast to decimal
    $name = $json_data['name'];
    $status = $json_data['status'] ?? 'Not Started';
    $due_date = $json_data['due_date'] ?? null;
    $created_at = $json_data['created_at'] ?? date('Y-m-d'); // Changed to date format
    $location = $json_data['location'];
    $inCharges = $json_data['inCharges'] ?? null;
    $user_id = $json_data['user_id'];
    $team_id = $json_data['team_id'] ?? null;

    // Validate required fields
    if (empty($user_id) || empty($parent_sub_activity_id) || empty($name)) {
        return $this->output
            ->set_content_type('application/json')
            ->set_status_header(400) // Bad Request
            ->set_output(json_encode(array(
                'success' => false,
                'message' => 'INVALID_INPUT'
            )));
    }

    // Validate user exists
    $this->db->where('id', $user_id);
    $user_exists = $this->db->get('users')->num_rows() > 0;
    if (!$user_exists) {
        return $this->output
            ->set_content_type('application/json')
            ->set_status_header(400) // Bad Request
            ->set_output(json_encode(array(
                'success' => false,
                'message' => 'INVALID_USER_ID'
            )));
    }

    // Validate parent sub-activity exists and is active
    $this->db->where('id', $parent_sub_activity_id);
    $this->db->where('is_active', 1);
    $parent_sub_activity = $this->db->get('sub_activities')->row_array();
    if (empty($parent_sub_activity)) {
        return $this->output
            ->set_content_type('application/json')
            ->set_status_header(400) // Bad Request
            ->set_output(json_encode(array(
                'success' => false,
                'message' => 'INVALID_PARENT_SUB_ACTIVITY'
            )));
    }

    // Validate status
    if (!in_array($status, ['Not Started', 'In Progress', 'Finalised'])) {
        return $this->output
            ->set_content_type('application/json')
            ->set_status_header(400) // Bad Request
            ->set_output(json_encode(array(
                'success' => false,
                'message' => 'INVALID_STATUS'
            )));
    }

    // Validate code (numeric, defaults to 0.0 if not provided)
    $code = floatval($code); // Will be stored as decimal(4,2)

    // Validate team_id if provided
    if ($team_id) {
        $this->db->where('id', $team_id);
        $this->db->where('is_active', 1);
        $team_exists = $this->db->get('teams')->num_rows() > 0;
        if (!$team_exists) {
            return $this->output
                ->set_content_type('application/json')
                ->set_status_header(400) // Bad Request
                ->set_output(json_encode(array(
                    'success' => false,
                    'message' => 'INVALID_TEAM_ID'
                )));
        }
    }

    // Validate due_date if provided
    if ($due_date) {
        $due_date = date('Y-m-d', strtotime($due_date));
        if (!$due_date || $due_date === '1970-01-01') {
            return $this->output
                ->set_content_type('application/json')
                ->set_status_header(400) // Bad Request
                ->set_output(json_encode(array(
                    'success' => false,
                    'message' => 'INVALID_DUE_DATE'
                )));
        }
    }

    // Validate location if provided (optional string)
    if (isset($location) && !is_string($location)) {
        return $this->output
            ->set_content_type('application/json')
            ->set_status_header(400) // Bad Request
            ->set_output(json_encode(array(
                'success' => false,
                'message' => 'INVALID_LOCATION'
            )));
    }

    // Parse and validate inCharges
    $inCharges_array = [];
    if ($inCharges !== null) {
        $parsed_ids = json_decode($inCharges, true);
        if (is_array($parsed_ids)) {
            $inCharges_array = array_filter(array_map('intval', $parsed_ids));
        } else {
            $ids = explode(',', str_replace(['[', ']', '"'], '', $inCharges));
            $inCharges_array = array_filter(array_map('trim', $ids), 'strlen');
            $inCharges_array = array_map('intval', $inCharges_array);
        }
        if (!empty($inCharges_array)) {
            $this->db->where_in('id', $inCharges_array);
            $this->db->where('is_active', 1);
            $users_exist = $this->db->get('users')->num_rows() === count($inCharges_array);
            if (!$users_exist) {
                return $this->output
                    ->set_content_type('application/json')
                    ->set_status_header(400) // Bad Request
                    ->set_output(json_encode(array(
                        'success' => false,
                        'message' => 'INVALID_INCHARGE_IDS'
                    )));
            }
        }
    }

    // Validate created_at
    $created_at = date('Y-m-d', strtotime($created_at)) ?: date('Y-m-d');

    // Prepare data for insertion
    $data = [
        'parent_sub_activity_id' => $parent_sub_activity_id,
        'code' => $code,
        'name' => $name,
        'progress' => 0,
        'status' => $status,
        'location' => $location,
        'created_at' => $created_at,
        'comments_count' => 0,
        'team_id' => $team_id,
        'inCharges' => !empty($inCharges_array) ? json_encode($inCharges_array) : json_encode([]),
        'created_by' => $user_id,
        'updated_by' => $user_id,
        'due_date' => $due_date,
        'is_active' => 1
    ];

    // Start transaction
    $this->db->trans_start();

    // Insert the follow-up activity
    $insert = $this->db->insert('sub_activity_follow_up_activities', $data);
    if (!$insert) {
        $this->db->trans_rollback();
        log_message('error', "Failed to insert follow-up activity: " . $this->db->error()['message']);
        return $this->output
            ->set_content_type('application/json')
            ->set_status_header(400)
            ->set_output(json_encode(array(
                'success' => false,
                'message' => 'FOLLOW_UP_ACTIVITY_NOT_CREATED - ' . $this->db->error()['message']
            )));
    }

    $follow_up_activity_id = $this->db->insert_id();

    // Commit transaction
    $this->db->trans_complete();

    if ($this->db->trans_status() === FALSE) {
        log_message('error', "Transaction failed: " . $this->db->error()['message']);
        return $this->output
            ->set_content_type('application/json')
            ->set_status_header(400)
            ->set_output(json_encode(array(
                'success' => false,
                'message' => 'TRANSACTION_FAILED - ' . $this->db->error()['message']
            )));
    }

    // Prepare inCharges details for response
    $inCharges_details = [];
    if (!empty($inCharges_array)) {
        $this->db->select('id, first_name, image as avatar');
        $this->db->where_in('id', $inCharges_array);
        $this->db->where('is_active', 1);
        $users = $this->db->get('users')->result_array();
        foreach ($users as $user) {
            $inCharges_details[] = [
                'id' => (string)$user['id'],
                'first_name' => $user['first_name'],
                'avatar' => $user['avatar'] ?? ''
            ];
        }
    }

    $team_response = [
        'name' => $team_id ? $this->db->where('id', $team_id)->get('teams')->row()->name : 'Sub-Activity Follow-Up Team',
        'members' => $inCharges_details
    ];

    $response_data = [
        'id' => (string)$follow_up_activity_id,
        'progress' => '0',
        'name' => $name,
        'code' => $code,
        'due_date' => $due_date,
        'team' => $team_response,
        'status' => $status,
        'created_at' => $created_at,
        'location' => $location,
        'comments_count' => '0',
        'outputs' => ['status' => 'Not Started', 'comments' => [], 'planned' => 0, 'achieved' => 0, 'list' => []],
        'comments' => [],
        'products' => [],
        'outputProducts' => [],
        'attachments' => []
    ];

    return $this->output
        ->set_content_type('application/json')
        ->set_status_header(201)
        ->set_output(json_encode(array(
            'success' => true,
            'message' => 'FOLLOW_UP_ACTIVITY_CREATED_SUCCESSFULLY',
            'data' => $response_data
        )));
}

private function get_sub_activity_output_products($sub_activity_id)
{
    $this->db->select('p.id, p.name, p.type, p.url, p.status, p.date_submitted, p.last_updated, p.in_charge_ids, p.prod_type, p.output_id');
    $this->db->where('p.group', 'output');
    $this->db->where('p.sub_activity_id', $sub_activity_id);
    $this->db->where('p.is_active', 1); // Assuming soft delete with is_active
    $products = $this->db->get('sub_activity_products p')->result_array();

    $products_data = [];
    foreach ($products as $product) {
        $in_charge_ids = json_decode($product['in_charge_ids'], true) ?: [];
        $in_charge = [];
        if (!empty($in_charge_ids)) {
            $this->db->select('id, first_name, image as avatar');
            $this->db->where_in('id', $in_charge_ids);
            $users = $this->db->get('users')->result_array();
            foreach ($users as $user) {
                $in_charge[] = [
                    'id' => (string)$user['id'], // Convert to string to match your response
                    'first_name' => $user['first_name'],
                    'avatar' => $user['avatar'] ?? ''
                ];
            }
        }

        $product_data = [
            'id' => (string)$product['id'], // Convert to string to match your response
            'name' => $product['name'],
            'type' => $product['type'] ?? '',
            'url' => $product['url'] ?? '',
            'inCharge' => $in_charge,
            'status' => $product['status'] ?? 'Pending',
            'dateSubmitted' => $product['date_submitted'] ?? '',
            'lastUpdated' => $product['last_updated'] ?? '',
            'prod_type' => $product['prod_type'] ?? null, // Add prod_type ID to the response
            'output_id' => (string)$product['output_id'] // Include output_id for output products
        ];

        // If it's a folder product, include files
        if ($product['type'] === 'folder') {
            $this->db->where('product_id', $product['id']);
            $this->db->where('is_active', 1); // Assuming soft delete with is_active
            $files_data = $this->db->get('sub_activity_product_files')->result_array();
            $files = [];
            foreach ($files_data as $file) {
                $files[] = [
                    'id' => (string)$file['id'], // Convert to string to match your response
                    'name' => $file['name'],
                    'type' => $file['type'],
                    'url' => $file['url'],
                    'date' => $file['date'],
                    'size' => $file['size']
                ];
            }
            $product_data['files'] = $files;
        }

        $products_data[] = $product_data;
    }

    return $products_data;
}

private function get_attachments_for_sub_activity($sub_activity_id)
{
    $this->db->where('sub_activity_id', $sub_activity_id);
    $this->db->where('is_active', 1);
    $attachments = $this->db->get('attachments')->result_array();

    return array_map(function ($attachment) {
        return $this->get_attachment_data($attachment['id']);
    }, $attachments);
}
// Helper method to fetch attachment data (consistent with add_attachment)
private function get_attachment_data($attachment_id)
{
    $this->db->where('a.id', $attachment_id);
    $this->db->where('a.is_active', 1);
    $attachment = $this->db->get('attachments a')->row_array();

    if (!$attachment) return null;

    $data = [
        'id' => (string)$attachment['id'],
        'type' => $attachment['type'],
        'title' => $attachment['title'],
        'date' => $attachment['date']
    ];

    if ($attachment['type'] === 'folder') {
        $this->db->where('attachment_id', $attachment_id);
        $this->db->where('is_active', 1);
        $files = $this->db->get('attachment_files')->result_array();
        $data['files'] = array_map(function ($file) {
            return [
                'id' => (string)$file['id'],
                'name' => $file['name'],
                'type' => $file['type'],
                'url' => $file['url'],
                'date' => $file['date'],
                'size' => $file['size']
            ];
        }, $files);
        $data['url'] = null;
        $data['size'] = null;
    } else {
        $data['url'] = $attachment['url'];
        $data['size'] = $attachment['size'];
        $data['files'] = [];
    }

    $in_charge_ids = json_decode($attachment['in_charge_ids'], true) ?: [];
    $data['team'] = [
        'name' => 'Attachment Team',
        'members' => $this->get_in_charge_details($in_charge_ids)
    ];

    return $data;
}

private function get_in_charge_details($in_charge_ids)
{
    $details = [];
    if (!empty($in_charge_ids)) {
        $this->db->select('id, first_name, image as avatar');
        $this->db->where_in('id', $in_charge_ids);
        $this->db->where('is_active', 1);
        $users = $this->db->get('users')->result_array();
        foreach ($users as $user) {
            $details[] = [
                'id' => (string)$user['id'],
                'first_name' => $user['first_name'],
                'avatar' => $user['avatar'] ?? ''
            ];
        }
    }
    return $details;
}

private function get_sub_activity_products($sub_activity_id)
{
    $this->db->select('p.id, p.name, p.type, p.url, p.status, p.date_submitted, p.last_updated, p.in_charge_ids, p.prod_type, p.is_active');
    $this->db->where('p.group', 'general');
    $this->db->where('p.sub_activity_id', $sub_activity_id);
    $this->db->where('p.is_active', 1); // Assuming soft delete with is_active
    $products = $this->db->get('sub_activity_products p')->result_array();

    $products_data = [];
    foreach ($products as $product) {
        $in_charge_ids = json_decode($product['in_charge_ids'], true) ?: [];
        $in_charge = [];
        if (!empty($in_charge_ids)) {
            $this->db->select('id, first_name, image as avatar');
            $this->db->where_in('id', $in_charge_ids);
            $users = $this->db->get('users')->result_array();
            foreach ($users as $user) {
                $in_charge[] = [
                    'id' => (string)$user['id'], // Convert to string to match your response
                    'first_name' => $user['first_name'],
                    'avatar' => $user['avatar'] ?? ''
                ];
            }
        }

        $product_data = [
            'id' => (string)$product['id'], // Convert to string to match your response
            'name' => $product['name'],
            'type' => $product['type'] ?? '',
            'url' => $product['url'] ?? '',
            'inCharge' => $in_charge,
            'status' => $product['status'] ?? 'Pending',
            'dateSubmitted' => $product['date_submitted'] ?? '',
            'lastUpdated' => $product['last_updated'] ?? '',
            'prod_type' => $product['prod_type'] ?? null // Add prod_type ID to the response
        ];

        // If it's a folder product, include files
        if ($product['type'] === 'folder') {
            $this->db->where('product_id', $product['id']);
            $this->db->where('is_active', 1); // Assuming soft delete with is_active
            $files_data = $this->db->get('sub_activity_product_files')->result_array();
            $files = [];
            foreach ($files_data as $file) {
                $files[] = [
                    'id' => (string)$file['id'], // Convert to string to match your response
                    'name' => $file['name'],
                    'type' => $file['type'],
                    'url' => $file['url'],
                    'date' => $file['date'],
                    'size' => $file['size']
                ];
            }
            $product_data['files'] = $files;
        }

        $products_data[] = $product_data;
    }

    return $products_data;
}


public function edit_sub_activity_follow_up_activity($id)
{
    // Get form data from JSON input
    $json_data = json_decode(@file_get_contents('php://input'), true);
    $parent_sub_activity_id = $json_data['parent_sub_activity_id'] ?? null;
    $code = $json_data['code'] ?? null;
    $name = $json_data['name'] ?? null;
    $status = $json_data['status'] ?? null;
    $due_date = $json_data['due_date'] ?? null;
    $created_at = $json_data['created_at'] ?? null;
    $location = $json_data['location'] ?? null;
    $inCharges = $json_data['inCharges'] ?? null;
    $user_id = $json_data['user_id'];
    $team_id = $json_data['team_id'] ?? null;

    // Validate required fields
    if (empty($user_id) || empty($id)) {
        return $this->output
            ->set_content_type('application/json')
            ->set_status_header(400) // Bad Request
            ->set_output(json_encode(array(
                'success' => false,
                'message' => 'INVALID_INPUT'
            )));
    }

    // Validate user exists
    $this->db->where('id', $user_id);
    $user_exists = $this->db->get('users')->num_rows() > 0;
    if (!$user_exists) {
        return $this->output
            ->set_content_type('application/json')
            ->set_status_header(400) // Bad Request
            ->set_output(json_encode(array(
                'success' => false,
                'message' => 'INVALID_USER_ID'
            )));
    }

    // Validate follow-up activity exists and is active
    $this->db->where('id', $id);
    $this->db->where('is_active', 1);
    $follow_up_activity = $this->db->get('sub_activity_follow_up_activities')->row_array();
    if (empty($follow_up_activity)) {
        return $this->output
            ->set_content_type('application/json')
            ->set_status_header(400) // Bad Request
            ->set_output(json_encode(array(
                'success' => false,
                'message' => 'FOLLOW_UP_ACTIVITY_NOT_FOUND_OR_ALREADY_DELETED'
            )));
    }

    // Validate parent sub-activity if provided
    if (isset($parent_sub_activity_id)) {
        $this->db->where('id', $parent_sub_activity_id);
        $this->db->where('is_active', 1);
        $parent_sub_activity = $this->db->get('sub_activities')->row_array();
        if (empty($parent_sub_activity)) {
            return $this->output
                ->set_content_type('application/json')
                ->set_status_header(400) // Bad Request
                ->set_output(json_encode(array(
                    'success' => false,
                    'message' => 'INVALID_PARENT_SUB_ACTIVITY'
                )));
        }
    }

    // Validate status if provided
    if (isset($status) && !in_array($status, ['Not Started', 'In Progress', 'Finalised'])) {
        return $this->output
            ->set_content_type('application/json')
            ->set_status_header(400) // Bad Request
            ->set_output(json_encode(array(
                'success' => false,
                'message' => 'INVALID_STATUS'
            )));
    }

    // Validate code if provided
    if (isset($code)) {
        $code = floatval($code); // Will be stored as decimal(4,2)
    }

    // Validate team_id if provided
    if (isset($team_id)) {
        if ($team_id !== null) {
            $this->db->where('id', $team_id);
            $this->db->where('is_active', 1);
            $team_exists = $this->db->get('teams')->num_rows() > 0;
            if (!$team_exists) {
                return $this->output
                    ->set_content_type('application/json')
                    ->set_status_header(400) // Bad Request
                    ->set_output(json_encode(array(
                        'success' => false,
                        'message' => 'INVALID_TEAM_ID'
                    )));
            }
        }
    }

    // Validate due_date if provided
    if (isset($due_date)) {
        if ($due_date !== null) {
            $due_date = date('Y-m-d', strtotime($due_date));
            if (!$due_date || $due_date === '1970-01-01') {
                return $this->output
                    ->set_content_type('application/json')
                    ->set_status_header(400) // Bad Request
                    ->set_output(json_encode(array(
                        'success' => false,
                        'message' => 'INVALID_DUE_DATE'
                    )));
            }
        }
    }

    // Validate location if provided
    if (isset($location) && !is_string($location)) {
        return $this->output
            ->set_content_type('application/json')
            ->set_status_header(400) // Bad Request
            ->set_output(json_encode(array(
                'success' => false,
                'message' => 'INVALID_LOCATION'
            )));
    }

    // Parse and validate inCharges if provided
    $inCharges_array = [];
    if (isset($inCharges)) {
        if ($inCharges !== null) {
            $parsed_ids = json_decode($inCharges, true);
            if (is_array($parsed_ids)) {
                $inCharges_array = array_filter(array_map('intval', $parsed_ids));
            } else {
                $ids = explode(',', str_replace(['[', ']', '"'], '', $inCharges));
                $inCharges_array = array_filter(array_map('trim', $ids), 'strlen');
                $inCharges_array = array_map('intval', $inCharges_array);
            }
            if (!empty($inCharges_array)) {
                $this->db->where_in('id', $inCharges_array);
                $this->db->where('is_active', 1);
                $users_exist = $this->db->get('users')->num_rows() === count($inCharges_array);
                if (!$users_exist) {
                    return $this->output
                        ->set_content_type('application/json')
                        ->set_status_header(400) // Bad Request
                        ->set_output(json_encode(array(
                            'success' => false,
                            'message' => 'INVALID_INCHARGE_IDS'
                        )));
                }
            }
        }
    }

    // Validate created_at if provided
    if (isset($created_at)) {
        $created_at = date('Y-m-d', strtotime($created_at)) ?: null;
        if (!$created_at || $created_at === '1970-01-01') {
            return $this->output
                ->set_content_type('application/json')
                ->set_status_header(400) // Bad Request
                ->set_output(json_encode(array(
                    'success' => false,
                    'message' => 'INVALID_CREATED_AT'
                )));
        }
    }

    // Prepare data for update (only include provided fields)
    $data = [];
    if (isset($parent_sub_activity_id)) $data['parent_sub_activity_id'] = $parent_sub_activity_id;
    if (isset($code)) $data['code'] = $code;
    if (isset($name)) $data['name'] = $name;
    if (isset($status)) $data['status'] = $status;
    if (isset($due_date)) $data['due_date'] = $due_date;
    if (isset($created_at)) $data['created_at'] = $created_at;
    if (isset($location)) $data['location'] = $location;
    if (isset($team_id)) $data['team_id'] = $team_id;
    if (isset($inCharges)) $data['inCharges'] = !empty($inCharges_array) ? json_encode($inCharges_array) : json_encode([]);

    // Add audit fields
    $data['updated_by'] = $user_id;
    // Note: updated_at is automatically handled by the database (current_timestamp)

    // Start transaction
    $this->db->trans_start();

    // Update the follow-up activity
    $this->db->where('id', $id);
    $update = $this->db->update('sub_activity_follow_up_activities', $data);
    if (!$update) {
        $this->db->trans_rollback();
        log_message('error', "Failed to update follow-up activity: " . $this->db->error()['message']);
        return $this->output
            ->set_content_type('application/json')
            ->set_status_header(400)
            ->set_output(json_encode(array(
                'success' => false,
                'message' => 'FOLLOW_UP_ACTIVITY_NOT_UPDATED - ' . $this->db->error()['message']
            )));
    }

    // Commit transaction
    $this->db->trans_complete();

    if ($this->db->trans_status() === FALSE) {
        log_message('error', "Transaction failed: " . $this->db->error()['message']);
        return $this->output
            ->set_content_type('application/json')
            ->set_status_header(400)
            ->set_output(json_encode(array(
                'success' => false,
                'message' => 'TRANSACTION_FAILED - ' . $this->db->error()['message']
            )));
    }

    // Fetch updated record for response
    $this->db->where('id', $id);
    $updated_activity = $this->db->get('sub_activity_follow_up_activities')->row_array();

    // Prepare inCharges details for response
    $inCharges_array = isset($inCharges) ? $inCharges_array : json_decode($updated_activity['inCharges'], true);
    $inCharges_details = [];
    if (!empty($inCharges_array)) {
        $this->db->select('id, first_name, image as avatar');
        $this->db->where_in('id', $inCharges_array);
        $this->db->where('is_active', 1);
        $users = $this->db->get('users')->result_array();
        foreach ($users as $user) {
            $inCharges_details[] = [
                'id' => (string)$user['id'],
                'first_name' => $user['first_name'],
                'avatar' => $user['avatar'] ?? ''
            ];
        }
    }

    $team_response = [
        'name' => $updated_activity['team_id'] ? $this->db->where('id', $updated_activity['team_id'])->get('teams')->row()->name : 'Sub-Activity Follow-Up Team',
        'members' => $inCharges_details
    ];

    $response_data = [
        'id' => (string)$updated_activity['id'],
        'progress' => (string)$updated_activity['progress'],
        'name' => $updated_activity['name'],
        'code' => $updated_activity['code'],
        'due_date' => $updated_activity['due_date'],
        'team' => $team_response,
        'status' => $updated_activity['status'],
        'created_at' => $updated_activity['created_at'],
        'location' => $updated_activity['location'],
        'comments_count' => (string)$updated_activity['comments_count'],
        'outputs' => ['status' => 'Not Started', 'comments' => [], 'planned' => 0, 'achieved' => 0, 'list' => []],
        'comments' => [],
        'products' => [],
        'outputProducts' => [],
        'attachments' => []
    ];

    return $this->output
        ->set_content_type('application/json')
        ->set_status_header(200)
        ->set_output(json_encode(array(
            'success' => true,
            'message' => 'FOLLOW_UP_ACTIVITY_UPDATED_SUCCESSFULLY',
            'data' => $response_data
        )));
}



// DELETE SUB ACTIVITY


public function delete_sub_activity()
{
    // Validate user_id (assuming it's passed via GET or form for authentication)
    $isAnnual = $this->input->get('isAnnual');
    $user_id = $this->input->get('user_id');
    if (empty($user_id)) {
        return $this->output
            ->set_content_type('application/json')
            ->set_status_header(400) // Bad Request
            ->set_output(json_encode(array(
                'success' => false,
                'message' => 'INVALID_USER_ID'
            )));
    }

    // Validate user exists
    $this->db->where('id', $user_id);
    $user_exists = $this->db->get('users')->num_rows() > 0;

    if (!$user_exists) {
        return $this->output
            ->set_content_type('application/json')
            ->set_status_header(400) // Bad Request
            ->set_output(json_encode(array(
                'success' => false,
                'message' => 'INVALID_USER_ID'
            )));
    }

    // Get sub_activity_id from input (required)
    $sub_activity_id = $this->input->get('sub_activity_id');
    if (empty($sub_activity_id) || !is_numeric($sub_activity_id)) {
        return $this->output
            ->set_content_type('application/json')
            ->set_status_header(400) // Bad Request
            ->set_output(json_encode(array(
                'success' => false,
                'message' => 'INVALID_SUB_ACTIVITY_ID'
            )));
    }

    // Get delete_type from input (optional, defaults to soft delete)
    $delete_type = $this->input->get('delete_type') ?? 'soft';
    if (!in_array($delete_type, ['soft', 'hard'])) {
        return $this->output
            ->set_content_type('application/json')
            ->set_status_header(400) // Bad Request
            ->set_output(json_encode(array(
                'success' => false,
                'message' => 'INVALID_DELETE_TYPE'
            )));
    }

    // Check if sub_activity exists and is active
    $this->db->where('id', $sub_activity_id);
    if ($delete_type === 'soft') {
        $this->db->where('is_active', 1); // Ensure the sub-activity is active before deleting
    } else {
        $this->db->where('is_active', 0); // For hard delete, ensure it's already soft-deleted
    }
    $sub_activity = $this->db->get('sub_activities')->row_array();

    if (empty($sub_activity)) {
        return $this->output
            ->set_content_type('application/json')
            ->set_status_header(400) // Bad Request
            ->set_output(json_encode(array(
                'success' => false,
                'message' => 'SUB_ACTIVITY_NOT_FOUND_OR_ALREADY_DELETED'
            )));
    }
       //check is annual
    if($isAnnual =='true'){
        
     $data = [
            'isActiveOnAnnual' => 0,
            'updated_by' => $user_id,
            'updated_at' => date('Y-m-d H:i:s') // Current timestamp
        ];
        $this->db->where('id', $sub_activity_id);
        $this->db->update('sub_activities', $data);
        
        return $this->output
        ->set_content_type('application/json')
        ->set_status_header(200)
        ->set_output(json_encode(array(
            'success' => true,
            'message' => ($delete_type === 'soft' ? 'SUB_ACTIVITY_SOFT_DELETED_SUCCESSFULLY' : 'SUB_ACTIVITY_HARD_DELETED_SUCCESSFULLY'),
            'data' => [
                'sub_activity_id' => $sub_activity_id,
                'isAnnual'=>'YES',
                'delete_type' => $delete_type
            ]
        )));
    }

    // Start transaction for consistency
    $this->db->trans_start();

    if ($delete_type === 'soft') {
        // Perform soft delete: update is_active to 0 and set deleted_at
        $data = [
            'is_active' => 0,
            'deleted_at' => date('Y-m-d H:i:s'), // Current timestamp
            'updated_by' => $user_id,
            'updated_at' => date('Y-m-d H:i:s') // Current timestamp
        ];

        $this->db->where('id', $sub_activity_id);
        $this->db->update('sub_activities', $data);

        // Soft delete related records
        $this->soft_delete_related_sub_activity_records($sub_activity_id, $user_id);
    } else {
        // Perform hard delete: delete sub_activity and related records
        $this->hard_delete_sub_activity_and_related($sub_activity_id);
    }

    // Complete transaction
    $this->db->trans_complete();

    if ($this->db->trans_status() === FALSE) {
        return $this->output
            ->set_content_type('application/json')
            ->set_status_header(500) // Internal Server Error
            ->set_output(json_encode(array(
                'success' => false,
                'message' => 'DELETE_FAILED'
            )));
    }

    return $this->output
        ->set_content_type('application/json')
        ->set_status_header(200)
        ->set_output(json_encode(array(
            'success' => true,
            'message' => ($delete_type === 'soft' ? 'SUB_ACTIVITY_SOFT_DELETED_SUCCESSFULLY' : 'SUB_ACTIVITY_HARD_DELETED_SUCCESSFULLY'),
            'data' => [
                'sub_activity_id' => $sub_activity_id,
                'delete_type' => $delete_type
            ]
        )));
}

// Helper function to soft delete related records for sub-activity
private function soft_delete_related_sub_activity_records($sub_activity_id, $user_id)
{
    $data = [
        'is_active' => 0,
        'deleted_at' => date('Y-m-d H:i:s'), // Current timestamp
        'updated_by' => $user_id,
        'updated_at' => date('Y-m-d H:i:s') // Current timestamp
    ];

    // Soft delete sub_activity_products
    $this->db->where('sub_activity_id', $sub_activity_id);
    $this->db->update('sub_activity_products', $data);

    // Soft delete sub_activity_product_files
    $this->db->where('product_id IN (SELECT id FROM sub_activity_products WHERE sub_activity_id = ' . $this->db->escape($sub_activity_id) . ')');
    $this->db->update('sub_activity_product_files', $data);

    // Soft delete follow-up activities
    $this->db->where('parent_sub_activity_id', $sub_activity_id);
    $this->db->update('sub_activity_follow_up_activities', $data);
}

// Helper function to hard delete sub-activity and related records
private function hard_delete_sub_activity_and_related($sub_activity_id)
{
    // Delete follow-up activities
    $this->db->where('parent_sub_activity_id', $sub_activity_id);
    $this->db->delete('sub_activity_follow_up_activities');

    // Get product IDs for this sub-activity
    $this->db->select('id');
    $this->db->where('sub_activity_id', $sub_activity_id);
    $products = $this->db->get('sub_activity_products')->result_array();
    $product_ids = array_column($products, 'id');

    // Delete sub_activity_product_files (if any)
    if (!empty($product_ids)) {
        $this->db->where_in('product_id', $product_ids);
        $this->db->delete('sub_activity_product_files');
    }

    // Delete sub_activity_products
    $this->db->where('sub_activity_id', $sub_activity_id);
    $this->db->delete('sub_activity_products');

    // Delete the sub_activity
    $this->db->where('id', $sub_activity_id);
    $this->db->delete('sub_activities');
}


public function transfer_sub_activity()
    {
        // Get form data from JSON input
        $json_data = json_decode(@file_get_contents('php://input'), true);
        $sub_activity_id = $json_data['sub_activity_id'];
        $target_activity_id = $json_data['target_activity_id'];
        $user_id = $json_data['user_id'];

        // Validate required fields
        if (empty($user_id) || empty($sub_activity_id) || empty($target_activity_id)) {
            return $this->output
                ->set_content_type('application/json')
                ->set_status_header(400)
                ->set_output(json_encode(array(
                    'success' => false,
                    'message' => 'INVALID_INPUT'
                )));
        }

        // Validate user exists
        $this->db->where('id', $user_id);
        $this->db->where('is_active', 1);
        $user_exists = $this->db->get('users')->num_rows() > 0;
        if (!$user_exists) {
            return $this->output
                ->set_content_type('application/json')
                ->set_status_header(400)
                ->set_output(json_encode(array(
                    'success' => false,
                    'message' => 'INVALID_USER_ID'
                )));
        }

        // Validate source sub-activity exists and is active
        $this->db->where('id', $sub_activity_id);
        $this->db->where('is_active', 1);
        $sub_activity = $this->db->get('sub_activities')->row_array();
        if (empty($sub_activity)) {
            return $this->output
                ->set_content_type('application/json')
                ->set_status_header(400)
                ->set_output(json_encode(array(
                    'success' => false,
                    'message' => 'SUB_ACTIVITY_NOT_FOUND_OR_ALREADY_DELETED'
                )));
        }

        // Validate target activity exists and is active
        $this->db->where('id', $target_activity_id);
        $this->db->where('is_active', 1);
        $target_activity = $this->db->get('activities')->row_array();
        if (empty($target_activity)) {
            return $this->output
                ->set_content_type('application/json')
                ->set_status_header(400)
                ->set_output(json_encode(array(
                    'success' => false,
                    'message' => 'INVALID_TARGET_ACTIVITY'
                )));
        }

        // Start transaction
        $this->db->trans_start();

        // Step 1: Create new sub-activity under target activity with original dates
        $new_sub_activity_data = [
            'parent_activity_id' => $target_activity_id,
            'code' => $sub_activity['code'],
            'name' => $sub_activity['name'],
            'progress' => $sub_activity['progress'],
            'status' => $sub_activity['status'],
            'location' => $sub_activity['location'],
            'team_id' => $sub_activity['team_id'],
            'inCharges' => $sub_activity['inCharges'],
            'created_by' => $sub_activity['created_by'],
            'updated_by' => $sub_activity['updated_by'],
            'created_at' => $sub_activity['created_at'], // Retain original created_at
            'updated_at' => $sub_activity['updated_at'], // Retain original updated_at
            'comments_count' => $sub_activity['comments_count'],
            'is_active' => 1
        ];

        $this->db->insert('sub_activities', $new_sub_activity_data);
        $new_sub_activity_id = $this->db->insert_id();

        if (!$new_sub_activity_id) {
            $this->db->trans_rollback();
            log_message('error', "Failed to create new sub-activity: " . $this->db->error()['message']);
            return $this->output
                ->set_content_type('application/json')
                ->set_status_header(400)
                ->set_output(json_encode(array(
                    'success' => false,
                    'message' => 'SUB_ACTIVITY_NOT_CREATED - ' . $this->db->error()['message']
                )));
        }

        // Step 2: Copy comments for the sub-activity
        $this->db->select('c.id, c.body, c.created_by, c.created_at, c.updated_by, c.updated_at, c.is_quarterly');
        $this->db->from('comments c');
        $this->db->where('c.entity_type', 'sub_activity');
        $this->db->where('c.entity_id', $sub_activity_id);
        $this->db->where('c.is_active', 1);
        $comments = $this->db->get()->result_array();

        if (!empty($comments)) {
            $comment_data = array_map(function($comment) use ($new_sub_activity_id, $user_id) {
                return [
                    'entity_type' => 'sub_activity',
                    'entity_id' => $new_sub_activity_id,
                    'body' => $comment['body'],
                    'is_quarterly' => $comment['is_quarterly'],
                    'created_by' => $comment['created_by'],
                    'updated_by' => $comment['updated_by'],
                    'created_at' => $comment['created_at'], // Retain original created_at
                    'updated_at' => $comment['updated_at'], // Retain original updated_at
                    'is_active' => 1
                ];
            }, $comments);
            $this->db->insert_batch('comments', $comment_data);
            if ($this->db->affected_rows() === FALSE) {
                $this->db->trans_rollback();
                log_message('error', "Failed to insert sub-activity comments: " . $this->db->error()['message']);
                return $this->output
                    ->set_content_type('application/json')
                    ->set_status_header(400)
                    ->set_output(json_encode(array(
                        'success' => false,
                        'message' => 'SUB_ACTIVITY_COMMENTS_NOT_CREATED - ' . $this->db->error()['message']
                    )));
            }
        }

        // Step 3: Copy sub-activity months with original dates
        $this->db->where('sub_activity_id', $sub_activity_id);
        $this->db->where('is_active', 1);
        $months = $this->db->get('sub_activity_months')->result_array();
        if (!empty($months)) {
            $month_data = array_map(function($month) use ($new_sub_activity_id, $user_id) {
                return [
                    'sub_activity_id' => $new_sub_activity_id,
                    'month' => $month['month'],
                    'created_by' => $month['created_by'],
                    'updated_by' => $month['updated_by'],
                    'created_at' => $month['created_at'], // Retain original created_at
                    'updated_at' => $month['updated_at'], // Retain original updated_at
                    'is_active' => 1
                ];
            }, $months);
            $this->db->insert_batch('sub_activity_months', $month_data);
            if ($this->db->affected_rows() === FALSE) {
                $this->db->trans_rollback();
                log_message('error', "Failed to insert sub-activity months: " . $this->db->error()['message']);
                return $this->output
                    ->set_content_type('application/json')
                    ->set_status_header(400)
                    ->set_output(json_encode(array(
                        'success' => false,
                        'message' => 'SUB_ACTIVITY_MONTHS_NOT_CREATED - ' . $this->db->error()['message']
                    )));
            }
        }

        // Step 4: Copy sub-activity products (general and output products) with original dates
        $this->db->where('sub_activity_id', $sub_activity_id);
        $this->db->where('is_active', 1);
        $products = $this->db->get('sub_activity_products')->result_array();
        $product_id_mapping = []; // Map old product IDs to new product IDs
        foreach ($products as $product) {
            $new_product_data = [
                'sub_activity_id' => $new_sub_activity_id,
                'name' => $product['name'],
                'type' => $product['type'],
                'url' => $product['url'],
                'status' => $product['status'],
                'group' => $product['group'],
                'prod_type' => $product['prod_type'],
                'isUrgent' => $product['isUrgent'],
                'isRequiredToProceed' => $product['isRequiredToProceed'],
                'in_charge_ids' => $product['in_charge_ids'],
                'output_id' => $product['output_id'],
                'date_submitted' => $product['date_submitted'],
                'last_updated' => $product['last_updated'],
                'created_by' => $product['created_by'],
                'updated_by' => $product['updated_by'],
                'date_submitted' => $product['date_submitted'], // Retain original created_at
                'updated_at' => $product['updated_at'], // Retain original updated_at
                'is_active' => 1
            ];
            $this->db->insert('sub_activity_products', $new_product_data);
            $new_product_id = $this->db->insert_id();
            $product_id_mapping[$product['id']] = $new_product_id;

            // Copy product comments
            $this->db->select('c.id, c.body, c.created_by, c.created_at, c.updated_at, c.updated_by, c.is_quarterly');
            $this->db->from('comments c');
            $this->db->where('c.entity_type', 'sub_activity_product');
            $this->db->where('c.entity_id', $product['id']);
            $this->db->where('c.is_active', 1);
            $product_comments = $this->db->get()->result_array();

            if (!empty($product_comments)) {
                $product_comment_data = array_map(function($comment) use ($new_product_id, $user_id) {
                    return [
                        'entity_type' => 'sub_activity_product',
                        'entity_id' => $new_product_id,
                        'body' => $comment['body'],
                        'is_quarterly' => $comment['is_quarterly'],
                        'created_by' => $comment['created_by'],
                        'updated_by' =>  $comment['updated_by'],
                        'created_at' => $comment['created_at'], // Retain original created_at
                        'updated_at' => $comment['updated_at'], // Retain original updated_at
                        'is_active' => 1
                    ];
                }, $product_comments);
                $this->db->insert_batch('comments', $product_comment_data);
                if ($this->db->affected_rows() === FALSE) {
                    $this->db->trans_rollback();
                    log_message('error', "Failed to insert sub-activity product comments: " . $this->db->error()['message']);
                    return $this->output
                        ->set_content_type('application/json')
                        ->set_status_header(400)
                        ->set_output(json_encode(array(
                            'success' => false,
                            'message' => 'SUB_ACTIVITY_PRODUCT_COMMENTS_NOT_CREATED - ' . $this->db->error()['message']
                        )));
                }
            }

            // Copy product files with original dates
            $this->db->where('product_id', $product['id']);
            $this->db->where('is_active', 1);
            $product_files = $this->db->get('sub_activity_product_files')->result_array();
            if (!empty($product_files)) {
                $file_data = array_map(function($file) use ($new_product_id, $user_id) {
                    return [
                        'product_id' => $new_product_id,
                        'name' => $file['name'],
                        'type' => $file['type'],
                        'url' => $file['url'],
                        'size' => $file['size'],
                        'date' => $file['date'],
                        'created_by' => $file['created_by'],
                        'updated_by' => $file['updated_by'],
                        'created_at' => $file['created_at'], // Retain original created_at
                        'updated_at' => $file['updated_at'], // Retain original updated_at
                        'is_active' => 1
                    ];
                }, $product_files);
                $this->db->insert_batch('sub_activity_product_files', $file_data);
                if ($this->db->affected_rows() === FALSE) {
                    $this->db->trans_rollback();
                    log_message('error', "Failed to insert sub-activity product files: " . $this->db->error()['message']);
                    return $this->output
                        ->set_content_type('application/json')
                        ->set_status_header(400)
                        ->set_output(json_encode(array(
                            'success' => false,
                            'message' => 'SUB_ACTIVITY_PRODUCT_FILES_NOT_CREATED - ' . $this->db->error()['message']
                        )));
                }
            }
        }

        // Step 5: Copy follow-up activities with original dates
        $this->db->where('parent_sub_activity_id', $sub_activity_id);
        $this->db->where('is_active', 1);
        $follow_up_activities = $this->db->get('sub_activity_follow_up_activities')->result_array();
        foreach ($follow_up_activities as $follow_up) {
            $new_follow_up_data = [
                'parent_sub_activity_id' => $new_sub_activity_id,
                'code' => $follow_up['code'],
                'name' => $follow_up['name'],
                'progress' => $follow_up['progress'],
                'status' => $follow_up['status'],
                'location' => $follow_up['location'],
                'due_date' => $follow_up['due_date'],
                'team_id' => $follow_up['team_id'],
                'inCharges' => $follow_up['inCharges'],
                'comments_count' => $follow_up['comments_count'],
                'created_by' => $follow_up['created_by'],
                'updated_by' => $follow_up['updated_by'],
                'created_at' => $follow_up['created_at'], // Retain original created_at
                'updated_at' => $follow_up['updated_at'], // Retain original updated_at
                'is_active' => 1
            ];
            $this->db->insert('sub_activity_follow_up_activities', $new_follow_up_data);
            $new_follow_up_id = $this->db->insert_id();

            // Copy follow-up activity comments
            $this->db->select('c.id, c.body, c.created_by, c.created_at, c.updated_at, c.is_quarterly');
            $this->db->from('comments c');
            $this->db->where('c.entity_type', 'sub_activity_follow_up_activity');
            $this->db->where('c.entity_id', $follow_up['id']);
            $this->db->where('c.is_active', 1);
            $follow_up_comments = $this->db->get()->result_array();

            if (!empty($follow_up_comments)) {
                $follow_up_comment_data = array_map(function($comment) use ($new_follow_up_id, $user_id) {
                    return [
                        'entity_type' => 'sub_activity_follow_up_activity',
                        'entity_id' => $new_follow_up_id,
                        'body' => $comment['body'],
                        'is_quarterly' => $comment['is_quarterly'],
                        'created_by' => $comment['created_by'],
                        'updated_by' => $comment['updated_by'],
                        'created_at' => $comment['created_at'], // Retain original created_at
                        'updated_at' => $comment['updated_at'], // Retain original updated_at
                        'is_active' => 1
                    ];
                }, $follow_up_comments);
                $this->db->insert_batch('comments', $follow_up_comment_data);
                if ($this->db->affected_rows() === FALSE) {
                    $this->db->trans_rollback();
                    log_message('error', "Failed to insert follow-up activity comments: " . $this->db->error()['message']);
                    return $this->output
                        ->set_content_type('application/json')
                        ->set_status_header(400)
                        ->set_output(json_encode(array(
                            'success' => false,
                            'message' => 'FOLLOW_UP_ACTIVITY_COMMENTS_NOT_CREATED - ' . $this->db->error()['message']
                        )));
                }
            }
        }

        // Step 6: Copy attachments with original dates
        $this->db->where('sub_activity_id', $sub_activity_id);
        $this->db->where('is_active', 1);
        $attachments = $this->db->get('attachments')->result_array();
        foreach ($attachments as $attachment) {
            $new_attachment_data = [
                'sub_activity_id' => $new_sub_activity_id,
                'follow_up_activity_id' => null, // Assuming no follow-up activity attachments unless specified
                'activity_id' => $target_activity_id,
                'title' => $attachment['title'],
                'type' => $attachment['type'],
                'url' => $attachment['url'],
                'size' => $attachment['size'],
                'date' => $attachment['date'],
                'in_charge_ids' => $attachment['in_charge_ids'],
                'created_by' => $attachment['created_by'],
                'updated_by' => $attachment['updated_by'],
                'created_at' => $attachment['created_at'], // Retain original created_at
                'updated_at' => $attachment['updated_at'], // Retain original updated_at
                'is_active' => 1
            ];
            $this->db->insert('attachments', $new_attachment_data);
            $new_attachment_id = $this->db->insert_id();

            // Copy attachment comments
            $this->db->select('c.id, c.body, c.created_by, c.created_at, c.updated_at, c.is_quarterly');
            $this->db->from('comments c');
            $this->db->where('c.entity_type', 'attachment');
            $this->db->where('c.entity_id', $attachment['id']);
            $this->db->where('c.is_active', 1);
            $attachment_comments = $this->db->get()->result_array();

            if (!empty($attachment_comments)) {
                $attachment_comment_data = array_map(function($comment) use ($new_attachment_id, $user_id) {
                    return [
                        'entity_type' => 'attachment',
                        'entity_id' => $new_attachment_id,
                        'body' => $comment['body'],
                        'is_quarterly' => $comment['is_quarterly'],
                        'created_by' => $comment['created_by'],
                        'updated_by' => $comment['updated_by'],
                        'created_at' => $comment['created_at'], // Retain original created_at
                        'updated_at' => $comment['updated_at'], // Retain original updated_at
                        'is_active' => 1
                    ];
                }, $attachment_comments);
                $this->db->insert_batch('comments', $attachment_comment_data);
                if ($this->db->affected_rows() === FALSE) {
                    $this->db->trans_rollback();
                    log_message('error', "Failed to insert attachment comments: " . $this->db->error()['message']);
                    return $this->output
                        ->set_content_type('application/json')
                        ->set_status_header(400)
                        ->set_output(json_encode(array(
                            'success' => false,
                            'message' => 'ATTACHMENT_COMMENTS_NOT_CREATED - ' . $this->db->error()['message']
                        )));
                }
            }

            // Copy attachment files with original dates
            $this->db->where('attachment_id', $attachment['id']);
            $this->db->where('is_active', 1);
            $attachment_files = $this->db->get('attachment_files')->result_array();
            if (!empty($attachment_files)) {
                $file_data = array_map(function($file) use ($new_attachment_id, $user_id) {
                    return [
                        'attachment_id' => $new_attachment_id,
                        'name' => $file['name'],
                        'type' => $file['type'],
                        'url' => $file['url'],
                        'size' => $file['size'],
                        'date' => $file['date'],
                        'created_by' => $file['created_by'],
                        'updated_by' => $file['updated_by'],
                        'created_at' => $file['created_at'], // Retain original created_at
                        'updated_at' => $file['updated_at'], // Retain original updated_at
                        'is_active' => 1
                    ];
                }, $attachment_files);
                $this->db->insert_batch('attachment_files', $file_data);
                if ($this->db->affected_rows() === FALSE) {
                    $this->db->trans_rollback();
                    log_message('error', "Failed to insert attachment files: " . $this->db->error()['message']);
                    return $this->output
                        ->set_content_type('application/json')
                        ->set_status_header(400)
                        ->set_output(json_encode(array(
                            'success' => false,
                            'message' => 'ATTACHMENT_FILES_NOT_CREATED - ' . $this->db->error()['message']
                        )));
                }
            }
        }

        // Commit transaction
        $this->db->trans_complete();

        if ($this->db->trans_status() === FALSE) {
            log_message('error', "Transaction failed: " . $this->db->error()['message']);
            return $this->output
                ->set_content_type('application/json')
                ->set_status_header(400)
                ->set_output(json_encode(array(
                    'success' => false,
                    'message' => 'TRANSACTION_FAILED - ' . $this->db->error()['message']
                )));
        }

        // Fetch new sub-activity for response
        $this->db->where('id', $new_sub_activity_id);
        $new_sub_activity = $this->db->get('sub_activities')->row_array();

        // Prepare inCharges details
        $inCharges_array = json_decode($new_sub_activity['inCharges'], true) ?: [];
        $inCharges_details = [];
        if (!empty($inCharges_array)) {
            $this->db->select('id, first_name, image as avatar');
            $this->db->where_in('id', $inCharges_array);
            $this->db->where('is_active', 1);
            $users = $this->db->get('users')->result_array();
            foreach ($users as $user) {
                $inCharges_details[] = [
                    'id' => (string)$user['id'],
                    'first_name' => $user['first_name'],
                    'avatar' => $user['avatar'] ?? ''
                ];
            }
        }

        $team_response = [
            'name' => $new_sub_activity['team_id'] ? $this->db->where('id', $new_sub_activity['team_id'])->get('teams')->row()->name : 'Sub-Activity Team',
            'members' => $inCharges_details
        ];

        // Fetch related data for response
        $months = $this->get_sub_activity_months($new_sub_activity_id);
        $outputs = $this->get_sub_activity_outputs($new_sub_activity_id);
        $products = $this->get_sub_activity_products($new_sub_activity_id);
        $output_products = $this->get_sub_activity_output_products($new_sub_activity_id);
        $attachments = $this->get_attachments_for_sub_activity($new_sub_activity_id);
        $attachments = array_filter($attachments);
        $comments = $this->get_comments('sub_activity', $new_sub_activity_id); // Fetch comments using get_comments

        // Construct response
        $response_data = [
            'id' => (string)$new_sub_activity['id'],
            'progress' => (string)$new_sub_activity['progress'],
            'name' => $new_sub_activity['name'],
            'code' => floatval($new_sub_activity['code']),
            'months' => $months,
            'team' => $team_response,
            'status' => $new_sub_activity['status'],
            'created_at' => $new_sub_activity['created_at'],
            'location' => $new_sub_activity['location'],
            'outputs' => [
                'status' => $outputs['status'],
                'comments' => $outputs['comments'],
                'planned' => (string)$outputs['planned'],
                'achieved' => (string)$outputs['achieved'],
                'list' => $outputs['list']
            ],
            'comments' => $comments,
            'comments_count' => (string)$new_sub_activity['comments_count'],
            'products' => $products,
            'outputProducts' => $output_products,
            'attachments' => $attachments
        ];

        return $this->output
            ->set_content_type('application/json')
            ->set_status_header(201)
            ->set_output(json_encode(array(
                'success' => true,
                'message' => 'SUB_ACTIVITY_TRANSFERRED_SUCCESSFULLY',
                'data' => $response_data
            )));
    }

    // Helper method to fetch comments (copied from Activities controller for consistency)
    private function get_comments($entity_type, $entity_id, $time_frame = 'quarterly')
    {
        $this->db->select('c.id, c.body, c.created_at, c.updated_at, c.is_quarterly, u.id as user_id, u.first_name, u.last_name, u.image as avatar');
        $this->db->from('comments c');
        $this->db->join('users u', 'u.id = c.created_by', 'left');
        $this->db->where('c.entity_type', $entity_type);
        $this->db->where('c.entity_id', $entity_id);
        $this->db->where('c.is_quarterly', ($time_frame === 'quarterly') ? 1 : 0);
        $this->db->where('c.is_active', 1);
        $this->db->order_by('c.created_at', 'DESC'); // Latest first
        $comments = $this->db->get()->result_array();

        return array_map(function ($comment) {
            return [
                'id' => (string)$comment['id'],
                'body' => $comment['body'],
                'created_at' => $comment['created_at'],
                'updated_at' => $comment['updated_at'],
                'time_frame' => $comment['is_quarterly'] ? 'quarterly' : 'yearly',
                'user' => [
                    'id' => (string)$comment['user_id'],
                    'first_name' => $comment['first_name'],
                    'last_name' => $comment['last_name'],
                    'avatar' => $comment['avatar'] ? $comment['avatar'] : ''
                ]
            ];
        }, $comments);
    }

}