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

class Vouchers 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');
        // avoiding preflight requests
        $method = $_SERVER['REQUEST_METHOD'];
        if ($method == "OPTIONS") {
            die();
        }

        $this->load->helper('form');
        $this->load->library('upload');
        $this->db->query("SET time_zone = '+03:00'");
    }

    /**
     * Upload a new voucher with file
     * POST /api/vouchers
     */
    public function upload_voucher()
    {
        // Get form data
        $voucher_number = $this->input->post('voucher_number');
        $month = $this->input->post('month');
        $year = $this->input->post('year');
        $voucher_date = $this->input->post('voucher_date'); // New field
        $amount = $this->input->post('amount');
        $project = $this->input->post('project');
        $description = $this->input->post('description');
        $user_id = $this->input->post('user_id');

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

        if (empty($voucher_number)) {
            return $this->output
                ->set_content_type('application/json')
                ->set_status_header(400)
                ->set_output(json_encode([
                    'success' => false,
                    'message' => 'Voucher number is required'
                ]));
        }

        if (empty($month)) {
            return $this->output
                ->set_content_type('application/json')
                ->set_status_header(400)
                ->set_output(json_encode([
                    'success' => false,
                    'message' => 'Month is required'
                ]));
        }

        if (empty($year)) {
            return $this->output
                ->set_content_type('application/json')
                ->set_status_header(400)
                ->set_output(json_encode([
                    'success' => false,
                    'message' => 'Year is required'
                ]));
        }

        if (empty($amount) || !is_numeric($amount) || $amount <= 0) {
            return $this->output
                ->set_content_type('application/json')
                ->set_status_header(400)
                ->set_output(json_encode([
                    'success' => false,
                    'message' => 'Valid amount is required'
                ]));
        }

        if (empty($project)) {
            return $this->output
                ->set_content_type('application/json')
                ->set_status_header(400)
                ->set_output(json_encode([
                    'success' => false,
                    'message' => 'Project is required'
                ]));
        }

        // 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([
                    'success' => false,
                    'message' => 'Invalid user ID'
                ]));
        }

        // Check if voucher number already exists
        $this->db->where('voucher_number', $voucher_number);
        $this->db->where('is_active', 1);
        $existing_voucher = $this->db->get('vouchers')->num_rows();

        if ($existing_voucher > 0) {
            return $this->output
                ->set_content_type('application/json')
                ->set_status_header(400)
                ->set_output(json_encode([
                    'success' => false,
                    'message' => 'Voucher number already exists'
                ]));
        }

        // Check if file was uploaded
        if (empty($_FILES['file']['name'])) {
            return $this->output
                ->set_content_type('application/json')
                ->set_status_header(400)
                ->set_output(json_encode([
                    'success' => false,
                    'message' => 'File is required'
                ]));
        }

        // Validate file upload
        if ($_FILES['file']['error'] !== UPLOAD_ERR_OK) {
            return $this->output
                ->set_content_type('application/json')
                ->set_status_header(400)
                ->set_output(json_encode([
                    'success' => false,
                    'message' => 'File upload failed'
                ]));
        }

        // Get file information
        $file_name = $_FILES['file']['name'];
        $file_size = $_FILES['file']['size'];
        $file_tmp = $_FILES['file']['tmp_name'];
        $file_ext = strtolower(pathinfo($file_name, PATHINFO_EXTENSION));

        // Validate file extension
        $allowed_extensions = ['pdf', 'doc', 'docx', 'xls', 'xlsx', 'jpg', 'jpeg', 'png'];
        if (!in_array($file_ext, $allowed_extensions)) {
            return $this->output
                ->set_content_type('application/json')
                ->set_status_header(400)
                ->set_output(json_encode([
                    'success' => false,
                    'message' => 'Invalid file type. Allowed types: ' . implode(', ', $allowed_extensions)
                ]));
        }

        // No file size limit validation

        // Create upload directory if it doesn't exist
        $upload_dir = 'uploads/vouchers/' . $year . '/';
        if (!is_dir($upload_dir)) {
            mkdir($upload_dir, 0755, true);
        }

        // Generate unique filename
        $unique_filename = time() . '_' . $user_id . '_' . uniqid() . '.' . $file_ext;
        $upload_path = $upload_dir . $unique_filename;

        // Move uploaded file
        if (!move_uploaded_file($file_tmp, $upload_path)) {
            return $this->output
                ->set_content_type('application/json')
                ->set_status_header(500)
                ->set_output(json_encode([
                    'success' => false,
                    'message' => 'Failed to save uploaded file'
                ]));
        }

        // Generate URL for the uploaded file
        $file_url = base_url($upload_path);

        // Prepare data for insertion
        $data = [
            'voucher_number' => $voucher_number,
            'month' => $month,
            'year' => $year,
             'voucher_date' => $voucher_date,
            'amount' => $amount,
            'project' => $project,
            'description' => $description,
            'file_url' => $file_url,
            'file_type' => $file_ext,
            'file_size' => $file_size,
            'status' => 'Paid',
            'created_by' => $user_id,
            'updated_by' => $user_id,
            'is_active' => 1,
            'created_at' => date('Y-m-d H:i:s'),
            'updated_at' => date('Y-m-d H:i:s')
        ];

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

        // Insert the voucher
        $insert = $this->db->insert('vouchers', $data);
        if (!$insert) {
            // Delete uploaded file if database insert fails
            if (file_exists($upload_path)) {
                unlink($upload_path);
            }

            $this->db->trans_rollback();
            return $this->output
                ->set_content_type('application/json')
                ->set_status_header(500)
                ->set_output(json_encode([
                    'success' => false,
                    'message' => 'Failed to save voucher to database'
                ]));
        }

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

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

        if ($this->db->trans_status() === FALSE) {
            // Delete uploaded file if transaction fails
            if (file_exists($upload_path)) {
                unlink($upload_path);
            }

            return $this->output
                ->set_content_type('application/json')
                ->set_status_header(500)
                ->set_output(json_encode([
                    'success' => false,
                    'message' => 'Transaction failed'
                ]));
        }

        // Prepare response data
        $response_data = [
            'id' => $voucher_id,
            'voucher_number' => $voucher_number,
            'month' => $month,
            'year' => $year,
             'voucher_date' => $voucher_date,
            'amount' => $amount,
            'project' => $project,
            'description' => $description,
            'file_url' => $file_url,
            'file_type' => $file_ext,
            'file_size' => $file_size,
            'status' => 'Paid',
            'created_by' => $user_id,
            'created_at' => $data['created_at'],
            'updated_at' => $data['updated_at']
        ];

        return $this->output
            ->set_content_type('application/json')
            ->set_status_header(201)
            ->set_output(json_encode([
                'success' => true,
                'message' => 'Voucher uploaded successfully',
                'data' => $response_data
            ]));
    }

    /**
     * Get vouchers with filters
     * GET /api/vouchers?year={year}&month={month}&search={search}&status={status}
     */
    public function get_vouchers()
    {
        $year = $this->input->get('year');
        $month = $this->input->get('month');
        $search = $this->input->get('search');
        $status = $this->input->get('status');

        try {
            // Build query
            $this->db->select('v.*, u.first_name, u.last_name, u.image');
            $this->db->from('vouchers v');
            $this->db->join('users u', 'v.created_by = u.id', 'left');
            $this->db->where('v.is_active', 1);

            // Apply filters
            if (!empty($year)) {
                $this->db->where('v.year', $year);
            }

            if (!empty($month) && $month !== 'All') {
                $this->db->where('v.month', $month);
            }

            if (!empty($status) && $status !== 'All') {
                $this->db->where('v.status', $status);
            }

            if (!empty($search)) {
                $this->db->group_start();
                $this->db->like('v.voucher_number', $search);
                $this->db->or_like('v.project', $search);
                $this->db->group_end();
            }

            $this->db->order_by('v.created_at', 'ASC');

            $vouchers = $this->db->get()->result_array();

            // Format response
            foreach ($vouchers as &$voucher) {
                $voucher['id'] = (int)$voucher['id'];
                $voucher['amount'] = (float)$voucher['amount'];
                $voucher['year'] = (int)$voucher['year'];
                $voucher['file_size'] = (int)$voucher['file_size'];
                $voucher['created_by'] = (int)$voucher['created_by'];
                $voucher['updated_by'] = (int)$voucher['updated_by'];

                // Add creator info
                $voucher['creator'] = [
                    'first_name' => $voucher['first_name'],
                    'last_name' => $voucher['last_name'],
                    'image' => $voucher['image']
                ];

                unset($voucher['first_name'], $voucher['last_name'], $voucher['image']);
            }

            return $this->output
                ->set_content_type('application/json')
                ->set_status_header(200)
                ->set_output(json_encode([
                    'success' => true,
                    'data' => $vouchers
                ]));

        } catch (Exception $e) {
            return $this->output
                ->set_content_type('application/json')
                ->set_status_header(500)
                ->set_output(json_encode([
                    'success' => false,
                    'message' => 'Failed to fetch vouchers: ' . $e->getMessage()
                ]));
        }
    }

    /**
     * Update an existing voucher
     * PUT /api/vouchers/{id}
     */
    public function edit_voucher()
    {
        // Check if it's a file upload (multipart/form-data)
        $is_file_upload = !empty($_FILES['file']['name']);
        
        if ($is_file_upload) {
            // Get data from POST
            $voucher_id = $this->input->post('id');
            $voucher_number = $this->input->post('voucher_number');
            $month = $this->input->post('month');
            $voucher_date = $this->input->post('voucher_date');
            $year = $this->input->post('year');
            $amount = $this->input->post('amount');
            $project = $this->input->post('project_code');
            $description = $this->input->post('description');
            $user_id = $this->input->post('user_id');
        } else {
            // Get data from JSON
            $json_data = json_decode(@file_get_contents('php://input'), true);
            $voucher_id = $json_data['id'];
            $voucher_number = $json_data['voucher_number'];
            $month = $json_data['month'];
            $year = $json_data['year'];
             $voucher_date = $json_data['voucher_date']; // New field
            $amount = $json_data['amount'];
            $project = $json_data['project'];
            $description = $json_data['description'];
            $user_id = $json_data['user_id'];
        }

        // Validate required fields
        if (empty($user_id) || empty($voucher_id)) {
            return $this->output
                ->set_content_type('application/json')
                ->set_status_header(400)
                ->set_output(json_encode([
                    'success' => false,
                    'message' => 'User ID and Voucher ID are required'
                ]));
        }

        // 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([
                    'success' => false,
                    'message' => 'Invalid user ID'
                ]));
        }

        // Validate voucher exists
        $this->db->where('id', $voucher_id);
        $this->db->where('is_active', 1);
        $existing_voucher = $this->db->get('vouchers')->row_array();

        if (empty($existing_voucher)) {
            return $this->output
                ->set_content_type('application/json')
                ->set_status_header(404)
                ->set_output(json_encode([
                    'success' => false,
                    'message' => 'Voucher not found'
                ]));
        }

        // Check if voucher number is being changed and already exists
        if (!empty($voucher_number) && $voucher_number !== $existing_voucher['voucher_number']) {
            $this->db->where('voucher_number', $voucher_number);
            $this->db->where('id !=', $voucher_id);
            $this->db->where('is_active', 1);
            $duplicate = $this->db->get('vouchers')->num_rows();

            if ($duplicate > 0) {
                return $this->output
                    ->set_content_type('application/json')
                    ->set_status_header(400)
                    ->set_output(json_encode([
                        'success' => false,
                        'message' => 'Voucher number already exists'
                    ]));
            }
        }

        // Handle file upload if provided
        $file_url = null;
        $file_ext = null;
        $file_size = null;
        $upload_path = null;

        if ($is_file_upload) {
            // Get file information
            $file_name = $_FILES['file']['name'];
            $file_size = $_FILES['file']['size'];
            $file_tmp = $_FILES['file']['tmp_name'];
            $file_ext = strtolower(pathinfo($file_name, PATHINFO_EXTENSION));

            // Validate file extension
            $allowed_extensions = ['pdf', 'doc', 'docx', 'xls', 'xlsx', 'jpg', 'jpeg', 'png'];
            if (!in_array($file_ext, $allowed_extensions)) {
                return $this->output
                    ->set_content_type('application/json')
                    ->set_status_header(400)
                    ->set_output(json_encode([
                        'success' => false,
                        'message' => 'Invalid file type. Allowed types: ' . implode(', ', $allowed_extensions)
                    ]));
            }

            // Create upload directory if it doesn't exist
            $upload_dir = 'uploads/vouchers/' . $year . '/';
            if (!is_dir($upload_dir)) {
                mkdir($upload_dir, 0755, true);
            }

            // Generate unique filename
            $unique_filename = time() . '_' . $user_id . '_' . uniqid() . '.' . $file_ext;
            $upload_path = $upload_dir . $unique_filename;

            // Move uploaded file
            if (!move_uploaded_file($file_tmp, $upload_path)) {
                return $this->output
                    ->set_content_type('application/json')
                    ->set_status_header(500)
                    ->set_output(json_encode([
                        'success' => false,
                        'message' => 'Failed to save uploaded file'
                    ]));
            }

            // Generate URL for the uploaded file
            $file_url = base_url($upload_path);

            // Delete old file if exists
            if (!empty($existing_voucher['file_url'])) {
                $old_file_path = str_replace(base_url(), '', $existing_voucher['file_url']);
                if (file_exists($old_file_path)) {
                    unlink($old_file_path);
                }
            }
        }

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

        // Update fields only if provided
        if (!empty($voucher_number)) {
            $data['voucher_number'] = $voucher_number;
        }
        if (!empty($month)) {
            $data['month'] = $month;
        }
        if (!empty($year)) {
            $data['year'] = $year;
        }
         if (!empty($voucher_date)) {
            $data['voucher_date'] = $voucher_date;
        }
        if (!empty($amount)) {
            $data['amount'] = $amount;
        }
        if (!empty($project)) {
            $data['project'] = $project;
        }
        if (isset($description)) {
            $data['description'] = $description;
        }

        // Add file data if new file was uploaded
        if ($file_url) {
            $data['file_url'] = $file_url;
            $data['file_type'] = $file_ext;
            $data['file_size'] = $file_size;
        }

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

        // Update the voucher
        $this->db->where('id', $voucher_id);
        $update = $this->db->update('vouchers', $data);

        if (!$update) {
            $this->db->trans_rollback();
            return $this->output
                ->set_content_type('application/json')
                ->set_status_header(500)
                ->set_output(json_encode([
                    'success' => false,
                    'message' => 'Failed to update voucher'
                ]));
        }

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

        if ($this->db->trans_status() === FALSE) {
            return $this->output
                ->set_content_type('application/json')
                ->set_status_header(500)
                ->set_output(json_encode([
                    'success' => false,
                    'message' => 'Transaction failed'
                ]));
        }

        // Get updated voucher data
        $this->db->where('id', $voucher_id);
        $updated_voucher = $this->db->get('vouchers')->row_array();

        return $this->output
            ->set_content_type('application/json')
            ->set_status_header(200)
            ->set_output(json_encode([
                'success' => true,
                'message' => 'Voucher updated successfully',
                'data' => $updated_voucher
            ]));
    }


    /**
     * Delete (soft delete) a voucher
     * DELETE /api/vouchers/{id}
     */
    public function delete_voucher()
    {
        $json_data = json_decode(@file_get_contents('php://input'), true);
        $voucher_id = $json_data['id'];
        $user_id = $json_data['user_id'];

        // Validate required fields
        if (empty($user_id) || empty($voucher_id)) {
            return $this->output
                ->set_content_type('application/json')
                ->set_status_header(400)
                ->set_output(json_encode([
                    'success' => false,
                    'message' => 'User ID and Voucher ID are required'
                ]));
        }

        // 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([
                    'success' => false,
                    'message' => 'Invalid user ID'
                ]));
        }

        // Validate voucher exists
        $this->db->where('id', $voucher_id);
        $this->db->where('is_active', 1);
        $existing_voucher = $this->db->get('vouchers')->row_array();

        if (empty($existing_voucher)) {
            return $this->output
                ->set_content_type('application/json')
                ->set_status_header(404)
                ->set_output(json_encode([
                    'success' => false,
                    'message' => 'Voucher not found'
                ]));
        }

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

        // Soft delete the voucher
        $this->db->where('id', $voucher_id);
        $delete = $this->db->update('vouchers', [
            'is_active' => 0,
            'updated_by' => $user_id,
            'updated_at' => date('Y-m-d H:i:s')
        ]);

        if (!$delete) {
            $this->db->trans_rollback();
            return $this->output
                ->set_content_type('application/json')
                ->set_status_header(500)
                ->set_output(json_encode([
                    'success' => false,
                    'message' => 'Failed to delete voucher'
                ]));
        }

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

        if ($this->db->trans_status() === FALSE) {
            return $this->output
                ->set_content_type('application/json')
                ->set_status_header(500)
                ->set_output(json_encode([
                    'success' => false,
                    'message' => 'Transaction failed'
                ]));
        }

        return $this->output
            ->set_content_type('application/json')
            ->set_status_header(200)
            ->set_output(json_encode([
                'success' => true,
                'message' => 'Voucher deleted successfully'
            ]));
    }

    /**
     * Update voucher status
     * PUT /api/vouchers/{id}/status
     */
    public function update_voucher_status()
    {
        $json_data = json_decode(@file_get_contents('php://input'), true);
        $voucher_id = $json_data['id'];
        $status = $json_data['status'];
        $user_id = $json_data['user_id'];

        // Validate required fields
        if (empty($user_id) || empty($voucher_id) || empty($status)) {
            return $this->output
                ->set_content_type('application/json')
                ->set_status_header(400)
                ->set_output(json_encode([
                    'success' => false,
                    'message' => 'User ID, Voucher ID, and Status are required'
                ]));
        }

        // Validate status
        $allowed_statuses = ['Pending', 'Approved', 'Rejected', 'Paid'];
        if (!in_array($status, $allowed_statuses)) {
            return $this->output
                ->set_content_type('application/json')
                ->set_status_header(400)
                ->set_output(json_encode([
                    'success' => false,
                    'message' => 'Invalid status. Allowed: ' . implode(', ', $allowed_statuses)
                ]));
        }

        // Validate voucher exists
        $this->db->where('id', $voucher_id);
        $this->db->where('is_active', 1);
        $existing_voucher = $this->db->get('vouchers')->row_array();

        if (empty($existing_voucher)) {
            return $this->output
                ->set_content_type('application/json')
                ->set_status_header(404)
                ->set_output(json_encode([
                    'success' => false,
                    'message' => 'Voucher not found'
                ]));
        }

        // Update voucher status
        $this->db->where('id', $voucher_id);
        $update = $this->db->update('vouchers', [
            'status' => $status,
            'updated_by' => $user_id,
            'updated_at' => date('Y-m-d H:i:s')
        ]);

        if (!$update) {
            return $this->output
                ->set_content_type('application/json')
                ->set_status_header(500)
                ->set_output(json_encode([
                    'success' => false,
                    'message' => 'Failed to update status'
                ]));
        }

        // Get updated voucher
        $this->db->where('id', $voucher_id);
        $updated_voucher = $this->db->get('vouchers')->row_array();

        return $this->output
            ->set_content_type('application/json')
            ->set_status_header(200)
            ->set_output(json_encode([
                'success' => true,
                'message' => 'Status updated successfully',
                'data' => $updated_voucher
            ]));
    }
}
