<?php

defined('BASEPATH') or exit('No direct script access allowed');

class Certificadores_model extends CI_Model
{
    public function __construct()
    {
        parent::__construct();
    }

    // ==============================
    // CERTIFICADORES
    // ==============================
    public function getallcertificadores()
    {
        return $this->db->order_by('id', 'ASC')->get('sma_certificadores')->result();
    }

    public function get_certificador($id)
    {
        return $this->db->where('id', (int)$id)->get('sma_certificadores')->row();
    }

    public function create_certificador($data)
    {
        return $this->db->insert('sma_certificadores', $data);
    }

    public function update_certificador($id, $data)
    {
        return $this->db->where('id', (int)$id)->update('sma_certificadores', $data);
    }

    public function delete_certificador($id)
    {
        return $this->db->where('id', (int)$id)->delete('sma_certificadores');
    }

    // ==============================
    // CONEXIONES
    // ==============================
    public function get_all_conexiones()
    {
        $this->db->select('c.*, w.name as sucursal, ce.nombre as certificador');
        $this->db->from('sma_clientes_certificador_conexion c');
        $this->db->join('sma_warehouses w', 'w.id = c.sucursal_id', 'left');
        $this->db->join('sma_certificadores ce', 'ce.id = c.certificador_id', 'left');
        $this->db->order_by('c.id', 'ASC');
        return $this->db->get()->result();
    }

    public function get_conexion($id)
    {
        return $this->db->where('id', (int)$id)->get('sma_clientes_certificador_conexion')->row();
    }

    public function create_conexion($data)
    {
        return $this->db->insert('sma_clientes_certificador_conexion', $data);
    }

    public function update_conexion($id, $data)
    {
        return $this->db->where('id', (int)$id)->update('sma_clientes_certificador_conexion', $data);
    }

    public function delete_conexion($id)
    {
        return $this->db->where('id', (int)$id)->delete('sma_clientes_certificador_conexion');
    }

    // ==============================
    // TOKENS
    // ==============================
    public function get_token_by_conexion_usuario($conexion_id, $usuario)
    {
        return $this->db
            ->where('conexion_id', (int)$conexion_id)
            ->where('usuario', $usuario)
            ->order_by('id', 'DESC')
            ->get('sma_certificador_tokens')
            ->row();
    }
public function get_token_nuc_by_conexion_usuario($conexion_id, $usuario)
{
    return $this->db
        ->where('conexion_id', $conexion_id)
        ->where('usuario', $usuario)
        ->order_by('id','DESC')
        ->get('sma_certificador_tokensnuc')
        ->row();
}

public function get_token_valido($certificador, $conexion)
{
    // ==========================================
    // 🚫 VALIDACIONES DE ACTIVACIÓN (NUEVO)
    // ==========================================
    if (
        !$certificador ||
        !$conexion ||
        (int)$certificador->activo !== 1 ||
        (int)$conexion->activo !== 1
    ) {
        // No hacer nada si está deshabilitado
        return null;
    }

    $row   = $this->get_token_by_conexion_usuario($conexion->id, $conexion->usuario);
    $ahora = time();

    // ==========================================
    // 🟢 TOKEN EXISTENTE Y VÁLIDO
    // ==========================================
    if ($row && strtotime($row->expiracion) > $ahora) {

        $restante = strtotime($row->expiracion) - $ahora;

        // 🔥 MENOS DE 24h → renovar en segundo plano
        if ($restante < 86400) {

            $nuevo = $this->solicitar_token($certificador, $conexion);

            if ($nuevo) {
                $this->save_or_update_token(
                    $conexion->id,
                    $conexion->usuario,
                    $nuevo['token'],
                    $nuevo['expiracion']
                );
            }
        }

        // 👉 usamos SIEMPRE el actual para esta factura
        return $row->token;
    }

    // ==========================================
    // 🔴 NO HAY TOKEN O ESTÁ VENCIDO
    // ==========================================
    $nuevo = $this->solicitar_token($certificador, $conexion);

    if (!$nuevo) {
        return null;
    }

    $this->save_or_update_token(
        $conexion->id,
        $conexion->usuario,
        $nuevo['token'],
        $nuevo['expiracion']
    );

    return $nuevo['token'];
}
/*
=========================================
TOKEN NUC (CONSULTA NIT)
=========================================
*/
public function get_token_valido_nuc($certificador, $conexion)
{
    // ==========================================
    // 🚫 VALIDACIONES DE ACTIVACIÓN (NUEVO)
    // ==========================================
    if (
        !$certificador ||
        !$conexion ||
        (int)$certificador->activo !== 1 ||
        (int)$conexion->activo !== 1
    ) {
        // No hacer nada si está deshabilitado
        return null;
    }

    $row   = $this->get_token_nuc_by_conexion_usuario($conexion->id, $conexion->usuario);
    $ahora = time();

    // ==========================================
    // 🟢 TOKEN EXISTENTE Y VÁLIDO
    // ==========================================
    if ($row && strtotime($row->expiracion) > $ahora) {

        $restante = strtotime($row->expiracion) - $ahora;

        // 🔥 MENOS DE 24h → renovar en segundo plano
        if ($restante < 86400) {

            $nuevo = $this->solicitar_token_nuc($certificador, $conexion);

            if ($nuevo) {
                $this->save_or_update_token_nuc(
                    $conexion->id,
                    $conexion->usuario,
                    $nuevo['token'],
                    $nuevo['expiracion']
                );
            }
        }

        // 👉 usamos SIEMPRE el actual para esta factura
        return $row->token;
    }

    // ==========================================
    // 🔴 NO HAY TOKEN O ESTÁ VENCIDO
    // ==========================================
    $nuevo = $this->solicitar_token_nuc($certificador, $conexion);

    if (!$nuevo) {
        return null;
    }

    $this->save_or_update_token_nuc(
        $conexion->id,
        $conexion->usuario,
        $nuevo['token'],
        $nuevo['expiracion']
    );

    return $nuevo['token'];
}


    public function save_or_update_token($conexion_id, $usuario, $token, $expiracion)
    {
        $now = date('Y-m-d H:i:s');
        $row = $this->get_token_by_conexion_usuario($conexion_id, $usuario);

        $data = [
            'conexion_id' => (int)$conexion_id,
            'usuario'     => $usuario,
            'token'       => $token,
            'expiracion'  => $expiracion,
            'updated_at'  => $now,
        ];

        if ($row) {
            return $this->db->where('id', $row->id)->update('sma_certificador_tokens', $data);
        } else {
            $data['created_at'] = $now;
            return $this->db->insert('sma_certificador_tokens', $data);
        }
    }

public function save_or_update_token_nuc($conexion_id, $usuario, $token, $expiracion)
{
    $now = date('Y-m-d H:i:s');

    $row = $this->get_token_nuc_by_conexion_usuario($conexion_id, $usuario);

    $data = [
        'conexion_id' => (int)$conexion_id,
        'usuario'     => $usuario,
        'token'       => $token,
        'expiracion'  => $expiracion,
        'updated_at'  => $now
    ];

    if ($row) {
        return $this->db->where('id', $row->id)
                        ->update('sma_certificador_tokensnuc', $data);
    } else {
        $data['created_at'] = $now;
        return $this->db->insert('sma_certificador_tokensnuc', $data);
    }
}

    public function solicitar_token($certificador, $conexion)
{
    $url = trim($certificador->api_path);

    // 🔥 DIGIFACT requiere formato especial:
    // Username = GT.000000NIT.USUARIO

    $nit = preg_replace('/\D/', '', $conexion->nit);
    $nit_padded = str_pad($nit, 12, '0', STR_PAD_LEFT);

    $username = 'GT.' . $nit_padded . '.' . $conexion->usuario;

    $payload = [
        'Username' => $username,
        'Password' => $conexion->contrasena,
    ];

    log_message('error', 'LOGIN DIGIFACT PAYLOAD: ' . json_encode($payload));

    $ch = curl_init($url);

    curl_setopt_array($ch, [
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_POST           => true,
        CURLOPT_HTTPHEADER     => ['Content-Type: application/json'],
        CURLOPT_POSTFIELDS     => json_encode($payload),
        CURLOPT_TIMEOUT        => 30,
    ]);

    $response = curl_exec($ch);
    $error    = curl_error($ch);

    curl_close($ch);

    log_message('error', 'RESPUESTA DIGIFACT: ' . $response);

    if ($error) {
        log_message('error', 'CURL ERROR: ' . $error);
        return null;
    }

    $data = json_decode($response, true);

    if (!is_array($data)) {
        return null;
    }

    // DIGIFACT normalmente devuelve:
    // { "Token": "...", "Expira": "2025-02-05T20:00:00" }

    $token      = $data['Token']  ?? null;
    $expiracion =
    $data['expira_en'] ??
    $data['expira'] ??
    $data['expiracion'] ??
    null;


    if (!$token) {
        return null;
    }

    if (!empty($expiracion)) {

    $dt = DateTime::createFromFormat('n/j/Y h:i:s A', $expiracion);

    if ($dt) {
        $expiracion = $dt->format('Y-m-d H:i:s');
    } else {
        log_message('error', 'No se pudo parsear expiración: ' . $expiracion);
        $expiracion = date('Y-m-d H:i:s', strtotime('+1 day'));
    }

} else {
    $expiracion = date('Y-m-d H:i:s', strtotime('+1 day'));
}


    return [
        'token'      => $token,
        'expiracion' => $expiracion,
    ];
}

public function solicitar_token_nuc($certificador, $conexion)
{
    $url = trim($certificador->api_path);

    // 🔥 DIGIFACT requiere formato especial:
    // Username = GT.000000NIT.USUARIO

    $nit = preg_replace('/\D/', '', $conexion->nit);
    $nit_padded = str_pad($nit, 12, '0', STR_PAD_LEFT);

    $username = 'GT.' . $nit_padded . '.' . $conexion->usuario;

    $payload = [
        'Username' => $username,
        'Password' => $conexion->contrasena,
    ];

    log_message('error', 'LOGIN DIGIFACT PAYLOAD: ' . json_encode($payload));

    $ch = curl_init($url);

    curl_setopt_array($ch, [
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_POST           => true,
        CURLOPT_HTTPHEADER     => ['Content-Type: application/json'],
        CURLOPT_POSTFIELDS     => json_encode($payload),
        CURLOPT_TIMEOUT        => 30,
    ]);

    $response = curl_exec($ch);
    $error    = curl_error($ch);

    curl_close($ch);

    log_message('error', 'RESPUESTA DIGIFACT: ' . $response);

    if ($error) {
        log_message('error', 'CURL ERROR: ' . $error);
        return null;
    }

    $data = json_decode($response, true);

    if (!is_array($data)) {
        return null;
    }

    // DIGIFACT normalmente devuelve:
    // { "Token": "...", "Expira": "2025-02-05T20:00:00" }

    $token      = $data['Token']  ?? null;
    $expiracion =
    $data['expira_en'] ??
    $data['expira'] ??
    $data['expiracion'] ??
    null;


    if (!$token) {
        return null;
    }

    if (!empty($expiracion)) {

    $dt = DateTime::createFromFormat('n/j/Y h:i:s A', $expiracion);

    if ($dt) {
        $expiracion = $dt->format('Y-m-d H:i:s');
    } else {
        log_message('error', 'No se pudo parsear expiración: ' . $expiracion);
        $expiracion = date('Y-m-d H:i:s', strtotime('+1 day'));
    }

} else {
    $expiracion = date('Y-m-d H:i:s', strtotime('+1 day'));
}


    return [
        'token'      => $token,
        'expiracion' => $expiracion,
    ];
}

}
