<?php

namespace SEOAIC\traits;

trait WPDB
{
    public function createIfNotExistsTable($tableName = '', $columns = '')
    {
        if (
            empty($tableName)
            || empty($columns)
        ) {
            return false;
        }

        // THE FIX: Don't load upgrade if table exists
        if ($this->existsTable($tableName)) {
            return true;
        }

        require_once(ABSPATH . 'wp-admin/includes/upgrade.php');

        $sql = "CREATE TABLE $tableName ($columns);";

        return maybe_create_table($tableName, $sql);
    }

    public function truncateTable($tableName = '')
    {
        global $wpdb;

        if (empty($tableName)) {
            return false;
        }

        $preparedQuery = $wpdb->prepare("SHOW TABLES LIKE %s", $wpdb->esc_like($tableName));
        $tableExists = $wpdb->get_var($preparedQuery) === $tableName;

        if ($tableExists) {
            $preparedQueryTruncate = $wpdb->prepare("TRUNCATE TABLE %i", $tableName);
            $wpdb->query($preparedQueryTruncate);

            return true;
        }

        return false;
    }

    public function dropTable($tableName = '')
    {
        global $wpdb;

        if (empty($tableName)) {
            return false;
        }

        $preparedQuery = $wpdb->prepare("DROP TABLE IF EXISTS %i", $tableName);
        $wpdb->query($preparedQuery);

        return true;
    }

    public function existsTable($tableName = '')
    {
        global $wpdb;

        if (empty($tableName)) {
            return false;
        }

        $preparedQuery = $wpdb->prepare("SHOW TABLES LIKE '%s'", [$tableName]);
        $result = $wpdb->get_var($preparedQuery);

        if (
            is_wp_error($result)
            || is_null( $result)
        ) {
            return false;
        }

        return $tableName == $result;
    }

    public function migrateTableData($fromTable, $toTable)
    {
        global $wpdb;

        $fromTableExists = $this->existsTable($fromTable);
        $toTableExists = $this->existsTable($toTable);

        if (
            $fromTableExists
            && $toTableExists
        ) {
            $result = $wpdb->query("INSERT INTO {$toTable} SELECT * FROM {$fromTable}");

            return 0 !== $result;
        }

        return false;
    }


    public function getAll($tableName)
    {
        global $wpdb;

        return $wpdb->get_results(
            $wpdb->prepare(
                "SELECT * FROM %i",
                [$tableName]
            )
        );
    }

    public function getById(string $tableName, int $id)
    {
        global $wpdb;

        return $wpdb->get_row(
            $wpdb->prepare(
                "SELECT * FROM %i WHERE id=%d",
                [$tableName, $id],
            )
        );
    }

    public function getByField(string $tableName, string $fieldName, $value)
    {
        global $wpdb;

        $valueType = is_numeric($value) ? '%d' : '%s';

        return $wpdb->get_results(
            $wpdb->prepare(
                "SELECT * FROM %i WHERE %i=" . $valueType,
                [$tableName, $fieldName, $value],
            )
        );
    }

    public function insert($tableName, $data = [])
    {
        global $wpdb;

        if (
            empty($tableName)
            || empty($data)
        ) {
            return false;
        }

        $format = [];
        foreach ($data as $field => $value) {
            if (is_numeric($value)) {
                $format[] = '%d';
            } else {
                $format[] = '%s';
            }
        }

        return $wpdb->insert($tableName, $data, $format) ? $wpdb->insert_id : false;
    }

    public function insertBulk($tableName, $fields = [], $data = [])
    {
        global $wpdb;

        if (
            empty($tableName)
            || empty($data)
        ) {
            return false;
        }

        $escapedFields = array_map(function ($field) {
            return esc_sql($field);
        }, $fields);
        $query = "INSERT INTO " . esc_sql($tableName) . " (" . implode(', ', $escapedFields) . ") VALUES ";
        $values = [];
        $placeholders = [];

        foreach ($data as $row) {
            $placeholderStr = "(";
            $formatArr = [];

            foreach ($row as $value) {
                if (is_numeric($value)) {
                    $format = '%d';
                } else {
                    $format = '%s';
                }

                $formatArr[] = $format;
                $values[] = $value;
            }

            $placeholderStr .= implode(',', $formatArr) . ")";
            $placeholders[] = $placeholderStr;
        }

        $query .= implode(', ', $placeholders);
        $wpdb->query($wpdb->prepare($query, $values));
    }

    public function update($tableName, array $data, array $where = [])
    {
        global $wpdb;

        $format = [];
        $whereFormat = [];

        foreach ($data as $field => $value) {
            if (is_numeric($value)) {
                $format[] = '%d';
            } else {
                $format[] = '%s';
            }
        }

        foreach ($where as $whereField => $whereValue) {
            if (is_numeric($whereValue)) {
                $whereFormat[] = '%d';
            } else {
                $whereFormat[] = '%s';
            }
        }

        $result = $wpdb->update(
            $tableName,
            $data,
            $where,
            $format,
            $whereFormat
        );

        return false !== $result;
    }

    public function deleteAllByField(string $tableName, array $conditions)
    {
        global $wpdb;

        if (empty($conditions)) {
            return;
        }

        $whereFormat = [];

        foreach ($conditions as $key => $value) {
            $whereFormat[] = is_numeric($value) ? '%d' : '%s';
        }

        $wpdb->delete($tableName, $conditions, $whereFormat);
    }
}
