<?php

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

class Credit_notes extends AdminController
{
    public function __construct()
    {
        parent::__construct();
        $this->load->model('credit_notes_model');
    }

    /* Get all credit ntoes in case user go on index page */
    public function index($id = '')
    {
        $this->list_credit_notes($id);
    }

    /* List all credit ntoes datatables */
    public function list_credit_notes($id = '')
    {
        if (staff_cant('view', 'credit_notes') && staff_cant('view_own', 'credit_notes')) {
            access_denied('credit_notes');
        }


        close_setup_menu();

        $data['years']          = $this->credit_notes_model->get_credits_years();
        $data['statuses']       = $this->credit_notes_model->get_statuses();
        $data['credit_note_id'] = $id;
        $data['title']          = _l('credit_notes');
        $data['table'] = App_table::find('credit_notes');
        $this->load->view('admin/credit_notes/manage', $data);
    }

    public function table($clientid = '')
    {
        if (staff_cant('view', 'credit_notes') && staff_cant('view_own', 'credit_notes')) {
            ajax_access_denied();
        }

        App_table::find('credit_notes')->output([
            'clientid' => $clientid,
        ]);
    }

    public function update_number_settings($id)
    {
        $response = [
            'success' => false,
            'message' => '',
        ];

        if (staff_can('edit',  'credit_notes')) {
            if ($this->input->post('prefix')) {
                $this->db->where('id', $id);
                $this->db->update(db_prefix() . 'creditnotes', [
                    'prefix' => $this->input->post('prefix'),
                ]);

                if ($this->db->affected_rows() > 0) {
                    $this->credit_notes_model->save_formatted_number($id);
                    $response['success'] = true;
                    $response['message'] = _l('updated_successfully', _l('credit_note'));
                }
            }
        }
        echo json_encode($response);
        die;
    }

    public function validate_number()
    {
        $isedit          = $this->input->post('isedit');
        $number          = $this->input->post('number');
        $date            = $this->input->post('date');
        $original_number = $this->input->post('original_number');
        $number          = trim($number);
        $number          = ltrim($number, '0');
        if ($isedit == 'true') { 
            if ($number == $original_number) {
                echo json_encode(true);
                die;
            }
        }
        if (total_rows(db_prefix() . 'creditnotes', [
            'YEAR(date)' => date('Y', strtotime(to_sql_date($date))),
            'number' => $number,
        ]) > 0) {
            echo 'false';
        } else {
            echo 'true';
        }
    }

    /* Add new invoice or update existing */
    public function credit_note($id = '')
    {
        if (staff_cant('view', 'credit_notes') && staff_cant('view_own', 'credit_notes')) {
            access_denied('credit_notes');
        }
        if ($this->input->post()) {
            $credit_note_data = $this->input->post();
            if ($id == '') {
                if (staff_cant('create', 'credit_notes')) {
                    access_denied('credit_notes');
                }
                $id = $this->credit_notes_model->add($credit_note_data);
                if ($id) {
                    set_alert('success', _l('added_successfully', _l('credit_note')));
                    redirect(admin_url('credit_notes/list_credit_notes/' . $id));
                }
            } else {
                if (staff_cant('edit', 'credit_notes')) {
                    access_denied('credit_notes');
                }
                $success = $this->credit_notes_model->update($credit_note_data, $id);
                if ($success) {
                    set_alert('success', _l('updated_successfully', _l('credit_note')));
                }
                redirect(admin_url('credit_notes/list_credit_notes/' . $id));
            }
        }
        if ($id == '') {
            $title = _l('add_new', _l('credit_note'));
        } else {
            $credit_note = $this->credit_notes_model->get($id);

            if (!$credit_note || (staff_cant('view', 'credit_notes') && $credit_note->addedfrom != get_staff_user_id())) {
                blank_page(_l('credit_note_not_found'), 'danger');
            }

            $data['credit_note'] = $credit_note;
            $data['edit']        = true;
            $title               = _l('edit', _l('credit_note')) . ' - ' . format_credit_note_number($credit_note->id);
        }

        if ($this->input->get('customer_id')) {
            $data['customer_id'] = $this->input->get('customer_id');
        }

        $this->load->model('taxes_model');
        $data['taxes'] = $this->taxes_model->get();
        $this->load->model('invoice_items_model');

        $data['ajaxItems'] = false;
        if (total_rows(db_prefix() . 'items') <= ajax_on_total_items()) {
            $data['items'] = $this->invoice_items_model->get_grouped();
        } else {
            $data['items']     = [];
            $data['ajaxItems'] = true;
        }

        $data['items_groups'] = $this->invoice_items_model->get_groups();

        $this->load->model('currencies_model');
        $data['currencies'] = $this->currencies_model->get();

        $data['base_currency'] = $this->currencies_model->get_base_currency();

        $data['title']     = $title;
        $data['bodyclass'] = 'credit-note';
        $this->load->view('admin/credit_notes/credit_note', $data);
    }

    public function apply_credits_to_invoices($credit_note_id)
    {
        $creditApplied = false;
        if ($this->input->post()) {
            foreach ($this->input->post('amount') as $invoice_id => $amount) {
                if ($this->credit_notes_model->apply_credits($credit_note_id, ['amount' => $amount, 'invoice_id' => $invoice_id])) {
                    update_invoice_status($invoice_id, true);
                    $creditsApplied = true;
                }
            }
        }
        if ($creditApplied) {
            set_alert('success', _l('credits_successfully_applied_to_invoices'));
        }
        redirect(admin_url('credit_notes/list_credit_notes/' . $credit_note_id));
    }

    public function credit_note_from_invoice($invoice_id)
    {
        if (staff_can('create',  'credit_notes')) {
            $id = $this->credit_notes_model->credit_note_from_invoice($invoice_id);

            if ($id) {
                redirect(admin_url('credit_notes/credit_note/' . $id));
            }
        }
        redirect(admin_url('invoices/list_invoices/' . $invoice_id));
    }

    public function refund($id, $refund_id = null)
    {
        if (staff_can('edit',  'credit_notes')) {
            $this->load->model('payment_modes_model');
            if (!$refund_id) {
                $data['payment_modes'] = $this->payment_modes_model->get('', [
                    'expenses_only !=' => 1,
                ]);
            } else {
                $data['refund']        = $this->credit_notes_model->get_refund($refund_id);
                $data['payment_modes'] = $this->payment_modes_model->get('', [], true, true);
                $i                     = 0;
                foreach ($data['payment_modes'] as $mode) {
                    if ($mode['active'] == 0 && $data['refund']->payment_mode != $mode['id']) {
                        unset($data['payment_modes'][$i]);
                    }
                    $i++;
                }
            }

            $data['credit_note'] = $this->credit_notes_model->get($id);
            $this->load->view('admin/credit_notes/refund', $data);
        }
    }

    public function create_refund($credit_note_id)
    {
        if (staff_can('edit',  'credit_notes')) {
            $data                = $this->input->post();
            $data['refunded_on'] = to_sql_date($data['refunded_on']);
            $data['staff_id']    = get_staff_user_id();
            $success             = $this->credit_notes_model->create_refund($credit_note_id, $data);

            if ($success) {
                set_alert('success', _l('added_successfully', _l('refund')));
            }
        }

        redirect(admin_url('credit_notes/list_credit_notes/' . $credit_note_id));
    }

    public function edit_refund($refund_id, $cerdit_note_id)
    {
        if (staff_can('edit',  'credit_notes')) {
            $data                = $this->input->post();
            $data['refunded_on'] = to_sql_date($data['refunded_on']);
            $success             = $this->credit_notes_model->edit_refund($refund_id, $data);

            if ($success) {
                set_alert('success', _l('updated_successfully', _l('refund')));
            }
        }

        redirect(admin_url('credit_notes/list_credit_notes/' . $cerdit_note_id));
    }

    public function delete_refund($refund_id, $credit_note_id)
    {
        if (staff_can('delete',  'credit_notes')) {
            $success = $this->credit_notes_model->delete_refund($refund_id, $credit_note_id);
            if ($success) {
                set_alert('success', _l('deleted', _l('refund')));
            }
        }
        redirect(admin_url('credit_notes/list_credit_notes/' . $credit_note_id));
    }

    /* Get all invoice note data */
    public function get_credit_note_data_ajax($id)
    {
        if (staff_cant('view', 'credit_notes') && staff_cant('view_own', 'credit_notes')) {
            echo _l('access_denied');
            die;
        }

        if (!$id) {
            die(_l('credit_note_not_found'));
        }

        $credit_note = $this->credit_notes_model->get($id);

        if (!$credit_note || (staff_cant('view', 'credit_notes') && $credit_note->addedfrom != get_staff_user_id())) {
            echo _l('credit_note_not_found');
            die;
        }

        $data = prepare_mail_preview_data('credit_note_send_to_customer', $credit_note->clientid);

        $data['credit_note']                   = $credit_note;
        $data['members']                       = $this->staff_model->get('', ['active' => 1]);
        $data['available_creditable_invoices'] = $this->credit_notes_model->get_available_creditable_invoices($id);

        $this->load->view('admin/credit_notes/credit_note_preview_template', $data);
    }

    public function mark_open($id)
    {
        if (total_rows(db_prefix() . 'creditnotes', ['status' => 3, 'id' => $id]) > 0 && staff_can('edit',  'credit_notes')) {
            $this->credit_notes_model->mark($id, 1);
        }

        redirect(admin_url('credit_notes/list_credit_notes/' . $id));
    }

    public function delete_attachment($id)
    {
        $file = $this->misc_model->get_file($id);
        if ($file->staffid == get_staff_user_id() || is_admin()) {
            echo $this->credit_notes_model->delete_attachment($id);
        } else {
            ajax_access_denied();
        }
    }

    public function mark_void($id)
    {
        $credit_note = $this->credit_notes_model->get($id);
        if ($credit_note->status != 2 && $credit_note->status != 3 && !$credit_note->credits_used && staff_can('edit',  'credit_notes')) {
            $this->credit_notes_model->mark($id, 3);
        }
        redirect(admin_url('credit_notes/list_credit_notes/' . $id));
    }

    /* Send credit note to email */
    public function send_to_email($id)
    {
        if (staff_cant('view', 'credit_notes') && staff_cant('view_own', 'credit_notes')) {
            access_denied('credit_notes');
        }
        $success = $this->credit_notes_model->send_credit_note_to_client($id, $this->input->post('attach_pdf'), $this->input->post('cc'));
        // In case client use another language
        load_admin_language();
        if ($success) {
            set_alert('success', _l('credit_note_sent_to_client_success'));
        } else {
            set_alert('danger', _l('credit_note_sent_to_client_fail'));
        }
        redirect(admin_url('credit_notes/list_credit_notes/' . $id));
    }

    public function delete_invoice_applied_credit($id, $credit_id, $invoice_id)
    {
        if (staff_can('delete',  'credit_notes')) {
            $this->credit_notes_model->delete_applied_credit($id, $credit_id, $invoice_id);
        }
        redirect(admin_url('invoices/list_invoices/' . $invoice_id));
    }

    public function delete_credit_note_applied_credit($id, $credit_id, $invoice_id)
    {
        if (staff_can('delete',  'credit_notes')) {
            $this->credit_notes_model->delete_applied_credit($id, $credit_id, $invoice_id);
        }
        redirect(admin_url('credit_notes/list_credit_notes/' . $credit_id));
    }

    /* Delete credit note */
    public function delete($id)
    {
        if (staff_cant('delete', 'credit_notes')) {
            access_denied('credit_notes');
        }

        if (!$id) {
            redirect(admin_url('credit_notes'));
        }

        $credit_note = $this->credit_notes_model->get($id);

        if ($credit_note->credits_used || $credit_note->status == 2) {
            $success = false;
        } else {
            $success = $this->credit_notes_model->delete($id);
        }

        if ($success) {
            set_alert('success', _l('deleted', _l('credit_note')));
        } else {
            set_alert('warning', _l('problem_deleting', _l('credit_note_lowercase')));
        }

        redirect(admin_url('credit_notes'));
    }

    /* Generates credit note PDF and send to email */
    public function pdf($id)
    {
        if (staff_cant('view', 'credit_notes') && staff_cant('view_own', 'credit_notes')) {
            access_denied('credit_notes');
        }
        if (!$id) {
            redirect(admin_url('credit_notes/list_credit_notes'));
        }
        $credit_note        = $this->credit_notes_model->get($id);
        $credit_note_number = format_credit_note_number($credit_note->id);

        try {
            $pdf = credit_note_pdf($credit_note);
        } catch (Exception $e) {
            $message = $e->getMessage();
            echo $message;
            if (strpos($message, 'Unable to get the size of the image') !== false) {
                show_pdf_unable_to_get_image_size_error();
            }
            die;
        }

        $type = 'D';

        if ($this->input->get('output_type')) {
            $type = $this->input->get('output_type');
        }

        if ($this->input->get('print')) {
            $type = 'I';
        }

        $pdf->Output(mb_strtoupper(slug_it($credit_note_number)) . '.pdf', $type);
    }


    //LHDN Credit Note

/* LHDN Credit Note */
    public function process_selected_invoices($id, $invoice_id)
    {
        
        if (!$id) {
            die(_l('credit_note_not_found'));
        }
         $this->load->model('invoices_model');
        $invoice = $this->invoices_model->get($invoice_id);
        $credit_note = $this->credit_notes_model->get($id);

        $credit_note_items = $this->credit_notes_model->get_credit_note_by_items($id);
        

      

        $process_invoice = $this->process_credit_note_api_batch($credit_note,$credit_note_items,$invoice);       

       if (isset($process_invoice['tokenResult'])) {
        
         set_alert('danger', $process_invoice);
        
        }  
     
        // 3) fetch longID
        $longID = $this->check_document_longID($id);
       if (! $longID) {
      set_alert('warning', 'Could not retrieve longID for this invoice.');
       }
       else{
        set_alert('success', 'The Credit Note has been successfully generated.');
       }

        redirect(admin_url('credit_notes/list_credit_notes/' . $id));
    }





    //LHDN Credit Note

private function submitDocuments($requestBody, $token)
{
    // Load the custom cURL library
    $this->load->library('curl');
    $submitUrl = myinv_submit_url();

    try {
        log_message('info', 'Submitting document with payload: ' . json_encode($requestBody));

        // Send POST request using the custom cURL library
        $response = $this->curl->simple_post($submitUrl, $requestBody, [
            'headers' => [
                'Authorization: Bearer ' . $token,
                'Content-Type: application/json'
            ]
        ]);

        if (!$response) {
            log_message('error', 'No response from CreditNote API.');
            return null;
        }

        // Log HTTP status code if available
        if (isset($response['http_code'])) {
            log_message('info', 'HTTP Code: ' . $response['http_code']);
        }

        $responseData = json_decode($response['response'], true);

        // Log the full API response for debugging
        log_message('info', 'Full CreditNote API Response: ' . json_encode($responseData));


        // Check if the API returned an error field
        //$detailMessage = 'Unknown error';

$detailMessage = null;
    if (! empty($responseData['rejectedDocuments'])
        && isset($responseData['rejectedDocuments'][0]['error']['details'])
        && is_array($responseData['rejectedDocuments'][0]['error']['details'])
        && isset($responseData['rejectedDocuments'][0]['error']['details'][0]['message'])
    ) {
        $detailMessage = $responseData['rejectedDocuments'][0]['error']['details'][0]['message'];
        log_message('error', 'MyInvois detail error: ' . $detailMessage);
        $responseData['detailMessage'] = $detailMessage;
        return $responseData;
    }

      // If submissionUid exists, log accepted and rejected documents
        if (isset($responseData['submissionUid'])) {
            log_message('info', 'Submission UID: ' . $responseData['submissionUid']);

            if (!empty($responseData['acceptedDocuments'])) {
                log_message('info', 'Accepted Documents: ' . json_encode($responseData['acceptedDocuments']));
            }

            if (!empty($responseData['rejectedDocuments'])) {
                log_message('warning', 'Rejected Documents: ' . json_encode($responseData['rejectedDocuments']));
            }

            return $responseData;
        }

        // If no submissionUid is found, log the entire response as an error
        log_message('error', 'Submission CreditNote UID not found in response. Full response: ' . json_encode($responseData));
        // Output Error Details
        if (isset($responseData['error'])) {
       $err = $responseData['error'];
  
    if (is_string($err)) {      
        $errorMsg = $err;
    } elseif (is_array($err)) {    
        if (! empty($err['message'])) {
            $errorMsg = $err['message'];
        } elseif (
            ! empty($err['details'])
            && is_array($err['details'])
            && ! empty($err['details'][0]['message'])
        ) {
            $errorMsg = $err['details'][0]['message'];
        } else {
            $errorMsg = 'An unknown API error occurred.';
        }
    } else {
        $errorMsg = 'An unexpected API error format was returned.';
    }
    set_alert('danger', $errorMsg);  
    log_activity('Credit Note Full API Response:' . $errorMsg);

}
     elseif (
    ! empty($responseData['rejectedDocuments'])
    && is_array($responseData['rejectedDocuments'])
) {
    $firstRej = $responseData['rejectedDocuments'][0];
    if (isset($firstRej['error'])) {
        $err = $firstRej['error'];
        // drill down to the actual message
        if (! empty($err['message'])) {
            $errorMsg = $err['message'];
        } elseif (
            ! empty($err['details'])
            && is_array($err['details'])
            && ! empty($err['details'][0]['message'])
        ) {
            $errorMsg = $err['details'][0]['message'];
        } else {
            $errorMsg = 'An unknown document‐level error occurred.';
        }
        set_alert('danger', $errorMsg);
        log_activity('Credit Note document rejected: ' . $errorMsg);
    }
}

    } catch (Exception $e) {
        log_message('error', 'Document submission error: ' . $e->getMessage());
        log_message('error', 'Exception trace: ' . $e->getTraceAsString());
        return null;
    }
}

    
    public function process_credit_note_api_batch($credit_note,$credit_note_items,$invoice)
{
    // Step 1: Get token
    $tokenData = $this->getTokenFromLoginEndpoint();
    if (!$tokenData) {
        log_message('error', 'Failed to retrieve access token.');
        log_activity('Credit Note tokenData:' . 'Failed to retrieve access token.');

        $this->output
            ->set_status_header(401)
            ->set_content_type('application/json')
            ->set_output(json_encode(['error' => 'Failed to retrieve token']));
         return ['tokenResult' => 'Failed to retrieve token'];
    }
    $token = $tokenData['access_token'];
    log_message('info', 'Access Token: ' . $token);
    log_message('info', 'Token Expiry: ' . $tokenData['expires_in'] . ' seconds');

    // Step 2: Encode and prepare the document
    $base64Document = $this->encodeDocumentToBase64_CN($credit_note, $credit_note_items,$invoice);
    $requestBody = $this->appendBase64ToRequestBody($base64Document, $credit_note);

    // Log the request body for debugging
    log_message('info', 'Request Body: ' . json_encode($requestBody));

    // Step 3: Submit the document
    $response = $this->submitDocuments($requestBody, $token);
    if (!$response) {
        log_message('error', 'Document submission failed.' );
     
        $this->output
            ->set_status_header(400)
            ->set_content_type('application/json')
            ->set_output(json_encode(['error' => 'Document submission failed']));
        return;
    }

    // Step 4: Process the API response
    $submissionUid = isset($response['submissionUid']) ? $response['submissionUid'] : null;
    $acceptedDocuments = $response['acceptedDocuments'] ?? [];
    $rejectedDocuments = $response['rejectedDocuments'] ?? [];
    $uuid = isset($response['acceptedDocuments'][0]['uuid']) ? $response['acceptedDocuments'][0]['uuid'] : null;
    $detailMessage = $response['detailMessage'] ?? null;
    
    $invoiceTid = $acceptedDocuments[0]['invoiceCodeNumber'] ?? $rejectedDocuments[0]['invoiceCodeNumber'] ?? null;

    if (! $uuid) {
    log_message('error', 'No UUID found for accepted document.');
    $status = 'error';
} else {
    $status = 'success';
    $detailMessage = NULL;
}


 $retrievedDetails = $this->getSubmittedDocument($submissionUid, $token);
    if (!$retrievedDetails) {
        $this->output
            ->set_status_header(400)
            ->set_content_type('application/json')
            ->set_output(json_encode(['error' => 'Failed to retrieve submission details']));
        return;
    }

    //$this->load->model('Invoices_model'); // Ensure the model is loaded
    $updateResult = $this->credit_notes_model->update_submission_data(
        $invoiceTid,
        $submissionUid,
        $acceptedDocuments,
        $detailMessage,
        $uuid,
        $status
    );

    if (!$updateResult) {
        log_message('error', 'Failed to update invoice with submission data.');
    } else {
        log_message('info', 'Invoice updated with submission data successfully.');
    }

    // Prepare final output data
    $result = [
        'submissionUid'      => $submissionUid,
        'acceptedDocuments'  => $acceptedDocuments,
        'rejectedDocuments'  => $rejectedDocuments,
        'submissionDetails'  => $retrievedDetails,
        // 'documentDetails' => $documentDetails, // Uncomment if implemented
    ];




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


private function getTokenFromLoginEndpoint()
{
    //$clientId = "3c6c52e7-e251-4d27-8aad-f2144ccc2592";
    //$clientSecret = "8449b500-b6ac-4c40-9a46-5c661c61389b";
    //$url = "https://preprod-api.myinvois.hasil.gov.my/connect/token";
    
      //Production
        $url  = myinv_token_url();
        $creds = myinv_credentials();
        $clientId     = $creds['clientId'];
        $clientSecret = $creds['clientSecret'];

    // Prepare POST data
    $postData = http_build_query([
        'client_id' => $clientId,
        'client_secret' => $clientSecret,
        'grant_type' => 'client_credentials',
        'scope' => 'InvoicingAPI'
    ]);

    // Initialize cURL session
    $ch = curl_init($url);

    // Set cURL options
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $postData);
    curl_setopt($ch, CURLOPT_HTTPHEADER, [
        'Content-Type: application/x-www-form-urlencoded'
    ]);

    // Execute the request
    $response = curl_exec($ch);

    // Check for errors
    if (curl_errno($ch)) {
        log_message('error', 'Token retrieval cURL error: ' . curl_error($ch));
        curl_close($ch);
        return null;
    }

    // Get HTTP status code
    $http_status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    curl_close($ch);

    // Log and process the response
    log_message('info', 'Token API Response: ' . $response);

    if ($http_status === 200) {
        return json_decode($response, true);
    } else {
        log_message('error', 'Failed to retrieve token. Status: ' . $http_status);
        log_activity('Failed to retrieve token. Status: ' . $http_status);
        return null;
    }
}











    private function encodeDocumentToBase64_CN($credit_note,$credit_note_items,$invoice)
    {
// 1. Build a DateTime in Malaysia time
//$dt = new DateTime($invoice->datecreated, new DateTimeZone('Asia/Kuala_Lumpur'));

// 2. Switch it over to UTC
$dt = new DateTime($credit_note->datecreated, new DateTimeZone('Asia/Kuala_Lumpur'));

// 2. Switch it over to UTC
$dt->setTimezone(new DateTimeZone('UTC'));

// 3. Grab the UTC date and UTC time (with Z)
$issueDateUtc = $dt->format('Y-m-d');       // e.g. "2025-06-09"
$issueTimeUtc = $dt->format('H:i:s') . 'Z'; // e.g. "23:47:34Z"

// 4. Tax
$subtotal    = (float) $credit_note->subtotal;   
$totalTax    = (float) $credit_note->total_tax; 

// 5.Country Code IdentificationCode
$countries = get_all_countries();
$map = array_column($countries, 'iso3', 'country_id');
$identificationCode = isset($map[$invoice->client->country]) 
       ? $map[$invoice->client->country] 
       : 'NA';

// 6.Buyer TIN
$registerType = get_custom_field_value($invoice->clientid, 6, 'customers', false);//Individu||Company
$idType_c = get_custom_field_value($invoice->clientid, 7, 'customers', false);
$idNo   = get_custom_field_value($invoice->clientid, 8, 'customers', false);
$storedTin   = $invoice->client->tin ?? '';
$idType      = $idType_c ?? '';
$defaultTin  = 'EI00000000010'; 


//7.Currency
$customer_currency = $invoice->currency_name;


//8. Register as Company or Individu
$primaryContactId = get_primary_contact_user_id($invoice->clientid); 
$primary_contact = e(get_contact_full_name($primaryContactId));//Primary Contact Name
$primary_email = get_contact_email($primaryContactId);
$registrationName = ($idType === 'BRN') ? $invoice->client->company : $primary_contact;

//9.Classification Code
$classCode = (empty($idNo) || empty($storedTin))
    ? '004'
    : '010';


if (empty($storedTin)) {
    switch ($idType) {
        case 'NRIC':
            $defaultTin = 'EI00000000010';
            break;
        case 'PASSPORT':
            $defaultTin = 'EI00000000020';
            break;
        case 'ARMY':
            $defaultTin = 'EI00000000040';
            break;
        default:
            $defaultTin = 'EI00000000010'; 
    }
}
if($classCode === '004'){ $defaultTin = 'EI00000000010';$idNo = "NA";}
// if we have a stored one, use it; otherwise the default
$tin = $storedTin !== '' ? $storedTin : $defaultTin;


    log_message('info', 'Submitting document with payloadx: ' . json_encode($invoice));

        // Prepare the document as an array
        $document = [

            
  "_D"=> "urn:oasis:names:specification:ubl:schema:xsd:Invoice-2",
  "_A"=> "urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2",
  "_B"=> "urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2",


  
  "Invoice"=> [
    [
      "ID"=> [
        [
          "_"=> format_credit_note_number($credit_note->id)
        ]
      ],
      "IssueDate"=> [
        [
          "_"=> $issueDateUtc
        ]
      ],
      "IssueTime"=> [
        [
          "_"=> $issueTimeUtc
        ]
      ],
      "InvoiceTypeCode"=> [
        [
          "_"=> "02", //https://sdk.myinvois.hasil.gov.my/files/EInvoiceTypes.json
          "listVersionID"=> "1.0"
        ]
      ],
      "DocumentCurrencyCode"=> [
        [
          "_"=> $customer_currency
        ]
      ],
      "TaxCurrencyCode"=> [
        [
          "_"=> $customer_currency
        ]
      ],
      "InvoicePeriod"=> [
        [
          "StartDate"=> [
            [
              "_"=> _d($invoice->date)
            ]
          ],
          "EndDate"=> [
            [
              "_"=> _d($invoice->duedate)
            ]
          ],
          "Description"=> [
            [
              "_"=> "Not Applicable"
            ]
          ]
        ]
      ],
      "BillingReference"=> [
        [
            "InvoiceDocumentReference"=> [
            [
              "ID"=> [
                [
                  "_"=> format_invoice_number($invoice->id)
                ]              ],
              "UUID"=> [
                [
                  "_"=> $invoice->uuid
                ]
              ]
           ]
          ],
          "AdditionalDocumentReference"=> [
            [
              "ID"=> [
                [
                  "_"=> ""
                ]
              ]
            ]
          ]
        ]
      ],
      "AdditionalDocumentReference"=> [
        [
          "ID"=> [
            [
              "_"=> ""
            ]
          ],
          "DocumentType"=> [
            [
              "_"=> ""
            ]
          ]
        ],
        [
          "ID"=> [
            [
              "_"=> ""
            ]
          ],
          "DocumentType"=> [
            [
              "_"=> ""
            ]
          ],
          "DocumentDescription"=> [
            [
              "_"=> ""
            ]
          ]
        ],
        [
          "ID"=> [
            [
              "_"=> ""
            ]
          ],
          "DocumentType"=> [
            [
              "_"=> ""
            ]
          ]
        ],
        [
          "ID"=> [
            [
              "_"=> ""
            ]
          ]
        ]
      ],
      "AccountingSupplierParty"=> [
        [
          "Party"=> [
            [
              "IndustryClassificationCode"=> [
                [
                  "_"=> "85302",
                  "name"=> "College and university education (Private)"
                ]
              ],
              "PartyIdentification"=> [
                [
                  "ID"=> [
                    [
                      "_"=> myinv_profile_get('tin'),
                      "schemeID"=> "TIN"
                    ]
                  ]
                ],
                [
                  "ID"=> [
                    [
                      "_"=> myinv_profile_get('id_no'),
                      "schemeID"=> myinv_profile_get('id_type')
                    ]
                  ]
                ],
                [
                  "ID"=> [
                    [
                      "_"=> myinv_profile_get('sst_no'),
                      "schemeID"=> "SST"
                    ]
                  ]
                ],
                [
                  "ID"=> [
                    [
                      "_"=> "",
                      "schemeID"=> "TTX"
                    ]
                  ]
                ]
              ],
              "PostalAddress"=> [
                [
                  "CityName"=> [
                    [
                      "_"=> myinv_profile_get('company_city')
                    ]
                  ],
                  "PostalZone"=> [
                    [
                      "_"=> myinv_profile_get('company_postcode')
                    ]
                  ],
                  "CountrySubentityCode"=> [
                    [
                      "_"=> "14"
                    ]
                  ],
                  "AddressLine"=> [
                    [
                      "Line"=> [
                        [
                          "_"=> myinv_profile_get('company_address')
                        ]
                      ]
                    ],
                    [
                      "Line"=> [
                        [
                          "_"=> ""
                        ]
                      ]
                    ],
                    [
                      "Line"=> [
                        [
                          "_"=> ""
                        ]
                      ]
                    ]
                  ],
                  "Country"=> [
                    [
                      "IdentificationCode"=> [
                        [
                          "_"=> "MYS",
                          "listID"=> "ISO3166-1",
                          "listAgencyID"=> "6"
                        ]
                      ]
                    ]
                  ]
                ]
              ],
              "PartyLegalEntity"=> [
                [
                  "RegistrationName"=> [
                    [
                      "_"=> myinv_profile_get('company_name')
                    ]
                  ]
                ]
              ],
              "Contact"=> [
                [
                  "Telephone"=> [
                    [
                      "_"=> myinv_profile_get('company_phone')
                    ]
                  ],
                  "ElectronicMail"=> [
                    [
                      "_"=> myinv_profile_get('company_email')
                    ]
                  ]
                ]
              ]
            ]
          ]
        ]
      ],
      "AccountingCustomerParty"=> [
        [
          "Party"=> [
            [
              "PostalAddress"=> [
                [
                  "CityName"=> [
                    [
                      "_"=> $invoice->client->city
                    ]
                  ],
                  "PostalZone"=> [
                    [
                      "_"=> $invoice->client->zip
                    ]
                  ],
                  "CountrySubentityCode"=> [
                    [
                      "_"=> $invoice->client->state //Client State Code
                    ]
                  ],
                  "AddressLine"=> [
                    [
                      "Line"=> [
                        [
                          "_"=> $invoice->client->address
                        ]
                      ]
                    ],
                    [
                      "Line"=> [
                        [
                          "_"=> ""
                        ]
                      ]
                    ],
                    [
                      "Line"=> [
                        [
                          "_"=> ""
                        ]
                      ]
                    ]
                  ],
                  "Country"=> [
                    [
                      "IdentificationCode"=> [
                        [
                          "_"=> $identificationCode,
                          "listID"=> "ISO3166-1",
                          "listAgencyID"=> "6"
                        ]
                      ]
                    ]
                  ]
                ]
              ],
              "PartyLegalEntity"=> [
                [
                  "RegistrationName"=> [
                    [
                      "_"=> $registrationName
                    ]
                  ]
                ]
              ],
              "PartyIdentification"=> [
                [
                  "ID"=> [
                    [
                      "_"=> $tin,//BUYER'S TIN
                      "schemeID"=> "TIN"
                    ]
                  ]
                ],
                [
                  "ID"=> [
                    [
                      "_"=> $idNo,//Buyer's ID No
                      "schemeID"=> $idType //Buyer ID Type
                    ]
                  ]
                ],
                [
                  "ID"=> [
                    [
                      "_"=> isset($invoice->client->vat) && $invoice->client->vat !== '' 
              ? $invoice->client->vat : 'NA',
                      "schemeID"=> "SST"
                    ]
                  ]
                ],
                [
                  "ID"=> [
                    [
                      "_"=> "NA",
                      "schemeID"=> "TTX" //Tourism Tax (TTX) 
                    ]
                  ]
                ]
              ],
              "Contact"=> [
                [
                  "Telephone"=> [
                    [
                      "_"=> $invoice->client->phonenumber //BUYER Phone
                    ]
                  ],
                  "ElectronicMail"=> [
                    [
                      "_"=> $primary_email //Buyer Email(Nanti Tukar)
                    ]
                  ]
                ]
              ]
            ]
          ]
        ]
      ],
      "TaxTotal"=> [
        [
          "TaxAmount"=> [
            [
              "_"=> (float) $credit_note->total_tax,
              "currencyID"=> $customer_currency
            ]
          ],
          "TaxSubtotal"=> [
            [
              "TaxableAmount"=> [
                [
                  "_"=>  (float) $credit_note->total_tax,
                  "currencyID"=> $customer_currency
                ]
              ],
              "TaxAmount"=> [
                [
                  "_"=> (float) $credit_note->total_tax,
                  "currencyID"=> $customer_currency
                ]
              ],
              "TaxCategory"=> [
                [
                  "ID"=> [
                    [
                      "_"=> "02"
                    ]
                  ],
                  "TaxScheme"=> [
                    [
                      "ID"=> [
                        [
                          "_"=> "OTH",
                          "schemeID"=> "UN/ECE 5153",
                          "schemeAgencyID"=> "6"
                        ]
                      ]
                    ]
                  ]
                ]
              ]
            ]
          ]
        ]
      ],
      "LegalMonetaryTotal"=> [
        [
          "LineExtensionAmount"=> [
            [
              "_"=> (float) $credit_note->subtotal, //Total Payable Amount
              "currencyID"=> $customer_currency
            ]
          ],
          "TaxExclusiveAmount"=> [
            [
              "_"=> (float) $credit_note->subtotal,
              "currencyID"=> $customer_currency
            ]
          ],
          "TaxInclusiveAmount"=> [
            [
              "_"=> $subtotal + $totalTax,
              "currencyID"=> $customer_currency
            ]
          ],
          "AllowanceTotalAmount"=> [
            [
              "_"=> (float)"0.00",
              "currencyID"=> $customer_currency
            ]
          ],
          "ChargeTotalAmount"=> [
            [
              "_"=> $subtotal + $totalTax,
              "currencyID"=> $customer_currency
            ]
          ],
          "PayableRoundingAmount"=> [
            [
              "_"=> (float)"0.00",
              "currencyID"=> $customer_currency
            ]
          ],
          "PayableAmount"=> [
            [
              "_"=> $subtotal + $totalTax,
              "currencyID"=> $customer_currency
            ]
          ]
        ]
      ],
      "InvoiceLine"=> []
    ]
  ]
];

 foreach ($credit_note_items as $key => $item) {
$taxes  = get_credit_note_item_taxes($item->id);
$rateInt = (int) round((float) ($taxes[0]['taxrate'] ?? 0));
$base      = (float) $item->rate;          // e.g. 100.00
$ratePct   = (float) $rateInt;             // e.g. 8 for 8%
$taxAmount = $base * ($ratePct / 100);           

        $invoiceItem = [
             "ID"=> [
            [
              "_"=> "$key=>$item->id"
            ]
          ],
          "InvoicedQuantity"=> [
            [
              "_"=> (float) str_replace([',',' '], '', (string)$item->qty),
              "unitCode"=> "EA" //Unit of measurement
            ]
          ],
          "LineExtensionAmount"=> [
            [
              "_"=> (float) $credit_note->subtotal,
              "currencyID"=> $customer_currency
            ]
          ],
          "AllowanceCharge"=> [
            [
              "ChargeIndicator"=> [
                [
                  "_"=> false
                ]
              ],
              "AllowanceChargeReason"=> [
                [
                  "_"=> ""
                ]
              ],
              "MultiplierFactorNumeric"=> [
                [
                  "_"=> (float) "0.00"
                ]
              ],
              "Amount"=> [
                [
                  "_"=> (float) $item->rate,
                  "currencyID"=> $customer_currency
                ]
              ]
            ],
            [
              "ChargeIndicator"=> [
                [
                  "_"=> false
                ]
              ],
              "AllowanceChargeReason"=> [
                [
                  "_"=> ""
                ]
              ],
              "MultiplierFactorNumeric"=> [
                [
                  "_"=> 0.1
                ]
              ],
              "Amount"=> [
                [
                  "_"=> (float) 0.00,
                  "currencyID"=> $customer_currency
                ]
              ]
            ]
          ],
          "TaxTotal"=> [
            [
              "TaxAmount"=> [
                [
                  "_"=> $taxAmount, //TotalTaxAmount
                  "currencyID"=> $customer_currency
                ]
              ],
              "TaxSubtotal"=> [
                [
                  "TaxableAmount"=> [
                    [
                      "_"=> (float) $credit_note->total_tax, //TotalTaxAmount
                      "currencyID"=> $customer_currency
                    ]
                  ],
                  "TaxAmount"=> [
                    [
                      "_"=> (float) $credit_note->total_tax, //TotalTaxAmount
                      "currencyID"=> $customer_currency
                    ]
                  ],
                  "Percent"=> [
                    [
                      "_"=> 8
                    ]
                  ],
                  "TaxCategory"=> [
                    [
                      "ID"=> [
                        [
                          "_"=> "02" //https://sdk.myinvois.hasil.gov.my/codes/tax-types/
                        ]
                      ],
                      "TaxExemptionReason"=> [
                        [
                          "_"=> ""
                        ]
                      ],
                      "TaxScheme"=> [
                        [
                          "ID"=> [
                            [
                              "_"=> "OTH",
                              "schemeID"=> "UN/ECE 5153",
                              "schemeAgencyID"=> "6"
                            ]
                          ]
                        ]
                      ]
                    ]
                  ]
                ]
              ]
            ]
          ],
          "Item"=> [
            [
              "CommodityClassification"=> [
                [
                  "ItemClassificationCode"=> [
                    [
                      "_"=> "022", //Classification Codes
                      "listID"=> "CLASS"
                    ]
                  ]
                ]
              ],
              "Description"=> [
                [
                  "_"=> "$item->description"
                ]
              ],
              "OriginCountry"=> [
                [
                  "IdentificationCode"=> [
                    [
                      "_"=> "MYS"
                    ]
                  ]
                ]
              ]
            ]
          ],
          "Price"=> [
            [
              "PriceAmount"=> [
                [
                  "_"=> (float) $item->rate,
                  "currencyID"=> $customer_currency
                ]
              ]
            ]
          ],
          "ItemPriceExtension"=> [
            [
              "Amount"=> [
                [
                  "_"=> (float) $item->rate,
                  "currencyID"=> $customer_currency
                ]
              ]
            ]
          ]

        ];
         $document["Invoice"][0]["InvoiceLine"][] = $invoiceItem;
    }
  
 
        // Convert the document array to a JSON string
        $documentJson = json_encode($document);
        
   
        // Log the JSON for debugging
        log_message('info', 'Document JSON: ' . $documentJson);
    
        // Encode the JSON to Base64
        return base64_encode($documentJson);
    }





        private function appendBase64ToRequestBody($base64Document, $credit_note)
{
    $documents = [];

   
        // Decode the Base64 back to JSON string to calculate its hash
        $decodedDocument = base64_decode($base64Document);

        // Append each document to the documents array
        $documents[] = [
            'format' => 'JSON',
            'document' => $base64Document,
            'documentHash' => hash('sha256', $decodedDocument), // Correctly hash the JSON string
            'codeNumber' => $credit_note->id,
        ];
    

    // Return the complete request body with all documents
    return [
        'documents' => $documents
    ];
}






private function getSubmittedDocument($submissionUid, $token, $pageNo = 1, $pageSize = 10)
{
    // Load the custom cURL library for CodeIgniter 3
    $this->load->library('curl');
    $submitUrl = myinv_submit_url();

    // Build the URL with query parameters
    $url = $submitUrl . $submissionUid . "?pageNo=" . $pageNo . "&pageSize=" . $pageSize;
    log_message('info', 'Retrieving document submission details with URL: ' . $url);

    try {
        // Send GET request using the custom cURL library
        // The second parameter is for GET parameters (empty here)
        // The third parameter is an options array with headers
        $response = $this->curl->simple_get($url, [], [
            'headers' => [
                'Authorization: Bearer ' . $token,
                'Content-Type: application/json'
            ]
        ]);

        if (!$response) {
            log_message('error', 'No response received from API.');
            return null;
        }

        // Log the HTTP code if available
        $http_code = isset($response['http_code']) ? $response['http_code'] : 0;
        log_message('info', 'HTTP Code: ' . $http_code);

        // If the HTTP code is 200, decode the response
        if ($http_code == 200) {
            $responseData = json_decode($response['response'], true);
            log_message('info', 'Document Retrieval Response: ' . json_encode($responseData));
            return $responseData;
        } else {
            log_message('error', 'Failed to retrieve submission details. HTTP Status: ' . $http_code);
            return null;
        }
    } catch (Exception $e) {
        log_message('error', 'Error retrieving document details: ' . $e->getMessage());
        log_message('error', 'Exception trace: ' . $e->getTraceAsString());
        return null;
    }
}


//Get LongID
public function check_document_longID($tid)
{
    $invoice = $this->credit_notes_model->get($tid);
    if (!$invoice || empty($invoice->uuid)) {
        log_message('error', "check_document_status: missing UUID for invoice {$tid}");
        return false;
    }
    $uuid = $invoice->uuid;

    $tokenData = $this->getTokenFromLoginEndpoint();
    if (empty($tokenData['access_token'])) {
        log_message('error', "check_document_status: failed to get access token for invoice {$tid}");
        return false;
    }
    $accessToken = $tokenData['access_token'];

    $url = myinv_document_raw_url($uuid);
    $headers = [
        "Authorization: Bearer {$accessToken}",
        "Accept: application/json",
    ];
    $ch = curl_init($url);
    curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    $response = curl_exec($ch);
    $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    curl_close($ch);

    // allow both 200 OK and 202 Accepted
    if (! in_array($httpCode, [200, 202], true)) {
        log_message('error', "check_document_status: unexpected HTTP code {$httpCode} for invoice {$tid}");
        return false;
    }

    $data = json_decode($response, true);

    if (empty($data['longID'])) {
        log_message('error', "check_document_status: no longID in response for invoice {$tid} — response was: {$response}");
         log_activity('No longID in response for invoice: ' . $tid);
        return false;
    }

    $longID = $data['longID'];

    // persist it
    
    if (! $this->credit_notes_model->update_longID($tid, $longID)) {
        log_message('error', "check_document_status: failed to save longID '{$longID}' for Credit Note {$tid}");
        // but still return it
    }

    return $longID;
}



//Get Submission
public function check_document_status($tid) 
{
  
    $invoice = $this->credit_notes_model->get($tid);

    //var_dump($invoice);die;

    if (! $invoice || empty($invoice->uuid)) {
        show_error('Invoice not found or UUID missing.');
    }

    $uuid = $invoice->uuid;

    // Get token using your existing function
    $tokenData = $this->getTokenFromLoginEndpoint();

      if (empty($tokenData) || empty($tokenData['access_token'])) {
    show_error('Failed to retrieve access token.');
}
    $accessToken = $tokenData['access_token'];

    // API endpoint
    $url = myinv_document_raw_url($uuid);

    $headers = [
        "Authorization: Bearer $accessToken",
        "Accept: application/json"
    ];

    $ch = curl_init($url);
    curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

    $response = curl_exec($ch);
    $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    curl_close($ch);
    $longID = isset($data['longID']) ? $data['longID'] : null;
    //log_message('info', 'e-invois Document longID: ' . $longID);
    log_message('e-invois Document Statusx:' , $response);

    if ($httpCode == 200) {
        $data = json_decode($response, true);
        $longID = isset($data['longID']) ? $data['longID'] : null;

     //$this->load->model('Invoices_model'); // Ensure the model is loaded
    $updateResult = $this->credit_notes_model->update_longID(
        $tid,
        $longID
    );

    if (!$updateResult) {
        log_message('error', 'Failed to update invoice with submission data.');
    } else {
        log_message('info', 'Invoice updated with submission data successfully.');
    }


        if (!empty($data['uuid']) && !empty($data['longID'])) {
            $envBaseUrl = myinv_portal_base();
            $shareUrl = $envBaseUrl . $data['uuid'] . '/share/' . $data['longID'];

            // Redirect to the document share URL
            redirect($shareUrl, 'location', 302);
        } else {
            show_error('UUID or longID not found in response.');
        }

    } else {
        echo "Failed to retrieve document details. HTTP Status: $httpCode<br>";
        echo "<pre>$response</pre>";
    }
}



public function cancel_document($tid, $reason = null)
{
    // 1) Fetch invoice record and UUID
    $invoice = $this->credit_notes_model->get($tid);
    if (!$invoice || empty($invoice->uuid)) {
        show_error('Invoice not found or UUID missing.');
    }
    $uuid = $invoice->uuid;

    // 2) Get access token
    $tokenData = $this->getTokenFromLoginEndpoint();

   if (empty($tokenData) || empty($tokenData['access_token'])) {
    show_error('Failed to retrieve access token.');
}
    $accessToken = $tokenData['access_token'];

    // 3) Build the cancel‐state URL
    //    Note: in production you’d swap out "preprod-api" for "api"
    $url = myinv_document_state_url($uuid);

    // 4) Prepare your payload
    //    Make sure $reason is non‐empty and under 300 chars
    $payload = [
        'status' => 'cancelled',
        'reason' => $reason ?? 'Wrong invoice details'
    ];
    $jsonPayload = json_encode($payload, JSON_UNESCAPED_UNICODE);

    // 5) Send the PUT request via cURL
    $ch = curl_init($url);
    curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PUT');
    curl_setopt($ch, CURLOPT_POSTFIELDS, $jsonPayload);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_HTTPHEADER, [
        "Authorization: Bearer {$accessToken}",
        "Accept: application/json",
        "Content-Type: application/json",
        "Content-Length: " . strlen($jsonPayload)
    ]);

    $response   = curl_exec($ch);
    $httpCode   = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    $curlErr    = curl_error($ch);
    curl_close($ch);
    
     // log as before
    log_message('info', "MyInvois CANCEL response for TID#{$tid} — HTTP {$httpCode}: {$response}");
    if ($curlErr) {
        log_message('error', "cURL error during cancel for TID#{$tid}: {$curlErr}");
    }
    
      // 1) decode the JSON
    $respData = json_decode($response, true);

    // 2) load your model
    //$this->load->model('Invoices_model');

    // 3) determine new status (standardize to lowercase)
    $newStatus = !empty($respData['status'])
        ? strtolower($respData['status'])
        : 'cancelled';

    // 4) call model to update
    $updated = $this->credit_notes_model->einvoice_cancelled(
        $tid,
        $respData['uuid'] ?? null,
        $newStatus
    );
    
    

    if ($httpCode === 200 || $httpCode === 204) {
        $msg = "Invoice $tid successfully cancelled and Database " .
               ($updated ? "updated." : "update FAILED.");
        $status = 'success';
    } else {
      $msg = "Failed to cancel invoice. API HTTP Status: {$httpCode}.";
     $status = 'error';
    }
    
  

     set_alert( $status, $msg);
     redirect(admin_url('credit_notes/list_credit_notes/' . $tid));
  
}

}
