<?php

namespace Services;

require_once __DIR__ . '/../vendor/autoload.php';
require_once __DIR__ . '/../Controllers/DonationController.php';
require_once __DIR__ . '/../Services/MailerService.php';
require_once __DIR__ . '/../PHPToolkit/NetSuiteService.php';
require_once $_SERVER['DOCUMENT_ROOT'] . '/tools.php';
require_once $_SERVER['DOCUMENT_ROOT'] . '/models/InvoiceHelper.php';
require_once $_SERVER['DOCUMENT_ROOT'] . '/models/VendorBillHelper.php';
require_once $_SERVER['DOCUMENT_ROOT'] . '/models/VendorPaymentHelper.php';
require_once $_SERVER['DOCUMENT_ROOT'] . '/netsuite/seach.php';
require_once $_SERVER['DOCUMENT_ROOT'] . '/netsuite/crud.php';




use Dotenv\Dotenv;
use Controllers\DonationController;
use Models\InvoiceHelper;
use Models\VendorBillHelper;
use Models\VendorPaymentHelper;
use Services\MailerService;
use Exception;
use DateTime;
use IntlDateFormatter;
use Stripe\StripeClient;

class NSService
{
    private $donationController;
    private $stripe;
    private $date;
    private $usoCfdiList;
    private $regimenList;
    private $url_base;

    public function __construct()
    {
        $this->initializeEnvironment();
        $this->initializeServices();
        $this->initializeCfdiLists();
    }

    private function initializeEnvironment()
    {
        $dotenv = Dotenv::createImmutable(__DIR__ . '/../');
        $dotenv->load();
        $this->url_base = "https://auna.nationbuilder.com";
    }

    private function initializeServices()
    {
        $this->donationController = new DonationController();
        $this->stripe = new StripeClient($_ENV['STRIPE_SECRET_KEY']);
        $this->date = date('Y/m/d H:i:s');
    }

    private function initializeCfdiLists()
    {
        $this->usoCfdiList = [
            -1 => "- Nuevo -",
            25 => "CN01 - Nómina",
            24 => "CP01 - Pagos",
            12 => "D01 - Honorarios Médicos, Dentales y Gastos Hospitalarios",
            13 => "D02 - Gastos Médicos por Incapacidad o Discapacidad",
            14 => "D03 - Gastos Funerales",
            15 => "D04 - Donativos (no aplica para membresía)",
            16 => "D05 - Intereses Reales Efectivamente Pagados por Créditos Hipotecarios (Casa Habitación)",
            17 => "D06 - Aportaciones Voluntarias al SAR",
            18 => "D07 - Primas por Seguros de Gastos Médicos",
            19 => "D08 - Gastos de Transportación Escolar Obligatoria",
            20 => "D09 - Depósitos en Cuentas para el Ahorro, Primas que Tengan como Base Planes de Pensiones",
            21 => "D10 - Pagos por Servicios Educativos (Colegiaturas)",
            1 => "G01 - Adquisición de Mercancías",
            2 => "G02 - Devoluciones, Descuentos o Bonificaciones",
            3 => "G03 - Gastos en General",
            4 => "I01 - Construcciones",
            5 => "I02 - Mobiliario y Equipo de Oficina por Inversiones",
            6 => "I03 - Equipo de Transporte",
            7 => "I04 - Equipo de Cómputo y Accesorios",
            8 => "I05 - Dados, Troqueles, Moldes, Matrices y Herramental",
            9 => "I06 - Comunicaciones Telefónicas",
            10 => "I07 - Comunicaciones Satelitales",
            11 => "I08 - Otra Maquinaria y Equipo",
            22 => "P01 - Por Definir",
            23 => "S01 - Sin efectos fiscales"
        ];

        $this->regimenList = [
            1 => "601 - General de Ley Personas Morales",
            2 => "603 - Personas Morales con Fines no Lucrativos",
            11 => "605 - Sueldos y Salarios e Ingresos Asimilados a Salarios",
            12 => "606 - Arrendamiento",
            10 => "607 - Régimen de Enajenación o Adquisición de Bienes",
            13 => "608 - Demás ingresos",
            4 => "610 - Residentes en el Extranjero sin Establecimiento Permanente en México",
            14 => "611 - Ingresos por Dividendos (socios y accionistas)",
            15 => "612 - Personas Físicas con Actividades Empresariales y Profesionales",
            16 => "614 - Ingresos por intereses",
            19 => "615 - Régimen de los ingresos por obtención de premios",
            17 => "616 - Sin obligaciones fiscales",
            5 => "620 - Sociedades Cooperativas de Producción que Optan por Diferir sus Ingresos",
            18 => "621 - Incorporación Fiscal",
            6 => "622 - Actividades Agrícolas, Ganaderas, Silvícolas Y Pesqueras",
            7 => "623 - Opcional para Grupos de Sociedades",
            8 => "624 - Coordinados",
            22 => "625 - Régimen de las Actividades Empresariales con ingresos a través de Plataformas Tecnológicas",
            23 => "626 - Régimen Simplificado de Confianza"
        ];
    }

    public function processSession($session)
    {
        try {
            $metadata = $session->metadata;
            $donationData = $this->extractDonationData($metadata);
            $this->donationController->createDonation($donationData);

            $customerInfo = $this->donationController->getLastDonation();
            $foundCustomer = $this->findCustomer($customerInfo, $metadata->isTest);

            if ($foundCustomer) {
                $customerInfo['customer'] = $foundCustomer[0];
            } else {
                $customerInfo = $this->prepareNewCustomerInfo($customerInfo, $metadata->isTest);
                $foundCustomerId = createCustomer($customerInfo);
                $customerInfo['customer'] = new Customer();
                $customerInfo['customer']->internalId = $foundCustomerId;
            }

            $invoiceData = $this->prepareInvoiceData($customerInfo, $metadata);
            $invoiceId = generateInvoice($invoiceData);
            $this->donationController->updateDonation($invoiceId, $customerInfo['id']);

            try{
                $isMembership = $metadata->isMembership ?? 0;
                if($isMembership){
                    $this->sendMembershipEmail($customerInfo);
                }else{
                    $this->sendUniqueDonationEmail($customerInfo);
                }
                
            }catch(Exception $e){
                error_log("Error al enviar correo electrónico: " . $e->getMessage());
            }

            $this->processNationBuilderTags($metadata, $invoiceId, $donationData, $customerInfo);

            $this->processStripePayment($session, $customerInfo['id'], $invoiceData);

        } catch (Exception $e) {
            error_log("Error al procesar sesión en NetSuite: " . $e->getMessage());
        }
    }

    private function extractDonationData($metadata)
    {
        return [
            'firstName' => $metadata->firstName,
            'lastName' => $metadata->lastName,
            'amount' => $metadata->amount,
            'email' => $metadata->email,
            'phone' => $metadata->phone,
            'country' => $metadata->country,
            'address' => $metadata->address,
            'address2' => $metadata->address2,
            'zip' => $metadata->zip,
            'rfc' => $metadata->rfc,
            'city' => $metadata->city,
            'state' => $metadata->state,
            'taxAddress' => $metadata->taxAddress ?? "",
            'taxRegime' => $metadata->taxRegime,
            'cfdiUsage' => $metadata->cfdiUse,
            'satName' => $metadata->satName,
        ];
    }

    private function findCustomer($customerInfo, $isTest)
    {
        if (!empty($customerInfo['rfc']) && !$isTest && $customerInfo['rfc'] !== $_ENV['GENERIC_RFC']) {
            return searchByRFC($customerInfo['rfc']);
        } elseif (!empty($customerInfo['email'])) {
            return searchByEmail($customerInfo['email']);
        }
        return null;
    }

    private function prepareNewCustomerInfo($customerInfo, $isTest)
    {
        if ($isTest) {
            return array_merge($customerInfo, [
                'satName' => 'JIMENEZ ESTRADA SALAS A A',
                'rfc' => 'JES900109Q90',
                'satIndustry' => '15',
                'zip' => '01030',
            ]);
        } else {
            $customerInfo['satIndustry'] = array_search($customerInfo['taxRegime'], $this->regimenList) ?: '15';
        }
        return $customerInfo;
    }

    private function prepareInvoiceData($customerInfo, $metadata)
    {
        $cfdiUsage = array_search($customerInfo['cfdiUsage'], $this->usoCfdiList) ?: 3;
        //$locationId = $this->getLocationId($customerInfo['state'], $metadata->capitulo ?? null);
        $locationId = $this->getLocationId($customerInfo['state']);
        error_log(print_r('locationId: '.$locationId, TRUE));
        //error_log(print_r('cCapítulo: '.$metadata->capitulo));
        error_log(print_r('state: '.$customerInfo['state']));
        

        $invoiceData = new InvoiceHelper();
        $invoiceData->customerId = $customerInfo['customer']->internalId;
        $invoiceData->departmentId = $metadata->departmentMembresia ?? $_ENV['DEPARTMENT'];
        $invoiceData->accountId = $_ENV['ACCOUNT_ID'];
        $invoiceData->classId = $metadata->classMembresia ?? $_ENV['CLASS'];
        $invoiceData->termsId = 1;
        $invoiceData->itemId = $metadata->itemMembresia ?? $_ENV['ITEM'];
        $invoiceData->amount = $customerInfo['amount'];
        $invoiceData->cfdiUsageId = $cfdiUsage;
        $invoiceData->subsidiary = $_ENV['SUBSIDIARY'];
        $invoiceData->custbody_psg_ei_template = $_ENV['TEMPLATE_PSG_EI'];
        $invoiceData->locationId = $locationId;

        return $invoiceData;
    }

    private function getLocationId($state)
    {
        $customerState = mb_strtoupper($state, 'UTF-8');

        /*if ($capitulo) {
            return $capitulo;
        }*/

        switch ($customerState) {
            case 'CDMX':
            case 'CIUDAD DE MÉXICO':
            case 'CIUDAD DE MEXICO':
                return $_ENV['LOCATION_CDMX'];
            case 'OAXACA':
                return $_ENV['LOCATION_OAX'];
            case 'JALISCO':
                return $_ENV['LOCATION_JAL'];
            case 'GUERRERO':
            case 'GRO':
                return $_ENV['LOCATION_GRO'];
            case 'NUEVO LEÓN':
            case 'NUEVO LEON':
                return $_ENV['LOCATION_NVOL'];
            default:
                return $_ENV['LOCATION_NACIONAL'];
        }
    }

    private function processNationBuilderTags($metadata, $invoiceId, $donationData, $customerInfo)
    {
        $urlBuscar = $this->url_base . '/api/v1/people/push' . '?access_token=' . $_ENV['TOKEN_NB'];

        error_log(print_r('donationData: '.json_encode($donationData), TRUE));
        error_log($urlBuscar);
        $dataPerson = [
            'person' => [
                'email' => $donationData['email'],
                'first_name' => $donationData['firstName'],
                'last_name' => $donationData['lastName'],
                'phone' => $donationData['phone'],
                'billing_address' => [
                    'address1' => $donationData['address'],
                    'address2' => $donationData['address2'],
                    'city' => $donationData['city'],
                    'state' => $donationData['state'],
                    'country_code' => $donationData['country'],
                    'zip' => $donationData['zip']
                ]
            ]
        ];

        $personJson = json_encode($dataPerson);

        $ch = curl_init($urlBuscar);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $personJson);
        curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "PUT");
        curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);   // Desactivar la verificación SSL


        $resultado = curl_exec($ch);

        if ($resultado === false) {
            error_log("[{$this->date}] Error al ejecutar la solicitud: " . curl_error($ch));
        } else {
            $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);

            if ($httpCode == 200 || $httpCode == 201) {
                $respuesta = json_decode($resultado, true);
                if (isset($respuesta['person']['id'])) {
                    $idPerson = $respuesta['person']['id'];
                    error_log("id person encontrado: " . $idPerson);
                    $this->assignTagsToPerson($idPerson, $metadata->isMembership ?? 0);
                }
            } else {
                error_log("[{$this->date}] Error en la solicitud. Código de respuesta HTTP: " . $httpCode);
            }
        }
        curl_close($ch);
    }

    private function assignTagsToPerson($idPerson, $isMembership)
    {
        $tagsToAssign = ["MembresiaNueva24"];
        $tagMembresia = "Capítulo_CDMX";

        if ($isMembership) {
            array_push($tagsToAssign, $tagMembresia);
        }

        foreach ($tagsToAssign as $tag) {
            $urlTags = $this->url_base . "/api/v1/people/{$idPerson}/taggings" . '?access_token=' . $_ENV['TOKEN_NB'];
            $tagData = ['tagging' => ['tag' => $tag]];
            $tagJson = json_encode($tagData);

            $ch = curl_init($urlTags);
            curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "PUT");
            curl_setopt($ch, CURLOPT_POSTFIELDS, $tagJson);
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
            curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']);
            curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);   // Desactivar la verificación SSL


            $resultado = curl_exec($ch);

            if ($resultado === false) {
                error_log("[{$this->date}] Error al ejecutar la solicitud: " . curl_error($ch));
            } else {
                $codigoRespuesta = curl_getinfo($ch, CURLINFO_HTTP_CODE);
                error_log("Código de Respuesta: " . $codigoRespuesta);
            }

            curl_close($ch);
        }
    }
    private function processStripePayment($session, $donationId, $invoiceData)
    {
        try {
            $paymentIntent = $this->stripe->paymentIntents->retrieve($session->payment_intent);
            $balanceTransactionId = $paymentIntent->charges->data[0]->balance_transaction;
            $balanceTransaction = \Stripe\BalanceTransaction::retrieve($balanceTransactionId);

            $comisionStripe = $balanceTransaction->fee / 100;
            $docRef = $session->id;

            error_log(print_r('comisionStripe: '.$comisionStripe, TRUE));
            $this->donationController->updateDonationCommission($donationId, $comisionStripe, $docRef);

            $vendorBill = new VendorBillHelper();
            $vendorBill->vendorId = $_ENV['VENDOR_ID'];
            $vendorBill->account = $_ENV['VENDOR_ACCOUNT'];
            $vendorBill->formVendor = $_ENV['FORMULARIO_ORDEN'];
            $vendorBill->subsidiary = $_ENV['SUBSIDIARY'];
            $vendorBill->memo = $_ENV['MEMO'];
            //$vendorBill->location = $_ENV['LOCATION_VENDOR'];
            $vendorBill->location = $invoiceData->locationId;
            $vendorBill->currency = $_ENV['CURRENCY_VENDOR'];
            $vendorBill->itemId = $_ENV['ITEM_VENDOR'];
            //$vendorBill->class = $_ENV['CLASS_VENDOR'];
            $vendorBill->class = $invoiceData->classId;
            //$vendorBill->department = $_ENV['DEPARTMENT_VENDOR'];
            $vendorBill->department = $invoiceData->departmentId;
            $vendorBill->amount = $comisionStripe / 1.16;
            $vendorBill->docRef = $donationId;


            $vendorBillId = generateBillOrder($vendorBill);
            $this->donationController->updateDonationVendorBill($donationId, $vendorBillId);

            $vendorPayment = new VendorPaymentHelper();
            $vendorPayment->appAccount = $_ENV['APP_ACCOUNT_VENDOR'];
            $vendorPayment->formPayment = $_ENV['FORMULARIO_PAYMENT'];
            $vendorPayment->vendorId = $_ENV['VENDOR_ID'];
            $vendorPayment->subsidiary = $_ENV['SUBSIDIARY'];
            $vendorPayment->account = $_ENV['ACCOUNT_PAYMENT'];
            $vendorPayment->currency = $_ENV['CURRENCY_VENDOR'];
            //$vendorPayment->class = $_ENV['CLASS_VENDOR'];  
            $vendorPayment->class = $invoiceData->classId;  
            $vendorPayment->department = $invoiceData->departmentId;
            $vendorPayment->location = $invoiceData->locationId;
            $vendorPayment->billOrder = $vendorBillId;
            $vendorPayment->amount = $comisionStripe;


            $vendorPaymentId = generatePaymentBill($vendorPayment);
            $this->donationController->updateDonationVendorPayment($donationId, $vendorPaymentId);
        } catch (Exception $e) {
            error_log("Error al procesar pago en Stripe: " . $e->getMessage());
        }
    }

    private function sendMembershipEmail($customerInfo){
        try {
            date_default_timezone_set('America/Mexico_City');
            $date = new DateTime();
            
            $formatter = new IntlDateFormatter(
                'es_MX',
                IntlDateFormatter::FULL,
                IntlDateFormatter::NONE,
                'America/Mexico_City',
                IntlDateFormatter::GREGORIAN,
                "d 'de' MMMM 'del' y"
            );

            $formattedDate = $formatter->format($date);

            $templatePath = __DIR__ . '/../templates/donation_membresia.html';
            if (!file_exists($templatePath)) {
                throw new Exception('La plantilla de correo no existe: ' . $templatePath);
            }

            $htmlContent = file_get_contents($templatePath);

            $fullAddress = sprintf(
                "%s %s %s %s %s",
                $customerInfo["address"],
                $customerInfo["address2"],
                $customerInfo["city"],
                $customerInfo["state"],
                $customerInfo["zip"]
            );

            $datos = [
                '{{first_name}}' => $customerInfo["firstName"],
                '{{long_name}}' => $customerInfo["firstName"] . " " . $customerInfo["lastName"],
                '{{donationId}}' => '',
                '{{donation.succeeded_at}}' => $formattedDate,
                '{{billing_address}}' => $fullAddress,
                '{{name}}' => $customerInfo["firstName"],
                '{{phone}}' => $customerInfo["phone"],
                '{{email}}' => $customerInfo["email"],
                '{{amount}}' => "$" . $customerInfo["amount"],
                '{{nex_billing_date}}' => '',
                '{{paymentType}}' => 'Card',
            ];

            foreach ($datos as $clave => $valor) {
                $htmlContent = str_replace($clave, $valor, $htmlContent);
            }

            $recipients = [
                ["email" => $customerInfo["email"]]
            ];

            $mailerService = new MailerService();
            $subject = 'Bienvenida a Aúna!';
            $fromEmail = 'programar@auna.org.mx';
            $fromName = 'Comunidad Aúna';

            if ($mailerService->sendEmail($recipients, $fromEmail, $fromName, $subject, $htmlContent)) {
                error_log("Correo enviado a: " . $customerInfo["email"]);
            } else {
                error_log("No se pudo enviar el correo a: " . $customerInfo["email"]);
            }
        } catch (Exception $e) {
            error_log('Error al enviar el correo: ' . $e->getMessage());
        }
    }

    private function sendUniqueDonationEmail($customerInfo){
        try {
            date_default_timezone_set('America/Mexico_City');
            $date = new DateTime();
            $formatter = new IntlDateFormatter(
                'es_MX',
                IntlDateFormatter::FULL,
                IntlDateFormatter::NONE,
                'America/Mexico_City',
                IntlDateFormatter::GREGORIAN,
                "d 'de' MMMM 'del' y"
            );

            $formattedDate = $formatter->format($date);
            $templatePath = 'templates/donation_unique.html';
            $htmlContent = file_get_contents($templatePath);

            $fullAddress = $customerInfo["address"] . " " . $customerInfo["address2"] . " " .
                $customerInfo["city"] . " " . $customerInfo["state"] . " " . $customerInfo["zip"];

            $datos = [
                '{{first_name}}' => $customerInfo["firstName"],
                '{{long_name}}' => $customerInfo["firstName"] . " " . $customerInfo["lastName"],
                '{{donationId}}' => '',
                '{{donation.succeeded_at}}' => $formattedDate,
                '{{billing_address}}' => $fullAddress,
                '{{name}}' => $customerInfo["firstName"],
                '{{phone}}' => $customerInfo["phone"],
                '{{email}}' => $customerInfo["email"],
                '{{amount}}' => "$" . $customerInfo["amount"],
                '{{nex_billing_date}}' => '',
                '{{paymentType}}' => 'Card'
            ];

            // Reemplazar los marcadores de posición con los valores reales
            foreach ($datos as $clave => $valor) {
                $htmlContent = str_replace($clave, $valor, $htmlContent);
            }

            $recipients = [
                ["email" => $customerInfo["email"]]
            ];

            $mailerService = new MailerService();
            $subject = '¡Gracias por donar a Aúna!';
            $fromEmail = 'programar@auna.org.mx';
            $fromName = 'Comunidad Aúna';

            if ($mailerService->sendEmail($recipients, $fromEmail, $fromName, $subject, $htmlContent)) {
                error_log("Correo enviado a: " . $customerInfo["email"]);
            } else {
                error_log("No se pudo enviar el correo a: " . $customerInfo["email"]);
            }
        } catch (Exception $e) {
            error_log("Error al enviar correo: " . $e->getMessage());
        }
    }
}
?>
