<?php
session_start();

//Error reporting
ini_set('display_errors', 0);
ini_set('log_errors', 1);
ini_set('error_log', dirname(__FILE__) . '/paypal_ipn_error_log.txt');
error_reporting(E_ALL);

//Includes
require_once dirname(__DIR__) . '/../config.php';
require_once DIRLIBCOMP . 'SPDO.php';
require_once DIRLIBCOMP . 'funciones.php';
require_once DIRLIBCOMP . 'registro_logs.php';
$conexion  = new SPDO(BDENGINE, BDHOST, BDDATABASE, BDUSER, BDPASS);
$conexion2 = new SPDO(BDENGINE, BDHOST, BDDATABASE, BDUSER, BDPASS);
/*******************************************************************
 * TRADUCCIONES
 *******************************************************************/
require_once DIRLIBCOMP . 'clases/lang.php';
$language = new lang();

/*****************************************************************
 * Mensajes del sistema
 *****************************************************************/
require_once DIRLIBCOMP . 'clases/messages.php';
$message = new messages();

Insertar_Sentencia("Entra en Paypal.ipn.php", 'compra');

//Inicio transacción
$conexion->beginTransaction();

file_put_contents(dirname(__FILE__) . '/Paypal_ipn.txt', var_export($_POST, true), FILE_APPEND);


if (strtolower($_POST['payment_status']) == 'completed') {

    $localizadores_alta = verificarLocalizador('localizadores', $_POST['invoice'], $_POST['mc_gross'] , $conexion);

    if ($localizadores_alta['extra'] == 1){
        $result['extra'] = $localizadores_alta['extra'];
    }

    if ($localizadores_alta['filas'] == 1) {
        // SI EL LOCALIZADOR EXISTE Y ES UNICO SE INTENTA ACTUALIZAR REDYSS LOCALIZADORES Y RESERVAS
        $result['estado']  = (paypal_update($_POST, $conexion) && loc_res_update($localizadores_alta['localizador'], $conexion));
        $result['literal'] = 'Correcto';
        logPaypal("Resultado de la recepción: " .  $result['literal']);
    } else {
        // SI EL LOCALIZADOR NO EXISTE O NO ES UNICO SE TRATA DE RECUPERAR
        logPaypal("Se ha recibido una confirmación de compra de un localizador no existente o duplicado\n");
        $localizadores_borrados = verificarLocalizador('localizadores_borrados', $_POST['invoice'], $_POST['mc_gross'], $conexion);
       
        if ($localizadores_borrados['extra'] == 1){
            $result['extra'] = $localizadores_borrados['extra'];            
        }

        if ($localizadores_borrados['filas'] == 0) {
            // SI EL LOCALIZADOR NO EXISTE EN BORRADOS SE PRODUCE ERROR
            $result['estado']  = false;
            $result['literal'] = 'No Existe en Borrados';
            logPaypal("ERROR: " . $result['literal']);
        } else {
            // SI EL LOCALIZADOR EXISTE EN BORRADOS SE TRATA DE INCLUIR EN EL PLANNING
            logPaypal("El localizador figura en el registro de borrados. Iniciamos recuperación.\n");
            if (calcularPlazas($localizadores_borrados['localizador'], $conexion)) {
                // SI SE PUEDE REINSERTAR SE RECUPERAN DE LOS BORRADOS
                $result['estado']  = recuperarBorrados($localizadores_borrados['localizador'], $_POST, $conexion);
                $result['literal'] =  "Correcto, recuperado de borrados: " . $localizadores_borrados['localizador'] . "\n";
                logPaypal("Resultado de la recepción: " . $result['literal']);
            } else {
                // SI NO ES POSIBLE REINSERTAR POR OVERBOKING SE PRODUCE ERROR
                $result['estado']  = false;
                $result['literal'] = "Error Overbooking \n";
                logPaypal("ERROR: " . $result['literal']);
            }
        }
    }

    if ($result['estado'] == true) {
        // SI EL RESULTADO ES CORRECTO SE HACE COMMIT Y SE INFORMA EL MAIL
        $conexion->commit();
        $datos_comercio = $_POST['invoice'];
        Insertar_Sentencia('intentamos mandar el correo', 'compra');

        if($result['extra'] == 1){          
            $sentencia = "LOCALIZADOR - " . $localizador . " - Envio de correo extra ";
            Insertar_Sentencia($sentencia, 'compra');
            require_once DIRMODULOSCOMP . 'compra/procesar_email_compra_extra.php';
        }else{
            require_once DIRMODULOSCOMP . 'compra/procesar_email_compra_paypal.php';
        }

        $sentencia = "LOCALIZADOR - " . $localizador . " - La reserva para el localizador ha cambiado de estado: finalizada ";
        Insertar_Sentencia($sentencia, 'compra');
        $sentencia = "LOCALIZADOR - " . $localizador . " - Cambio de estado: pagado";
        Insertar_Sentencia($sentencia, 'compra');
        logPaypal("EL PAGO SE HA REALIZADO");
    } else {
        // SI EL RESULTADO ES INCORRECTO SE HACE ROLLBACK
        $conexion->rollback();
        // ¿POSIBLE NUEVA FUNCIONALIDAD PARA ENVIAR MAIL DE ERROR?
        // require_once DIRMODULOSCOMP . 'compra/procesar_email_error_compra.php';
        $sentencia = "LOCALIZADOR - " . $localizador . " ERROR EN EL PROCESO: " . $errores[$result['literal']];
        Insertar_Sentencia($sentencia, 'compra');
        logPaypal("EL PAGO NO SE HA REALIZADO");
    }
} elseif ($_POST['payment_status'] == 'failed' || $_POST['payment_status'] == 'expired' || $_POST['payment_status'] == 'voided' || $_POST['payment_status'] == 'Refunded') {
    // El pago no se ha realizado
    $sentencia = "IDPEDIDO - " . $_POST['invoice'] . " - La reserva para el localizador no se ha pagado";
    Insertar_Sentencia($sentencia, 'compra');
    logPaypal("EL PAGO NO SE HA REALIZADO");
    devolver_stock($_POST['invoice'], $conexion2);
}

// Actualiza Paypal con un objeto facilitado en la conexión indicada.
function paypal_update($paypal, $conexion)
{
    $sql_tpv = "UPDATE Paypal
                    SET
                        protection_eligibility = :protection_eligibility,
                        payer_id               = :payer_id,
                        tax                    = :tax,
                        payment_date           = :payment_date,
                        payment_status         = :payment_status,
                        charset                = :charset,
                        first_name             = :first_name,
                        mc_fee                 = :mc_fee,
                        notify_version         = :notify_version,
                        custom                 = :custom,
                        payer_status           = :payer_status,
                        business               = :business,
                        quantity               = :quantity,
                        verify_sign            = :verify_sign,
                        payer_email            = :payer_email,
                        txn_id                 = :txn_id,
                        payment_type           = :payment_type,
                        last_name              = :last_name,
                        receiver_email         = :receiver_email,
                        payment_fee            = :payment_fee,
                        receiver_id            = :receiver_id,
                        txn_type               = :txn_type,
                        item_name              = :item_name,
                        mc_currency            = :mc_currency,
                        item_number            = :item_number,
                        residence_country      = :residence_country,
                        test_ipn               = :test_ipn,
                        handling_amount        = :handling_amount,
                        transaction_subject    = :transaction_subject,
                        payment_gross          = :payment_gross,
                        shipping               = :shipping,
                        ipn_track_id           = :ipn_track_id,
                        estado                 = :estado
                    WHERE invoice = :Num_operacion";

    $result_tpv = $conexion->prepare($sql_tpv);
    $exec_tpv   = $result_tpv->execute(array(
        ':protection_eligibility' => (isset($paypal['protection_eligibility']) ? $paypal['protection_eligibility'] : ""),
        ':payer_id'               => (isset($paypal['payer_id']) ? $paypal['payer_id'] : ""),
        ':tax'                    => (isset($paypal['tax']) ? $paypal['tax'] : ""),
        ':payment_date'           => (isset($paypal['payment_date']) ? $paypal['payment_date'] : ""),
        ':payment_status'         => (isset($paypal['payment_status']) ? $paypal['payment_status'] : ""),
        ':charset'                => (isset($paypal['charset']) ? $paypal['charset'] : ""),
        ':first_name'             => (isset($paypal['first_name']) ? $paypal['first_name'] : ""),
        ':mc_fee'                 => (isset($paypal['mc_fee']) ? $paypal['mc_fee'] : ""),
        ':notify_version'         => (isset($paypal['notify_version']) ? $paypal['notify_version'] : ""),
        ':custom'                 => (isset($paypal['custom']) ? $paypal['custom'] : ""),
        ':payer_status'           => (isset($paypal['payer_status']) ? $paypal['payer_status'] : ""),
        ':business'               => (isset($paypal['business']) ? $paypal['business'] : ""),
        ':quantity'               => (isset($paypal['num_cart_items']) ? $paypal['num_cart_items'] : ""),
        ':verify_sign'            => (isset($paypal['verify_sign']) ? $paypal['verify_sign'] : ""),
        ':payer_email'            => (isset($paypal['payer_email']) ? $paypal['payer_email'] : ""),
        ':txn_id'                 => (isset($paypal['txn_id']) ? $paypal['txn_id'] : ""),
        ':payment_type'           => (isset($paypal['payment_type']) ? $paypal['payment_type'] : ""),
        ':last_name'              => (isset($paypal['last_name']) ? $paypal['last_name'] : ""),
        ':receiver_email'         => (isset($paypal['receiver_email']) ? $paypal['receiver_email'] : ""),
        ':payment_fee'            => (isset($paypal['payment_fee']) ? $paypal['payment_fee'] : ""),
        ':receiver_id'            => (isset($paypal['receiver_id']) ? $paypal['receiver_id'] : ""),
        ':txn_type'               => (isset($paypal['txn_type']) ? $paypal['txn_type'] : ""),
        ':item_name'              => (isset($paypal['item_name']) ? $paypal['item_name'] : (isset($paypal['item_name1']) ? $paypal['item_name1'] : "")),
        ':mc_currency'            => (isset($paypal['mc_currency']) ? $paypal['mc_currency'] : ""),
        ':item_number'            => (isset($paypal['item_number']) ? $paypal['item_number'] : ""),
        ':residence_country'      => (isset($paypal['residence_country']) ? $paypal['residence_country'] : ""),
        ':test_ipn'               => (isset($paypal['test_ipn']) ? $paypal['test_ipn'] : ""),
        ':handling_amount'        => (isset($paypal['handling_amount']) ? $paypal['handling_amount'] : ""),
        ':transaction_subject'    => (isset($paypal['transaction_subject']) ? $paypal['transaction_subject'] : ""),
        ':payment_gross'          => (isset($paypal['payment_gross']) ? $paypal['payment_gross'] : ""),
        ':shipping'               => (isset($paypal['shipping']) ? $paypal['shipping'] : ""),
        ':ipn_track_id'           => (isset($paypal['ipn_track_id']) ? $paypal['ipn_track_id'] : ""),
        ':estado'                 => 'pagado',
        ':Num_operacion'          => $paypal['invoice'],
    ));
    logPaypal(var_export($exec_tpv, true));
    $sentencia = "IDPEDIDO - " . $_POST['invoice'] . " - Actualizacion tabla tpv:" . var_export($exec_tpv, true);
    Insertar_Sentencia($sentencia, 'compra');
    return $exec_tpv;
}

// Actualiza el estado de localizadoresa pagado y reservas a finalizada en la conexión indicada.
function loc_res_update($localizador, $conexion)
{
    $update_loc = " UPDATE localizadores
                    SET estado = 'pagado'
                    WHERE localizador = ?";
    $result_localizador = $conexion->prepare($update_loc);
    $exec_loc           = $result_localizador->execute(array($localizador));
    $sentencia          = "LOCALIZADOR - " . $localizador . " - Actualizacion tabla localizadores:" . var_export($exec_loc, true);
    $update_res         = " UPDATE reservas
                            SET estado = 'finalizada'
                            WHERE localizador = ?";
    $result_reserva = $conexion->prepare($update_res);
    $exec_res       = $result_reserva->execute(array($localizador));
    $sentencia      = "LOCALIZADOR - " . $localizador . " - Actualizacion tabla reservas:" . var_export($exec_res, true);
    Insertar_Sentencia($sentencia, 'compra');

    
    $update_ext = " UPDATE localizador_extras_servicio
    SET estado = 'pagado'
    WHERE localizador_extra = ?";
    $result_ext = $conexion->prepare($update_ext);
    $exec_res       = $result_ext->execute(array($localizador));
    $sentencia      = "LOCALIZADOR - " . $localizador . " - Actualizacion tabla extras:" . var_export($exec_res, true);
    Insertar_Sentencia($sentencia, 'compra');
    
    return $exec_loc && $exec_res;
}

// Recibe el nombre de una tabla, el filtro de búsqueda y los datos de conexión a BBDD
// Devuelve un array con el número de filas de la query correspondiente al join de Paypal y la tabla remitida filtrando por MerchantData
// y en caso de existir resultados el primer localizador.
function verificarLocalizador($tabla, $filtro, $total, $conexion)
{
    $sql_localizador = "SELECT localizador.localizador as loc , localizador.total as total ,localizador.extra as extra
                        FROM " . $tabla . " localizador JOIN Paypal tpv ON localizador.localizador = tpv.localizador
                        AND tpv.invoice = :pedido ";
    $result_localizador = $conexion->prepare($sql_localizador);   
    $exec_localizador   = $result_localizador->execute(array(
        ':pedido' => $filtro)); 

    $result['extra'] = false;
    $result['filas'] = $result_localizador->rowCount();
    if ($result['filas'] > 0) {
        $row = $result_localizador->fetch(PDO::FETCH_ASSOC);

        // Las comparativas con campos de tipo float dan problemas
        $desviacion = 0.01;
        if(abs($row['total'] - $total) < $desviacion ){
            $sentencia = "LOCALIZADOR encontrado con estos parametros - Id_pedido:" . $filtro . " - Precio pasado: " .$total  . " Tabla: " . $tabla ;
            $result['localizador'] = $result['filas'] > 0 ? $row['loc'] : '';

            if($row['extra'] ==1 ){                      
                $result['extra'] = true;
                $update_localizador = " UPDATE localizadores
                            SET tiene_extras = 1
                            WHERE localizador = ?";
                $result_localizador = $conexion->prepare($update_localizador);
                $exec_localizador   = $result_localizador->execute(array($result['localizador_extra']));
                $sentencia          = "LOCALIZADOR - " . $result['localizador_extra'] . " tiene extras 1:" . var_export($exec_localizador, true);
                Insertar_Sentencia($sentencia, 'compra');
            }
        }else{
            $sentencia = "Incidencia comprobacion precios - Id_pedido:" . $filtro . " - Precio pasado: " .$total  . " Tabla: " . $tabla . ". Precio bbdd: " .$row['total'] ;
            $result['localizador'] ='';
        }
        Insertar_Sentencia($sentencia, 'compra');
        return $result;
    }else{
        $sentencia = "LOCALIZADOR no encontrado con estos parametros - Id_pedido:" . $filtro . " - Precio pasado: " .$total  . " Tabla: " . $tabla ;
        Insertar_Sentencia($sentencia, 'compra');

        $result['localizador'] = '';
        return $result;
    }


}

// Recibe un localizador y una conexión de BBDD
// Devuelve si el número de plazas de una reserva borrada asociada a ese localizador es menor o igual a las plazas libres de su horario asociado.
function calcularPlazas($localizador, $conexion)
{
    $sql_calculo = " SELECT  sala_horarios.plazas_libres - reservas_borradas.unidades as total
                     FROM sala_horarios
                     JOIN reservas_borradas ON sala_horarios.id=reservas_borradas.sala_horario_id
                     JOIN localizadores_borrados ON localizadores_borrados.localizador=reservas_borradas.localizador
                     WHERE localizadores_borrados.localizador= ?";
    $result_calculo = $conexion->prepare($sql_calculo);
    $result_calculo->execute(array($localizador));
    $row = $result_calculo->fetch(PDO::FETCH_ASSOC);
    return $row['total'] >= 0;
}

// Borra de las tablas localizadores_borrados y reservas_borradas (Se dispara trigger de BBDD que los inserta en localizadores y reservas respectivamente)
// Verifica que el localizador es único y actualiza las plazas.
function recuperarBorrados($localizador, $paypal, $conexion)
{
    $delete_reservas      = "DELETE FROM reservas_borradas WHERE localizador = ?";
    $result_delres        = $conexion->prepare($delete_reservas);
    $result               = $result_delres->execute(array($localizador));
    $delete_localizadores = "DELETE FROM localizadores_borrados WHERE localizador = ?";
    $result_delloc        = $conexion->prepare($delete_localizadores);
    $result               = $result && $result_delloc->execute(array($localizador));
    $update_plazas        = "   UPDATE reservas rv
                                JOIN sala_horarios sh on rv.sala_horario_id=sh.id
                                JOIN salas sl on sl.id=sh.sala_id
                                JOIN localizadores loc on loc.localizador=rv.localizador
                                JOIN servicios sv on loc.servicio_id=sv.id
                                SET sh.plazas_libres = sh.plazas_libres - (CASE WHEN sv.horario_completo = 1 THEN sl.plazas ELSE rv.unidades END)
                                WHERE rv.localizador=?";
    $result_update      = $conexion->prepare($update_plazas);
    $result             = $result_update->execute(array($localizador));
    $localizadores_alta = verificarLocalizador('localizadores', $paypal['invoice'], $_POST['mc_gross'], $conexion);
    if ($result == true && $localizadores_alta['filas'] == 1) {
        $result = paypal_update($paypal, $conexion) && loc_res_update($localizador, $conexion);
    }
    return $result;
}

// Agrega al log de Paypal el literal facilitado, precedido de la hora actual
function logPaypal($texto)
{
    file_put_contents(dirname(__FILE__) . '/Paypal_ipn.txt', "[" . date("Y-m-d H:i:s") . "] " . $texto, FILE_APPEND);
}
