<?php

namespace ESI_PEPPOL\models;

class PEPPOL_Main_model {

    public $id;
    public $id_order;
    public $data_sent;
    public $response_data;
    public $document_id;
    public $peppol_document_id;
    public $status;
    public $success;
    public $message;
    public $http_code;
    public $date_add;
    public $date_update;

    /**
     * Retourne le nom complet de la table (avec préfixe WP)
     *
     * @return string
     */
    public static function get_table_name(): string {
        global $wpdb;

        return $wpdb->prefix . 'esi_peppol_invoices';
    }

    /**
     * Récupère les derniers enregistrements pour l'affichage dans l'admin.
     *
     * @param int $limit Nombre maximum de lignes à retourner.
     *
     * @return array Liste d'objets (stdClass).
     */
    public static function get_recent(int $limit = 50): array {
        global $wpdb;

        $table_name = self::get_table_name();
        $limit      = max(1, $limit);

        $sql = $wpdb->prepare(
            "SELECT * FROM {$table_name} ORDER BY date_add DESC LIMIT %d",
            $limit
        );

        return (array) $wpdb->get_results($sql);
    }

    /**
     * Crée la table esi_peppol_invoices si elle n'existe pas
     *
     * À appeler lors de l'activation du plugin.
     *
     * @return void
     */
    public static function create_table(): void {
        global $wpdb;

        $table_name      = self::get_table_name();
        $charset_collate = $wpdb->get_charset_collate();

        $sql = "CREATE TABLE {$table_name} (
            id BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT,
            id_order BIGINT(20) UNSIGNED NOT NULL,
            data_sent LONGTEXT NULL,
            response_data LONGTEXT NULL,
            document_id VARCHAR(100) NOT NULL,
            peppol_document_id VARCHAR(191) NOT NULL,
            status VARCHAR(50) NOT NULL,
            success TINYINT(1) NOT NULL DEFAULT 0,
            message TEXT NULL,
            http_code INT(11) NULL,
            date_add DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
            date_update DATETIME NULL DEFAULT NULL,
            PRIMARY KEY  (id),
            KEY id_order (id_order),
            KEY document_id (document_id),
            KEY peppol_document_id (peppol_document_id)
        ) {$charset_collate};";

        require_once \ABSPATH . 'wp-admin/includes/upgrade.php';
        \dbDelta($sql);
    }

    /**
     * Crée un enregistrement PEPPOL pour une commande WooCommerce.
     *
     * @param int         $order_id            ID de la commande WooCommerce.
     * @param mixed       $response_data       Données retournées par l'API (array / objet / string).
     * @param mixed       $data_sent           Payload envoyé à l'API (array / objet / string).
     * @param string      $document_id         Identifiant / numéro du document (côté boutique).
     * @param string      $peppol_document_id  Identifiant du document dans Peppol.
     * @param string      $status              Statut métier (ex: 'created', 'sent', 'error').
     * @param bool        $success             Indique si l'appel API est un succès.
     * @param string      $message             Message d'information / d'erreur.
     * @param int|null    $http_code           Code HTTP retourné par l'API, si disponible.
     *
     * @return int|null ID inséré ou null en cas d'erreur.
     */
    public static function create(
        int $order_id,
        $response_data,
        $data_sent,
        string $document_id,
        string $peppol_document_id,
        string $status,
        bool $success,
        string $message = '',
        ?int $http_code = null
    ): ?int {
        global $wpdb;

        $table_name           = self::get_table_name();
        $serialized_response  = \maybe_serialize($response_data);
        $serialized_data_sent = \maybe_serialize($data_sent);
        $now                  = \current_time('mysql');
        $success_int          = $success ? 1 : 0;

        $inserted = $wpdb->insert(
            $table_name,
            [
                'id_order'           => $order_id,
                'data_sent'          => $serialized_data_sent,
                'response_data'      => $serialized_response,
                'document_id'        => $document_id,
                'peppol_document_id' => $peppol_document_id,
                'status'             => $status,
                'success'            => $success_int,
                'message'            => $message,
                'http_code'          => $http_code,
                'date_add'           => $now,
                'date_update'        => $now,
            ],
            ['%d', '%s', '%s', '%s', '%s', '%s', '%d', '%s', '%d', '%s', '%s']
        );

        if ($inserted === false) {
            return null;
        }

        return (int) $wpdb->insert_id;
    }

    /**
     * Enregistre ou met à jour les données PEPPOL pour une commande WooCommerce.
     *
     * - 1 ligne par commande (id_order) : si une ligne existe déjà, elle est mise à jour.
     * - La réponse d'API est stockée en sérialisé dans response_data.
     * - Le payload envoyé est stocké dans data_sent.
     */
    public static function save_for_order(
        int $order_id,
        $response_data,
        $data_sent,
        string $document_id,
        string $peppol_document_id,
        string $status,
        bool $success,
        string $message = '',
        ?int $http_code = null
    ): bool {
        global $wpdb;

        $table_name           = self::get_table_name();
        $serialized_response  = \maybe_serialize($response_data);
        $serialized_data_sent = \maybe_serialize($data_sent);
        $now                  = \current_time('mysql');
        $success_int          = $success ? 1 : 0;

        // Vérifier si une ligne existe déjà pour cette commande
        $existing_id = $wpdb->get_var(
            $wpdb->prepare(
                "SELECT id FROM {$table_name} WHERE id_order = %d LIMIT 1",
                $order_id
            )
        );

        if ($existing_id) {
            // Mise à jour
            $updated = $wpdb->update(
                $table_name,
                [
                    'data_sent'          => $serialized_data_sent,
                    'response_data'      => $serialized_response,
                    'document_id'        => $document_id,
                    'peppol_document_id' => $peppol_document_id,
                    'status'             => $status,
                    'success'            => $success_int,
                    'message'            => $message,
                    'http_code'          => $http_code,
                    'date_update'        => $now,
                ],
                ['id' => (int) $existing_id],
                ['%s', '%s', '%s', '%s', '%s', '%d', '%s', '%d', '%s'],
                ['%d']
            );

            return $updated !== false;
        }

        // Pas d'enregistrement existant : on crée
        return self::create(
            $order_id,
            $response_data,
            $data_sent,
            $document_id,
            $peppol_document_id,
            $status,
            $success,
            $message,
            $http_code
        ) !== null;
    }

    /**
     * Récupère un enregistrement PEPPOL par ID de commande (id_order).
     *
     * La propriété response_data est désérialisée automatiquement.
     * La propriété data_sent est désérialisée automatiquement.
     */
    public static function get_by_order_id(int $order_id): ?object {
        global $wpdb;

        $table_name = self::get_table_name();

        $row = $wpdb->get_row(
            $wpdb->prepare(
                "SELECT * FROM {$table_name} WHERE id_order = %d LIMIT 1",
                $order_id
            )
        );

        if (!$row) {
            return null;
        }

        // Désérialiser la réponse API et le payload si nécessaire
        if (isset($row->response_data)) {
            $row->response_data = \maybe_unserialize($row->response_data);
        }
        if (isset($row->data_sent)) {
            $row->data_sent = \maybe_unserialize($row->data_sent);
        }

        return $row;
    }

    /**
     * Récupère un enregistrement PEPPOL par ID (id).
     *
     * La propriété response_data est désérialisée automatiquement.
     * La propriété data_sent est désérialisée automatiquement.
     *
     * @param int $id ID de l'enregistrement.
     * @return object|null
     */
    public static function get_by_id(int $id): ?object {
        global $wpdb;

        $table_name = self::get_table_name();

        $row = $wpdb->get_row(
            $wpdb->prepare(
                "SELECT * FROM {$table_name} WHERE id = %d LIMIT 1",
                $id
            )
        );

        if (!$row) {
            return null;
        }

        // Désérialiser la réponse API et le payload si nécessaire
        if (isset($row->response_data)) {
            $row->response_data = \maybe_unserialize($row->response_data);
        }
        if (isset($row->data_sent)) {
            $row->data_sent = \maybe_unserialize($row->data_sent);
        }

        return $row;
    }
}