<?php

namespace App\Http\Controllers\Api\dev\kashio;

use App\Http\Controllers\Controller;
use App\Models\dev\resyde\Invoice;
use App\Models\dev\resyde\Payment;
use App\Models\dev\resyde\Houses;
use App\Models\dev\resyde\Tenants;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use GuzzleHttp\Client;

class KashioInvoiceController extends Controller
{
    private function obtenerInvoiceTenant(Request $request, String $conexion)
    {
        $data = $request->all();
        $tenantExternalId = null;
        
        if (isset($data['data']['invoice']['external_id'])) {
            $tenantExternalId = $data['data']['invoice']['external_id'];
        } else {
            return [
                'invoice' => null,
                'error' => 'Structure del request invalida - no se encontro external_id'
            ];
        }
        
        $invoicePersonalActual = Invoice::on($conexion)
            ->where('id', $tenantExternalId)
            ->where('status', 'pendiente ')
            ->first();

        if (!$invoicePersonalActual) {
            return [
                'invoice' => null,
                'error' => 'El residente no cuenta con un recibo registrado o ya esta pagado'
            ];
        }

        return [
            'invoice' => $invoicePersonalActual,
            'error' => null
        ];
    }


    public function registrarPagoInspira(Request $request)
    {
        try {

            $invoice = $this->obtenerInvoiceTenant($request, 'mysql_resyde_inspira');
            if ($invoice['error']) {
                $codigoError = str_contains($invoice['error'], 'No se encontro recibo') ? 404 : 403;
                return response()->json([
                    'success' => false,
                    'message' => $invoice['error']
                ], $codigoError);
            }

            $data = $request->all();
            $amount = $data['data']['invoice']['amount'] ?? 0;
            $idInvoice = $data['data']['invoice']['id'] ?? '';
            $date = $data['created'] ?? '';
            
            if ($date) {
                $date = explode(' ', $date)[0];
            }   
            DB::beginTransaction();
            try {
                $nuevoRegistro = Payment::on('mysql_resyde_inspira')->create([
                    'tenant' => $invoice['invoice']->id,
                    'house' => $invoice['invoice']->id,
                    'year' => $invoice['invoice']->id,
                    'month' => $invoice['invoice']->id,
                    'date' => $date,
                    'expected_amount' => $invoice['invoice']->id,
                    'paid_amount' => $amount,
                    'balance' => floatval($invoice['invoice']->total) - floatval($amount),
                    'comments' => 'IDKashio: '. $idInvoice,
                    'residente_id' => $invoice['invoice']->tenant,
                    'forma_carga' => 'Kashio Webhook',
                ]);


                if ($nuevoRegistro) {
                    $existente = Invoice::on('mysql_resyde_inspira')->where('id', $invoice['invoice']->id)->first();
                    $existente->status = 'pagado';
                    $existente->save();
                }

                DB::commit();

                return response()->json([
                    'success' => true,
                    'message' => 'Pago registrado correctamente',
                    'invoice' => [
                        'id' => $existente->id,
                        'tenant' => $existente->tenant,
                        'house' => $existente->house,
                        'year' => $existente->year,
                        'month' => $existente->month,
                        'particulars' => $existente->particulars,
                        'total' => $existente->total,
                        'comments' => $existente->comments,
                        'status' => $existente->status,
                        'total_part' => $existente->total_part,
                        'total_agua' => $existente->total_agua,
                        'total_asen' => $existente->total_asen,
                        'total_mant2' => $existente->total_mant2,
                        'total_mant3' => $existente->total_mant3,
                        'monto_extra' => $existente->monto_extra,
                        'fecha_emision' => $existente->fecha_emision,
                        'fecha_vencimiento' => $existente->fecha_vencimiento,
                        'lectura_actual' => $existente->lectura_actual,
                        'lectura_pasada' => $existente->lectura_pasada,
                        'diferencia' => $existente->diferencia,
                        'medidor_image' => $existente->medidor_image,
                        'total_luzssgg' => $existente->total_luzssgg,
                        'total_aguacomun' => $existente->total_aguacomun,
                        'total_mant' => $existente->total_mant,
                        'total_extraordinaria' => $existente->total_extraordinaria,
                        'visible' => $existente->visible
                    ]
                ], 200);
            } catch (\Exception $e) {
                DB::rollBack();
                throw $e;
            }


        } catch (\Exception $e) {
            Log::error('Error al obtener invoices: ' . $e->getMessage());
            Log::error('Stack trace: ' . $e->getTraceAsString());

            return response()->json([
                'success' => false,
                'message' => 'Error al obtener invoices: ' . $e->getMessage()
            ], 500);
        }
    }
    
    public function registrarPagoAltuars(Request $request)
    {
        try {

            $invoice = $this->obtenerInvoiceTenant($request, 'mysql_resyde_altuars');
            if ($invoice['error']) {
                $codigoError = str_contains($invoice['error'], 'No se encontro recibo') ? 404 : 403;
                return response()->json([
                    'success' => false,
                    'message' => $invoice['error']
                ], $codigoError);
            }

            $data = $request->all();
            $amount = $data['data']['invoice']['amount'] ?? 0;
            $idInvoice = $data['data']['invoice']['id'] ?? '';
            $date = $data['created'] ?? '';
            
            if ($date) {
                $date = explode(' ', $date)[0];
            }   
            DB::beginTransaction();
            try {
                $nuevoRegistro = Payment::on('mysql_resyde_altuars')->create([
                    'tenant' => $invoice['invoice']->id,
                    'house' => $invoice['invoice']->id,
                    'year' => $invoice['invoice']->id,
                    'month' => $invoice['invoice']->id,
                    'date' => $date,
                    'expected_amount' => $invoice['invoice']->id,
                    'paid_amount' => $amount,
                    'balance' => floatval($invoice['invoice']->total) - floatval($amount),
                    'comments' => 'IDKashio: '. $idInvoice,
                    'residente_id' => $invoice['invoice']->tenant,
                    'forma_carga' => 'Kashio Webhook',
                ]);


                if ($nuevoRegistro) {
                    $existente = Invoice::on('mysql_resyde_altuars')->where('id', $invoice['invoice']->id)->first();
                    $existente->status = 'pagado';
                    $existente->save();
                }

                DB::commit();

                return response()->json([
                    'success' => true,
                    'message' => 'Pago registrado correctamente',
                    'invoice' => [
                        'id' => $existente->id,
                        'tenant' => $existente->tenant,
                        'house' => $existente->house,
                        'year' => $existente->year,
                        'month' => $existente->month,
                        'particulars' => $existente->particulars,
                        'total' => $existente->total,
                        'comments' => $existente->comments,
                        'status' => $existente->status,
                        'total_part' => $existente->total_part,
                        'total_agua' => $existente->total_agua,
                        'total_asen' => $existente->total_asen,
                        'total_mant2' => $existente->total_mant2,
                        'total_mant3' => $existente->total_mant3,
                        'monto_extra' => $existente->monto_extra,
                        'fecha_emision' => $existente->fecha_emision,
                        'fecha_vencimiento' => $existente->fecha_vencimiento,
                        'lectura_actual' => $existente->lectura_actual,
                        'lectura_pasada' => $existente->lectura_pasada,
                        'diferencia' => $existente->diferencia,
                        'medidor_image' => $existente->medidor_image,
                        'total_luzssgg' => $existente->total_luzssgg,
                        'total_aguacomun' => $existente->total_aguacomun,
                        'total_mant' => $existente->total_mant,
                        'total_extraordinaria' => $existente->total_extraordinaria,
                        'visible' => $existente->visible
                    ]
                ], 200);
            } catch (\Exception $e) {
                DB::rollBack();
                throw $e;
            }


        } catch (\Exception $e) {
            Log::error('Error al obtener invoices: ' . $e->getMessage());
            Log::error('Stack trace: ' . $e->getTraceAsString());

            return response()->json([
                'success' => false,
                'message' => 'Error al obtener invoices: ' . $e->getMessage()
            ], 500);
        }

    }

    public function registrarPagoCoral(Request $request)
    {
        try {

            $invoice = $this->obtenerInvoiceTenant($request, 'mysql_resyde_coral');
            if ($invoice['error']) {
                $codigoError = str_contains($invoice['error'], 'No se encontro recibo') ? 404 : 403;
                return response()->json([
                    'success' => false,
                    'message' => $invoice['error']
                ], $codigoError);
            }

            $data = $request->all();
            $amount = $data['data']['invoice']['amount'] ?? 0;
            $idInvoice = $data['data']['invoice']['id'] ?? '';
            $date = $data['created'] ?? '';
            
            if ($date) {
                $date = explode(' ', $date)[0];
            }   
            DB::beginTransaction();
            try {
                $nuevoRegistro = Payment::on('mysql_resyde_coral')->create([
                    'tenant' => $invoice['invoice']->id,
                    'house' => $invoice['invoice']->id,
                    'year' => $invoice['invoice']->id,
                    'month' => $invoice['invoice']->id,
                    'date' => $date,
                    'expected_amount' => $invoice['invoice']->id,
                    'paid_amount' => $amount,
                    'balance' => floatval($invoice['invoice']->total) - floatval($amount),
                    'comments' => 'IDKashio: '. $idInvoice,
                    'residente_id' => $invoice['invoice']->tenant,
                    'forma_carga' => 'Kashio Webhook',
                ]);


                if ($nuevoRegistro) {
                    $existente = Invoice::on('mysql_resyde_coral')->where('id', $invoice['invoice']->id)->first();
                    $existente->status = 'pagado';
                    $existente->save();
                }

                DB::commit();

                return response()->json([
                    'success' => true,
                    'message' => 'Pago registrado correctamente',
                    'invoice' => [
                        'id' => $existente->id,
                        'tenant' => $existente->tenant,
                        'house' => $existente->house,
                        'year' => $existente->year,
                        'month' => $existente->month,
                        'particulars' => $existente->particulars,
                        'total' => $existente->total,
                        'comments' => $existente->comments,
                        'status' => $existente->status,
                        'total_part' => $existente->total_part,
                        'total_agua' => $existente->total_agua,
                        'total_asen' => $existente->total_asen,
                        'total_mant2' => $existente->total_mant2,
                        'total_mant3' => $existente->total_mant3,
                        'monto_extra' => $existente->monto_extra,
                        'fecha_emision' => $existente->fecha_emision,
                        'fecha_vencimiento' => $existente->fecha_vencimiento,
                        'lectura_actual' => $existente->lectura_actual,
                        'lectura_pasada' => $existente->lectura_pasada,
                        'diferencia' => $existente->diferencia,
                        'medidor_image' => $existente->medidor_image,
                        'total_luzssgg' => $existente->total_luzssgg,
                        'total_aguacomun' => $existente->total_aguacomun,
                        'total_mant' => $existente->total_mant,
                        'total_extraordinaria' => $existente->total_extraordinaria,
                        'visible' => $existente->visible
                    ]
                ], 200);
            } catch (\Exception $e) {
                DB::rollBack();
                throw $e;
            }


        } catch (\Exception $e) {
            Log::error('Error al obtener invoices: ' . $e->getMessage());
            Log::error('Stack trace: ' . $e->getTraceAsString());

            return response()->json([
                'success' => false,
                'message' => 'Error al obtener invoices: ' . $e->getMessage()
            ], 500);
        }

    }

    public function obtenerInvoicesKashio(Request $request)
    {
        try {
            $invoice_final = null;
            $invoice_id = $request->query('invoice_id');
            $edificio_db = $request->query('edificio');

            // Determinar conexión a partir de la última palabra de $edificio_db
            $suffix = null;
            if ($edificio_db) {
                $parts = explode('_', $edificio_db);
                $suffix = end($parts);
            }
            if (!$suffix) {
                $suffix = 'inspira'; // valor por defecto
            }
            $connectionName = 'mysql_resyde_' . $suffix;
            Log::info('Kashio: usando conexión', ['edificio' => $edificio_db, 'connection' => $connectionName]);

            $invoicePersonalActual = Invoice::on($connectionName)
                ->where('id', $invoice_id)
                ->first();

            if (!$invoicePersonalActual) {
                return response()->json([
                    'success' => false,
                    'message' => 'No se encontró el recibo con el ID proporcionado'
                ], 404);
            }

            $tentantActual = Tenants::on($connectionName)
                ->where('id', $invoicePersonalActual->tenant)
                ->first();

            if (!$tentantActual) {
                return response()->json([
                    'success' => false,
                    'message' => 'No se encontró el residente asociado al recibo'
                ], 404);
            }

            $houseActual = Houses::on($connectionName)
                ->where('id', $tentantActual->house)
                ->first();

            $fechaRecaudadora = $invoicePersonalActual ? $invoicePersonalActual->fecha_recaudadora : null;
            $fechaRecaudadoraFormatted = null;
            if ($fechaRecaudadora) {
                // Soporta varios formatos y añade +5 horas sólo si viene componente horario
                $dt = false;
                $hasTime = false;

                // 1) Formato esperado: Y/m/d H:i:s (ej: 2026/02/23 21:13:20)
                if (preg_match('/^\d{4}\/\d{2}\/\d{2} /', $fechaRecaudadora)) {
                    $dt = \DateTime::createFromFormat('Y/m/d H:i:s', $fechaRecaudadora);
                    $hasTime = true;
                }

                // 2) Posible formato d/m/Y H:i:s o d/m/Y
                if (!$dt && strpos($fechaRecaudadora, '/') !== false) {
                    $dt = \DateTime::createFromFormat('d/m/Y H:i:s', $fechaRecaudadora);
                    if ($dt) {
                        $hasTime = true;
                    } else {
                        $dt = \DateTime::createFromFormat('d/m/Y', $fechaRecaudadora);
                        $hasTime = false;
                    }
                }

                // 3) Formato Y-m-d H:i:s o Y-m-d
                if (!$dt && preg_match('/^\d{4}-\d{2}-\d{2}/', $fechaRecaudadora)) {
                    $dt = \DateTime::createFromFormat('Y-m-d H:i:s', $fechaRecaudadora);
                    if ($dt) {
                        $hasTime = true;
                    } else {
                        $dt = \DateTime::createFromFormat('Y-m-d', $fechaRecaudadora);
                        $hasTime = false;
                    }
                }

                if ($dt instanceof \DateTime) {
                    if ($hasTime) {
                        // Añadir 5 horas sólo si la fecha original incluía hora
                        $dt->modify('+5 hours');
                        Log::info('Kashio: fechaRecaudadora normalizada con +5h', ['original' => $fechaRecaudadora, 'adjusted' => $dt->format('Y-m-d H:i:s')]);
                    } else {
                        Log::info('Kashio: fechaRecaudadora sin componente horario, no se ajusta hora', ['original' => $fechaRecaudadora]);
                    }
                    $fechaRecaudadoraFormatted = $dt->format('Y-m-d');
                } else {
                    // fallback: dejar el valor original si no se pudo parsear
                    $fechaRecaudadoraFormatted = $fechaRecaudadora;
                    Log::warning('Kashio: no se pudo parsear fechaRecaudadora, usando valor original', ['value' => $fechaRecaudadora]);
                }
            }
            
            $valoresResidenciales = DB::connection($connectionName)
                ->table('valores_genericos')
                ->whereIn('valores_genericos.palabra_clave', ["inspira_kashio_api_key"])
                ->select(
                    'valores_genericos.id',
                    'valores_genericos.palabra_clave',
                    'valores_genericos.valor'
                )->get();
            $kashioApiKey = null;

            // Asignar valores a variables según la palabra clave
            foreach ($valoresResidenciales as $valor) {
                if ($valor->palabra_clave === 'inspira_kashio_api_key') {
                    $kashioApiKey = $valor->valor;
                }
            }

            $client = new Client();
            $url = 'https://api.kashio.net/v1/payments/invoices?date=' . ($fechaRecaudadoraFormatted ?? $fechaRecaudadora);
            $username = $kashioApiKey;
            Log::info('Kashio: iniciar obtenerInvoicesKashio - invoice_id: ' . $invoice_id . ' fechaRecaudadora: ' . $fechaRecaudadora);

            $response = $client->request('GET', $url, [
                'auth' => [$username, ''],
                'headers' => [
                    'Accept' => 'application/json',
                ]
            ]);
            Log::info('Kashio: respuesta recibida - status: ' . $response->getStatusCode());

            $body = $response->getBody()->getContents();
            $data = json_decode($body, true);

            $invoices = $data['data']['invoices'] ?? $data['invoices'] ?? $data['data'] ?? $data;

            Log::info('Invoice obtenido', $invoicePersonalActual ? $invoicePersonalActual->toArray() : []);
            $checkedIds = [];
            foreach ($invoices as $key => $inv) {
                $date = $inv['created'] ?? null;
                $formatted = null;
                if ($date) {
                    $formatted = explode(' ', $date)[0]; // "YYYY-MM-DD"
                    // guardar el valor formateado en la estructura local
                    $invoices[$key]['created'] = $formatted;
                }

                Log::info('Kashio: procesando invoice', ['invoice' => $inv]);

                // Extraer los dígitos finales de invoice_id (ej: INSFEBRERO213 -> 213)
                // Comprobar que el número de casa aparece AL FINAL del invoice_id
                $invoiceIdRaw = trim($inv['invoice_id'] ?? '');
                $house = (string) ($houseActual->house_number ?? '');
                $matched = false;

                if ($house !== '') {
                    // usar preg_quote para evitar metacaracteres
                    $pattern = '/' . preg_quote($house, '/') . '$/';
                    $endMatch = preg_match($pattern, $invoiceIdRaw) === 1;
                    Log::debug('Kashio: endMatch check', ['invoice_id' => $invoiceIdRaw, 'pattern' => $pattern, 'endMatch' => $endMatch]);
                    if ($endMatch) {
                        $matched = true;
                        Log::info('Kashio: house number found at end of invoice_id', ['invoice_id' => $invoiceIdRaw, 'house' => $house]);
                    }
                }

                // Si no se encontró por comparación directa, probar validaciones adicionales
                if (! $matched) {
                    // 1) Si el invoice_id es sólo numérico, compararlo con el id del recibo local
                    if ($invoiceIdRaw !== '' && preg_match('/^\d+$/', $invoiceIdRaw)) {
                        $numericId = $invoiceIdRaw;
                        Log::debug('Kashio: invoice_id es numérico', ['invoice_id' => $invoiceIdRaw, 'numericId' => $numericId, 'local_invoice_id' => $invoicePersonalActual->id ?? null]);
                        if ((string) $numericId === (string)($invoicePersonalActual->id ?? '')) {
                            $matched = true;
                            Log::info('Kashio: invoice_id numérico coincide con invoicePersonalActual->id', ['invoice_id' => $invoiceIdRaw, 'local_id' => $invoicePersonalActual->id ?? null]);
                        }
                    }

                    // 2) Si aún no coincide, intentar extraer sufijo alfanumérico y dígitos finales
                    if (! $matched) {
                        $trailing = null;
                        if ($invoiceIdRaw && preg_match('/([A-Za-z0-9]+)$/', $invoiceIdRaw, $m)) {
                            $trailing = $m[1];
                        }
                        // extraer sólo los dígitos finales del sufijo (si existen)
                        $trailingDigits = null;
                        if ($trailing && preg_match('/(\d+)$/', $trailing, $n)) {
                            $trailingDigits = $n[1];
                            Log::debug('Kashio: trailingDigits extracted', ['invoice_id' => $invoiceIdRaw, 'trailing' => $trailing, 'digits' => $trailingDigits]);
                            if ((string) $trailingDigits === $house) {
                                $matched = true;
                                Log::info('Kashio: trailing digits match house', ['invoice_id' => $invoiceIdRaw, 'trailing' => $trailing, 'digits' => $trailingDigits]);
                            }
                        }
                    }
                }

                $checkedIds[] = $invoiceIdRaw;
                if ($matched) {
                    $invoice_final = $inv;
                    Log::info('Kashio: invoice encontrada', ['invoice_id' => $invoiceIdRaw, 'house' => $house]);
                    break; // si ya encontramos la invoice, no necesitamos seguir iterando
                }
            }

            if (! $invoice_final) {
                // mostrar una muestra de los invoice_id procesados para depuración
                $sample = array_slice($checkedIds, 0, 10);
                Log::warning('Kashio: no se encontró invoice coincidente', ['house' => $house ?? null, 'checked_count' => count($checkedIds), 'sample_invoice_ids' => $sample]);

                return response()->json([
                    'success' => false,
                    'message' => 'No se encontró invoice coincidente para el recibo local',
                    'checked_count' => count($checkedIds),
                    'sample_invoice_ids' => $sample
                ], 404);
            }

            Log::info('Kashio: invoice final encontrada', ['id' => $invoice_final['id'] ?? null]);

            return response()->json([
                'success' => true,
                'message' => 'Invoices obtenidas correctamente',
                'data' => $invoice_final
            ], 200);

        } catch (\Exception $e) {
            Log::error('Error al obtener invoices de Kashio: ' . $e->getMessage());
            Log::error('Stack trace: ' . $e->getTraceAsString());

            return response()->json([
                'success' => false,
                'message' => 'Error al obtener invoices: ' . $e->getMessage()
            ], 500);
        }
    }
}
