<?php

namespace SmsNotifier\Service;

use GuzzleHttp\Client;
use Stripe\StripeClient;
use Stripe\Exception\ApiErrorException;

class PaymentIntentService
{
    private $ucrmApi;
    private $stripeApiKey;
    private $stripeClient;
    private $logger;

    public function __construct($ucrmApi, $stripeApiKey, $logger = null)
    {
        $this->ucrmApi = $ucrmApi;
        $this->stripeApiKey = $stripeApiKey;
        $this->logger = $logger;
        $this->stripeClient = new StripeClient($this->stripeApiKey);
    }

    public function searchClients($query)
    {
        try {
            $clients = $this->ucrmApi->get('clients', [
                'query' => $query,
                'limit' => 5
            ]);

            return array_map(function ($client) {
                return [
                    'id' => $client['id'],
                    'firstName' => $client['firstName'],
                    'lastName' => $client['lastName'],
                    'username' => $client['username'],
                    'fullAddress' => $client['fullAddress'] ?? '',
                    'companyName' => $client['companyName'],
                    'clientType' => $client['clientType'],
                    'isSuspended' => $client['isSuspended'] ?? false,
                    'contacts' => $client['contacts'] ?? [],
                    'attributes' => $client['attributes'] ?? []
                ];
            }, $clients);
        } catch (\Exception $e) {
            return ['error' => $e->getMessage()];
        }
    }

    public function getClientDetails($clientId)
    {
        try {
            $client = $this->ucrmApi->get("clients/{$clientId}");

            $stripeCustomerId = null;
            $clabeInterbancaria = null;
            if (isset($client['attributes'])) {
                foreach ($client['attributes'] as $attribute) {
                    if ($attribute['key'] === 'stripeCustomerId' || $attribute['name'] === 'Stripe Customer ID') {
                        $stripeCustomerId = $attribute['value'];
                    }
                    if ($attribute['key'] === 'clabeInterbancaria' || $attribute['name'] === 'Clabe Interbancaria') {
                        $clabeInterbancaria = $attribute['value'];
                    }
                }
            }

            return [
                'id'                 => $client['id'],
                'fullName'           => ($client['clientType'] == 1)
                    ? $client['firstName'] . ' ' . $client['lastName']
                    : $client['companyName'],
                'stripeCustomerId'   => $stripeCustomerId,
                'clabeInterbancaria' => $clabeInterbancaria,
                'email'              => $this->getClientEmail($client),
                'accountOutstanding' => $client['accountOutstanding'] ?? 0,
                'accountBalance'     => $client['accountBalance'] ?? 0,  // crédito a favor del cliente
                'accountCredit'      => $client['accountCredit'] ?? 0,
                'fullAddress'        => $client['fullAddress'] ?? '',
            ];
        } catch (\Exception $e) {
            return ['error' => $e->getMessage()];
        }
    }

    private function getClientEmail($clientData)
    {
        if (!empty($clientData['contacts'])) {
            foreach ($clientData['contacts'] as $contact) {
                if (!empty($contact['email'])) {
                    return $contact['email'];
                }
            }
        }
        return $clientData['username'] ?? '';
    }

    public function createPaymentIntent($clientId, $amount, $stripeCustomerId, $adminId = null)
    {
        if ($amount < 10) {
            throw new \Exception("El monto debe ser mayor a 10 MXN");
        }

        try {
            $amountCentavos = intval($amount * 100);

            $paymentIntent = $this->stripeClient->paymentIntents->create([
                'amount' => $amountCentavos,
                'currency' => 'mxn',
                'customer' => $stripeCustomerId,
                'payment_method_types' => ['customer_balance'],
                'payment_method_data' => ['type' => 'customer_balance'],
                'confirm' => true,
                'payment_method_options' => [
                    'customer_balance' => [
                        'funding_type' => 'bank_transfer',
                        'bank_transfer' => ['type' => 'mx_bank_transfer']
                    ],
                ],
                'metadata' => [
                    'clientId' => $clientId,
                    'createdBy' => 'UCRM',
                    'paymentType' => 'card.one_time',
                    'signedInAdminId' => $adminId,
                    'tipoPago' => 'Transferencia Bancaria'
                ],
            ]);

            $this->log("PaymentIntent created: " . $paymentIntent->id . " Status: " . $paymentIntent->status);

            return [
                'success' => true,
                'id' => $paymentIntent->id,
                'status' => $paymentIntent->status,
                'amount' => $paymentIntent->amount / 100,
                'currency' => $paymentIntent->currency,
                'next_action' => $paymentIntent->next_action
            ];
        } catch (ApiErrorException $e) {
            return ['success' => false, 'error' => $e->getMessage()];
        } catch (\Exception $e) {
            return ['success' => false, 'error' => $e->getMessage()];
        }
    }

    public function getLastPayments($stripeCustomerId, $limit = 10)
    {
        try {
            // Buscamos más registros para filtrar por tipo de pago (transferencias)
            $collection = $this->stripeClient->paymentIntents->all([
                'customer' => $stripeCustomerId,
                'limit' => 50,
                'expand' => ['data.charges']
            ]);

            $result = [];
            foreach ($collection->data as $payment) {
                // Filtramos por transferencias bancarias (balance de cliente)
                $isBankTransfer = in_array('customer_balance', $payment->payment_method_types);
                
                if ($isBankTransfer) {
                    $description = $payment->description ?? $payment->metadata['description'] ?? 'Transferencia Bancaria';
                    
                    // Extraer referencia si existe en los cargos
                    $reference = '-';
                    if (!empty($payment->charges->data)) {
                        foreach ($payment->charges->data as $charge) {
                            if ($charge->payment_method_details->type === 'customer_balance') {
                                $bankTransfer = $charge->payment_method_details->customer_balance->bank_transfer;
                                if ($bankTransfer && isset($bankTransfer->reference)) {
                                    $reference = $bankTransfer->reference;
                                }
                            }
                        }
                    }

                    $dt = (new \DateTime('@' . $payment->created))->setTimezone(new \DateTimeZone('America/Mexico_City'));
                    $result[] = [
                        'id'          => $payment->id,
                        'amount'      => $payment->amount / 100,
                        'currency'    => strtoupper($payment->currency),
                        'status'      => $payment->status,
                        'created'     => $payment->created,
                        'date'        => $dt->format('d/m/Y H:i'),
                        'description' => $description,
                        'reference'   => $reference
                    ];

                    if (count($result) >= $limit) break;
                }
            }
            return $result;
        } catch (\Exception $e) {
            $this->log("Error fetching last payments: " . $e->getMessage());
            return [];
        }
    }

    public function getLastOxxoPayments($stripeCustomerId, $limit = 5)
    {
        try {
            // Fetch a bit more to allow for filtering
            $collection = $this->stripeClient->paymentIntents->all([
                'customer' => $stripeCustomerId,
                'limit' => 100,
                'expand' => ['data.charges'],
            ]);

            $result = [];
            foreach ($collection->data as $payment) {
                // Check if it's an OXXO payment
                $isOxxo = false;
                if (isset($payment->payment_method_types) && in_array('oxxo', $payment->payment_method_types)) {
                    $isOxxo = true;
                }

                if ($isOxxo) {
                    $oxxoNumber = $payment->next_action->oxxo_display_details->number ?? '-';
                    $pdfUrl = $payment->next_action->oxxo_display_details->hosted_voucher_url ?? null;

                    // Fallback for Succeeded payments (where next_action might be null)
                    if ($oxxoNumber === '-' && !empty($payment->charges->data)) {
                        $charge = $payment->charges->data[0];
                        if (isset($charge->payment_method_details->oxxo->number)) {
                            $oxxoNumber = $charge->payment_method_details->oxxo->number;
                        }
                    }

                    $result[] = [
                        'id' => $payment->id,
                        'amount' => $payment->amount / 100,
                        'currency' => strtoupper($payment->currency),
                        'status' => $payment->status,
                        'created' => $payment->created,
                        'oxxoNumber' => $oxxoNumber, // Reference Number
                        'voucherUrl' => $pdfUrl
                    ];
                }

                if (count($result) >= $limit) break;
            }
            return $result;
        } catch (\Exception $e) {
            $this->log("Error fetching OXXO payments: " . $e->getMessage());
            return ['error' => $e->getMessage()];
        }
    }

    public function getCustomerCashBalance($stripeCustomerId)
    {
        try {
            $balanceObj = $this->stripeClient->customers->retrieveCashBalance(
                $stripeCustomerId,
                []
            );
            $amount = $balanceObj->available['mxn'] ?? 0;
            return $amount / 100;
        } catch (\Exception $e) {
            // Fallback or old api version check
            try {
                $customer = $this->stripeClient->customers->retrieve(
                    $stripeCustomerId,
                    ['expand' => ['cash_balance']]
                );
                return ($customer->cash_balance->available['mxn'] ?? 0) / 100;
            } catch (\Exception $ex) {
                return 0;
            }
        }
    }

    private function log($message)
    {
        if ($this->logger) {
            $this->logger->debug($message);
        } else {
            error_log($message);
        }
    }
}
