<?php

namespace Daniv04\HaciendaPackage\Services\DbService;

use Daniv04\HaciendaPackage\Models\Receipt;
use Daniv04\HaciendaPackage\Models\SentReceipt;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Daniv04\HaciendaPackage\Services\ConsecutiveNumberService;
use DateTime;
use Illuminate\Contracts\Pagination\LengthAwarePaginator;


class DbService
{
    public function __construct(
        private ConsecutiveNumberService $consecutiveNumberService
    ) {}


    public function saveReceipt(array $payload, string $receiptType): Receipt
    {
        try {
            DB::beginTransaction();

            $documentType  = $payload['Clave']['TipoComprobante'];
            $establishment = (int) (ltrim($payload['Clave']['Sucursal'] ?? '1', '0') ?: 1);
            $terminal      = (int) (ltrim($payload['Clave']['Terminal'] ?? '1', '0') ?: 1);

            $receipt = Receipt::create([
                'consecutive_number' => $this->consecutiveNumberService->getIncrementedConsecutiveNumber($documentType, $establishment, $terminal),
                'receipt_type' => $receiptType,
                'emission_date' => $payload['Encabezado']['FechaEmision'] ?? now()->toIso8601String(),
                'hacienda_status' => 'pending',

                'sell_condition' => $payload['Encabezado']['CondicionVenta'] ?? 'cash',
                'total_amount' => $payload['ResumenFactura']['TotalVenta'],
                'tax_amount' => $payload['ResumenFactura']['TotalImpuesto'],
                'total_discount' => $payload['ResumenFactura']['TotalDescuentos'],
                'total_voucher' => $payload['ResumenFactura']['TotalComprobante'],
                'currency' => $payload['ResumenFactura']['CodigoTipoMoneda']['CodigoMoneda'],
                'exchange_rate' => $payload['ResumenFactura']['CodigoTipoMoneda']['TipoCambio'],

                'emissor_name' => $payload['Emisor']['Nombre'],
                'emissor_number' => $payload['Emisor']['Identificacion']['Numero'],
                'emissor_type_identification' => $payload['Emisor']['Identificacion']['Tipo'],
                'receiver_name' => $payload['Receptor']['Nombre'] ?? null,
                'receiver_number' => $payload['Receptor']['Identificacion']['Numero'] ?? null,
                'receiver_type_identification' => $payload['Receptor']['Identificacion']['Tipo'] ?? null,
          

            ]);

            $receipt->payload()->create([
                'receipt_type' => $receiptType,
                'payload_json' => $payload,
            ]);

            DB::commit();
            
            return $receipt->load('payload');

        } catch (\Exception $e) {
            DB::rollBack();
            
            Log::error('Error saving receipt', [
                'receiptType' => $receiptType,
                'error' => $e->getMessage(),
                'trace' => $e->getTraceAsString()
            ]);
            
            throw $e;
        }
    }

    public function saveSentReceipt(array $payload,  string $status, string $documentType): Receipt
    {
        try {
            DB::beginTransaction();

            $establishment = (int) (ltrim($payload['Clave']['Sucursal'] ?? '1', '0') ?: 1);
            $terminal      = (int) (ltrim($payload['Clave']['Terminal'] ?? '1', '0') ?: 1);
            $typeCode      = $payload['Clave']['TipoComprobante'] ?? '01';

            $sentReceipt = SentReceipt::create([
                'consecutive_number' => $this->consecutiveNumberService->getIncrementedConsecutiveNumber($typeCode, $establishment, $terminal),
                'receipt_type' => $documentType,
                'emission_date' => $payload['FechaEmision'],
                'receipt_status' => 'pending',
                'hacienda_status' => 'pending',

                'reception_message' => $payload['Detalle']['Mensaje'] ?? null,
                'reception_status' => $status,
                'reception_code' => $payload['Detalle']['CodigoMensaje'] ?? null,
                'economic_activity_code' => $payload['Detalle']['CodigoActividad'] ?? null,
                'ui_key_sent_document' => $payload['Detalle']['Clave'] ?? null,
                'tax_condition_code' => $payload['Detalle']['CondicionImpuesto'] ?? null,
                'tax_credited' => $payload['Detalle']['MontoTotalImpuestoAcreditar'] ?? null,
                'total_expense' => $payload['Detalle']['MontoTotalDeGastoAplicable'] ?? null,
                'tax_amount' => $payload['Detalle']['MontoTotalImpuesto'] ?? null,
                'total_voucher' => $payload['Detalle']['TotalFactura'] ?? null,

                'emissor_name' => $payload['Emisor']['Nombre'],
                'emissor_number' => $payload['Emisor']['Identificacion']['Numero'],
                'emissor_type_identification' => $payload['Emisor']['Identificacion']['Tipo'],
                'receiver_name' => $payload['Receptor']['Nombre'] ?? null,
                'receiver_number' => $payload['Receptor']['Identificacion']['Numero'] ?? null,
                'receiver_type_identification' => $payload['Receptor']['Identificacion']['Tipo'] ?? null,
          

            ]);

            DB::commit();
            return $sentReceipt;

        } catch (\Exception $e) {
            DB::rollBack();
            Log::error('Error saving sent receipt', [
                'data' => $payload,
                'error' => $e->getMessage(),
                'trace' => $e->getTraceAsString()
            ]);
            throw $e;
        }
    }

    public function getAllReceipts(int $perPage = 25): LengthAwarePaginator
    {
        return Receipt::with('payload', 'haciendaResponse')
        ->paginate($perPage);
    }

    public function getAllReceiptsByType(string $receiptType, int $perPage = 25): LengthAwarePaginator
    {
        return Receipt::with('payload', 'haciendaResponse')
        ->where('receipt_type', $receiptType)
        ->paginate($perPage);
    }

    public function getReceiptsByStatus(string $receiptStatus, int $perPage = 25): LengthAwarePaginator
    {
        return Receipt::with('payload', 'haciendaResponse')
        ->where('receipt_status', $receiptStatus)
        ->paginate($perPage);
    }

    public function getReceiptsByHaciendaStatus(string $haciendaStatus, int $perPage = 25): LengthAwarePaginator
    {
        return Receipt::with('payload', 'haciendaResponse')
        ->where('hacienda_status', $haciendaStatus)
        ->paginate($perPage);
    }

    public function getReceiptById(int $id): ?Receipt
    {
        return Receipt::where('id', $id)
        ->with('payload')
        ->with('haciendaResponse')
        ->first();
    }

    public function getReceiptStatusByUiKey(string $ui_key): ?Receipt
    {
        return Receipt::where('ui_key', $ui_key)
        ->with('haciendaResponse')
        ->first();
    } 

    public function getReceiptByUiKey(string $ui_key): ?Receipt
    {
        return Receipt::where('ui_key', $ui_key)
        ->with('payload')
        ->with('haciendaResponse')
        ->first();
    } 

    public function updateReceiptStatus(string $ui_key, string $receiptStatus, string $haciendaStatus, ?string $haciendaResponse = null): ?Receipt
    {
        $receipt = Receipt::where('ui_key', $ui_key)->first();

        if (!$receipt) {
            return null;
        }

        $receipt->update([
            'receipt_status' => $receiptStatus,
            'hacienda_status' => $haciendaStatus,
        ]);

        if ($haciendaResponse) {
            $receipt->haciendaResponse()->create([
                'hacienda_response_at' => now(),
                'response_json' => json_decode($haciendaResponse, true),
            ]);
        }

        return $receipt->fresh('haciendaResponse');
    }

   

}
