<?php

namespace Sibs\Stargate\Models;

use Sibs\Stargate\Loggers\SibsLogger;

if (!defined('ABSPATH')) {
    exit; // Prevent direct access
}

class SibsMultibancoDetails extends SibsModels
{
    /**
     * Sibs Transactions.
     *
     * @var SibsTransactions
     */
    protected $sibsTransactions;

    /**
     * Constructor.
     */
    public function __construct()
    {
        $this->sibsTransactions = new SibsTransactions();

        parent::__construct('multibanco_details', 'id');
    }

    /**
     * Get Table Name.
     */
    public function getTableName(): string
    {
        return $this->getModulePrefix().$this->table_name;
    }

    /**
     * Get Config Name.
     */
    public function getConfigName(): string
    {
        return 'CREATED_SIBS_DPG_MULTIBANCO_DETAIL_TABLE';
    }

    /**
     * Create Model.
     */
    public function create(): bool
    {
        $this->db->hide_errors();

        $table = $this->getTableName();
        $sibs_transactions_table = $this->sibsTransactions->getTableName();
        $charset_collate = $this->db->get_charset_collate();

        if ($this->table_exists()) {
            // Table exists, no need to create it again
            SibsLogger::debug("Table '{$table}' already exists, skipping creation.");

            return true;
        }

        SibsLogger::debug("Table '{$table}' not exists and will be created.");

        // Recuperar tipos reais das colunas referenciadas
        $sibs_transactions_id_type = $this->get_column_type($sibs_transactions_table, 'id') ?: 'BIGINT(20) UNSIGNED';

        $sql = "CREATE TABLE {$table} (
            `id` BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
            `sibs_transaction_id` {$sibs_transactions_id_type} NOT NULL,
            `payment_entity` VARCHAR(50) NOT NULL,
            `payment_reference` VARCHAR(50) NOT NULL,
            `payment_value` DECIMAL(17,2) NOT NULL,
            `payment_ref_expiration_date` DATETIME NOT NULL /* ,
            FOREIGN KEY (`sibs_transaction_id`) REFERENCES `{$sibs_transactions_table}`(`id`) */
        ) {$charset_collate};";

        SibsLogger::debug("dbDelta will execute: {$sql}");

        $result = dbDelta($sql);

        if (!empty($this->db->last_error)) {
            $this->logDbError("Failed to create table {$table}", ['result' => $result]);

            return false;
        }

        if (empty($result)) {
            SibsLogger::warning("dbDelta returned no changes for table {$table}");
        } else {
            SibsLogger::debug("dbDelta executed for table {$table} - ", [
                'changes' => $result,
            ]);
        }

        return $this->is_table_created($result, $table);
    }

    /**
     * Migrate Model.
     */
    public function migrate(string $installedVersion): bool
    {
        return true;
    }

    /**
     * Check.
     */
    public function check(bool $suppressLog = false): bool
    {
        $this->setSuppressLog($suppressLog);

        $table = $this->getTableName();
        $sibs_transactions_table = $this->sibsTransactions->getTableName();
        $sibs_transactions_id_type = $this->get_column_type($sibs_transactions_table, 'id') ?: 'BIGINT(20) UNSIGNED';

        return $this->health_check(
            $table,
            // Expected columns
            [
                'id' => 'BIGINT(20) UNSIGNED',
                'sibs_transaction_id' => $sibs_transactions_id_type,
                'payment_entity' => 'VARCHAR(50)',
                'payment_reference' => 'VARCHAR(50)',
                'payment_value' => 'DECIMAL(17,2)',
                'payment_ref_expiration_date' => 'DATETIME',
            ],
            // Indexes
            [],
            // Foreign keys
            [
                // 'fk_sibs_transaction' => ['column' => 'sibs_transaction_id', 'referenced_table' => $sibs_transactions_table, 'referenced_column' => 'id'],
            ]
        );
    }

    /**
     * Get By SIBS Transaction Id.
     *
     * @param int  $sibs_transaction_id
     * @param bool $all
     *
     * @return null|array|object
     */
    public function getBySibsTransactionId($sibs_transaction_id, $all = false)
    {
        if ($all) {
            return $this->get_all([
                'sibs_transaction_id' => $sibs_transaction_id,
            ], 'id', 'DESC');
        }

        return $this->get_by('sibs_transaction_id', $sibs_transaction_id);
    }

    /**
     * Upsert Multibanco.
     *
     * @return false|int
     *
     * @throws \PDOException
     */
    public function upsertMultibanco(array $data, array $where = [])
    {
        $multibancoDetailsUpserted = $this->upsert(
            $this->processDataOrWhere($data),
            $this->processDataOrWhere($where)
        );

        $params = [
            'data' => $data,
            'where' => $where,
        ];

        if (false === $multibancoDetailsUpserted) {
            throw new \PDOException('Multibanco Details was not upserted: '.SibsLogger::prettify($params));
        }
        SibsLogger::debug('Multibanco Details upserted', [
            'params' => $params,
        ]);

        return $multibancoDetailsUpserted;
    }

    /**
     * Update Multibanco.
     *
     * @return false|int
     *
     * @throws \PDOException
     */
    public function updateMultibanco(array $data, array $where = [])
    {
        $multibancoDetailsUpdated = $this->update(
            $this->processDataOrWhere($data),
            $this->processDataOrWhere($where)
        );

        $params = [
            'data' => $data,
            'where' => $where,
        ];

        if (false === $multibancoDetailsUpdated) {
            throw new \PDOException('Multibanco Details was not updated: '.SibsLogger::prettify($params));
        }
        SibsLogger::debug('Multibanco Details updated', [
            'params' => $params,
        ]);

        return $multibancoDetailsUpdated;
    }

    /**
     * Save Multibanco.
     *
     * @return false|int
     *
     * @throws \PDOException
     */
    public function saveMultibanco(array $data, array $where = [])
    {
        $multibancoDetailsSaved = $this->insert(
            $this->processDataOrWhere($data),
            $this->processDataOrWhere($where)
        );

        $params = [
            'data' => $data,
            'where' => $where,
        ];

        if (false === $multibancoDetailsSaved) {
            throw new \PDOException('Multibanco Details was not saved: '.SibsLogger::prettify($params));
        }
        SibsLogger::debug('Multibanco Details saved', [
            'params' => $params,
        ]);

        return $multibancoDetailsSaved;
    }

    /**
     * Update Or Save Data.
     *
     * @return array
     */
    protected function processDataOrWhere(array $data)
    {
        $updateOrSaveData = [];

        if (!empty($data['sibs_transaction_id'])) {
            $updateOrSaveData['sibs_transaction_id'] = $data['sibs_transaction_id'];
        }

        if (!empty($data['payment_entity'])) {
            $updateOrSaveData['payment_entity'] = $data['payment_entity'];
        }

        if (!empty($data['payment_reference'])) {
            $updateOrSaveData['payment_reference'] = $data['payment_reference'];
        }

        if (!empty($data['payment_value'])) {
            $updateOrSaveData['payment_value'] = $data['payment_value'];
        }

        if (!empty($data['payment_ref_expiration_date'])) {
            $updateOrSaveData['payment_ref_expiration_date'] = $data['payment_ref_expiration_date'];
        }

        return $updateOrSaveData;
    }
}
