<?php

/**
 * @file
 * Credit administration menu items.
 */

/**
 * Displays the credit card terminal page.
 */
function uc_credit_terminal($order) {
  $output = l(t('Return to order view screen.'), 'admin/store/orders/'. $order->order_id);

  $output .= '<p>'. t('Use this terminal to process credit card payments through your default gateway.') .'</p>';

  if (!variable_get('uc_credit_debug', FALSE) || variable_get('uc_credit_checkout_process', TRUE)) {
    $output .= '<p>'. t('Be warned that credit card data will automatically be converted to the last 4 digits of the card once a transaction has occurred.  As such, subsequent charges after a partial payment will not have any stored credit card information to use.') .'</p>';
  }

  $context = array(
    'revision' => 'formatted-original',
    'type' => 'order_total',
    'subject' => array(
      'order' => $order,
    ),
  );
  $output .= '<div><strong>'. t('Order total: @total', array('@total' => uc_price($order->order_total, $context))) .'</strong></div>'
            .'<div><strong>'. t('Balance: @balance', array('@balance' => uc_price(uc_payment_balance($order), $context))) .'</strong></div>';

  $output .= drupal_get_form('uc_credit_terminal_form', $order);

  return $output;
}

/**
 * Displays the credit card terminal form for administrators.
 *
 * @see uc_credit_terminal_form_validate()
 * @see uc_credit_terminal_form_submit()
 */
function uc_credit_terminal_form($form_state, $order, $lock_amount = FALSE) {
  // Get the transaction types available to our default gateway.
  $types = uc_credit_gateway_txn_types(uc_credit_default_gateway());

  // Put the order ID in the form.
  $form['order_id'] = array(
    '#type' => 'hidden',
    '#value' => $order->order_id,
  );

  $balance = uc_payment_balance($order);

  $context = array(
    'revision' => 'formatted-original',
    'type' => 'amount',
  );
  $options = array(
    'sign' => FALSE,
    'thou' => FALSE,
    'dec' => '.',
  );

  // Let the administrator set the amount to charge.
  $form['amount'] = array(
    '#type' => 'textfield',
    '#title' => t('Charge Amount'),
    '#default_value' => $balance > 0 ? uc_price($balance, $context, $options) : 0,
    '#size' => 10,
    '#disabled' => $lock_amount,
    '#field_prefix' => variable_get('uc_sign_after_amount', FALSE) ? '' : variable_get('uc_currency_sign', '$'),
    '#field_suffix' => variable_get('uc_sign_after_amount', FALSE) ? variable_get('uc_currency_sign', '$') : '',
  );

  // Build a credit card form.
  $form['specify_card'] = array(
    '#type' => 'fieldset',
    '#title' => t('Credit card details'),
    '#description' => t('Use the available buttons in this fieldset to process with the specified card details.'),
  );
  $form['specify_card']['cc_data'] = array(
    '#theme' => 'uc_payment_method_credit_form',
    '#tree' => TRUE,
  );
  $form['specify_card']['cc_data'] += uc_payment_method_credit_form(array(), $order);
  unset($form['specify_card']['cc_data']['cc_policy']);

  // If available, let the card be charged now.
  if (in_array(UC_CREDIT_AUTH_CAPTURE, $types)) {
    $form['specify_card']['charge_card'] = array(
      '#type' => 'submit',
      '#value' => t('Charge amount'),
    );
  }

  // If available, let the amount be authorized.
  if (in_array(UC_CREDIT_AUTH_ONLY, $types)) {
    $form['specify_card']['authorize_card'] = array(
      '#type' => 'submit',
      '#value' => t('Authorize amount only'),
    );
  }

  // If available, create a reference at the gateway.
  if (in_array(UC_CREDIT_REFERENCE_SET, $types)) {
    $form['specify_card']['reference_set'] = array(
      '#type' => 'submit',
      '#value' => t('Set a reference only'),
    );
  }

  // If available, create a reference at the gateway.
  if (in_array(UC_CREDIT_CREDIT, $types)) {
    $form['specify_card']['credit_card'] = array(
      '#type' => 'submit',
      '#value' => t('Credit amount to this card'),
    );
  }

  // Find any uncaptured authorizations.
  $options = array();

  foreach ((array) $order->data['cc_txns']['authorizations'] as $auth_id => $data) {
    if (empty($data['captured'])) {
      $options[$auth_id] = t('@auth_id - @date - @amount authorized', array('@auth_id' => strtoupper($auth_id), '@date' => format_date($data['authorized'], 'small'), '@amount' => uc_price($data['amount'], $context)));
    }
  }

  // If any authorizations existed...
  if (!empty($options)) {
    // Display a fieldset with the authorizations and available action buttons.
    $form['authorizations'] = array(
      '#type' => 'fieldset',
      '#title' => t('Prior authorizations'),
      '#description' => t('Use the available buttons in this fieldset to select and act on a prior authorization. The charge amount specified above will be captured against the authorization listed below.  Only one capture is possible per authorization, and a capture for more than the amount of the authorization may result in additional fees to you.'),
    );

    $form['authorizations']['select_auth'] = array(
      '#type' => 'radios',
      '#title' => t('Select authorization'),
      '#options' => $options,
    );

    // If available, capture a prior authorization.
    if (in_array(UC_CREDIT_PRIOR_AUTH_CAPTURE, $types)) {
      $form['authorizations']['auth_capture'] = array(
        '#type' => 'submit',
        '#value' => t('Capture amount to this authorization'),
      );
    }

    // If available, void a prior authorization.
    if (in_array(UC_CREDIT_VOID, $types)) {
      $form['authorizations']['auth_void'] = array(
        '#type' => 'submit',
        '#value' => t('Void authorization'),
      );
    }

    // Collapse this fieldset if no actions are available.
    if (!isset($form['authorizations']['auth_capture']) && !isset($form['authorizations']['auth_void'])) {
      $form['authorizations']['#collapsible'] = TRUE;
      $form['authorizations']['#collapsed'] = TRUE;
    }
  }

  // Find any uncaptured authorizations.
  $options = array();

  // Log a reference to the order for testing.
  // $order->data = uc_credit_log_reference($order->order_id, substr(md5(time()), 0, 16), '4111111111111111');

  foreach ((array) $order->data['cc_txns']['references'] as $ref_id => $data) {
    $options[$ref_id] = t('@ref_id - @date - (Last 4) @card', array('@ref_id' => strtoupper($ref_id), '@date' => format_date($data['created'], 'small'), '@card' => $data['card']));
  }

  // If any references existed...
  if (!empty($options)) {
    // Display a fieldset with the authorizations and available action buttons.
    $form['references'] = array(
      '#type' => 'fieldset',
      '#title' => t('Customer references'),
      '#description' => t('Use the available buttons in this fieldset to select and act on a customer reference.'),
    );

    $form['references']['select_ref'] = array(
      '#type' => 'radios',
      '#title' => t('Select references'),
      '#options' => $options,
    );

    // If available, capture a prior references.
    if (in_array(UC_CREDIT_REFERENCE_TXN, $types)) {
      $form['references']['ref_capture'] = array(
        '#type' => 'submit',
        '#value' => t('Charge amount to this reference'),
      );
    }

    // If available, remove a previously stored reference.
    if (in_array(UC_CREDIT_REFERENCE_REMOVE, $types)) {
      $form['references']['ref_remove'] = array(
        '#type' => 'submit',
        '#value' => t('Remove reference'),
      );
    }

    // If available, remove a previously stored reference.
    if (in_array(UC_CREDIT_REFERENCE_CREDIT, $types)) {
      $form['references']['ref_credit'] = array(
        '#type' => 'submit',
        '#value' => t('Credit amount to this reference'),
      );
    }

    // Collapse this fieldset if no actions are available.
    if (!isset($form['references']['ref_capture']) && !isset($form['references']['ref_remove']) && !isset($form['references']['ref_credit'])) {
      $form['references']['#collapsible'] = TRUE;
      $form['references']['#collapsed'] = TRUE;
    }
  }

  return $form;
}

/**
 * Validation handler for credit terminal form.
 *
 * @see uc_credit_terminal_form()
 * @see uc_credit_terminal_form_submit()
 */
function uc_credit_terminal_form_validate($form, &$form_state) {
  switch ($form_state['values']['op']) {
    case t('Charge amount'):
    case t('Authorize amount only'):
    case t('Capture amount to this authorization'):
    case t('Charge amount to this reference'):
      if (!is_numeric($form_state['values']['amount']) || $form_state['values']['amount'] <= 0) {
        form_set_error('amount', t('You must enter a positive number for the amount.'));
      }
  }

  if (uc_order_load($form_state['values']['order_id']) === FALSE) {
    form_set_error('', t('Invalid order ID.  Unable to process payment.'));
  }
}

/**
 * Submit handler for credit terminal form.
 *
 * @see uc_credit_terminal_form()
 * @see uc_credit_terminal_form_validate()
 */
function uc_credit_terminal_form_submit($form, &$form_state) {
  // Load the order.
  $order = uc_order_load($form_state['values']['order_id']);

  // Get the data from the form and replace masked data from the order.
  $cc_data = $form_state['values']['cc_data'];

  if (strpos($cc_data['cc_number'], t('(Last 4) ')) === 0) {
    $cc_data['cc_number'] = $order->payment_details['cc_number'];
  }

  if ($cc_data['cc_cvv'] == str_repeat('-', strlen($cc_data['cc_cvv']))) {
    $cc_data['cc_cvv'] = $order->payment_details['cc_cvv'];
  }

  // Cache the values for use during processing.
  uc_credit_cache('save', $cc_data, FALSE);

  // Build the data array passed on to the payment gateway.
  $data = array();

  switch ($form_state['values']['op']) {
    case t('Charge amount'):
      $data['txn_type'] = UC_CREDIT_AUTH_CAPTURE;
      break;

    case t('Authorize amount only'):
      $data['txn_type'] = UC_CREDIT_AUTH_ONLY;
      break;

    case t('Set a reference only'):
      $data['txn_type'] = UC_CREDIT_REFERENCE_SET;
      break;

    case t('Credit amount to this card'):
      $data['txn_type'] = UC_CREDIT_CREDIT;
      break;

    case t('Capture amount to this authorization'):
      $data['txn_type'] = UC_CREDIT_PRIOR_AUTH_CAPTURE;
      $data['auth_id'] = $form_state['values']['select_auth'];
      break;

    case t('Void authorization'):
      $data['txn_type'] = UC_CREDIT_VOID;
      $data['auth_id'] = $form_state['values']['select_auth'];
      break;

    case t('Charge amount to this reference'):
      $data['txn_type'] = UC_CREDIT_REFERENCE_TXN;
      $data['ref_id'] = $form_state['values']['select_ref'];
      break;

    case t('Remove reference'):
      $data['txn_type'] = UC_CREDIT_REFERENCE_REMOVE;
      $data['ref_id'] = $form_state['values']['select_ref'];
      break;

    case t('Credit amount to this reference'):
      $data['txn_type'] = UC_CREDIT_REFERENCE_CREDIT;
      $data['ref_id'] = $form_state['values']['select_ref'];
  }

  $result = uc_payment_process('credit', $form_state['values']['order_id'], $form_state['values']['amount'], $data, TRUE, NULL, FALSE);

  if ($result) {
    $crypt = new uc_encryption_class();

    // Load up the existing data array.
    $data = db_result(db_query("SELECT data FROM {uc_orders} WHERE order_id = %d", $form_state['values']['order_id']));
    $data = unserialize($data);

    $cache = uc_credit_cache('load');

    if (variable_get('uc_credit_debug', FALSE) && !variable_get('uc_credit_checkout_process', TRUE)) {
      $cc_data = $cache;
    }
    else {
      $cc_data = array(
        'cc_number' => substr($cache['cc_number'], -4),
      );
    }

    // Stuff the serialized and encrypted CC details into the array.
    $data['cc_data'] = $crypt->encrypt(uc_credit_encryption_key(), base64_encode(serialize($cc_data)));
    uc_store_encryption_errors($crypt, 'uc_credit');

    // Save it again.
    db_query("UPDATE {uc_orders} SET data = '%s' WHERE order_id = %d", serialize($data), $form_state['values']['order_id']);

    drupal_set_message(t('The credit card was processed successfully. See the admin comments for more details.'));
  }
  else {
    if (variable_get('uc_credit_debug', FALSE)) {
      _save_cc_data_to_order(uc_credit_cache('load'), $form_state['values']['order_id']);
    }

    drupal_set_message(t('There was an error processing the credit card.  See the admin comments for details.'), 'error');
  }

  $form_state['redirect'] = 'admin/store/orders/'. $form_state['values']['order_id'];
}
