<?php

if (!defined('ABSPATH')) {
    exit;
}

/*----------------------------------------
メール送信履歴テーブル名を取得
----------------------------------------*/
function immf_mail_logs_table_name() {

    global $wpdb;

    return $wpdb->prefix . 'im_mail_form_logs';

}


/*----------------------------------------
メール送信履歴テーブルが実在するか確認
----------------------------------------*/
function immf_mail_logs_table_exists() {

    global $wpdb;

    $table_name = immf_mail_logs_table_name();

    // テーブルの実在確認のための直接クエリ。テーブル名はesc_like()で
    // ワイルドカード文字をエスケープした上でプレースホルダーへ渡す。
    // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching
    $found_table_name = $wpdb->get_var(
        $wpdb->prepare(
            'SHOW TABLES LIKE %s',
            $wpdb->esc_like($table_name)
        )
    );

    return $found_table_name === $table_name;

}


/*----------------------------------------
メール送信履歴テーブルを作成・更新
----------------------------------------*/
function immf_create_mail_logs_table() {

    global $wpdb;

    $table_name = immf_mail_logs_table_name();

    $charset_collate = $wpdb->get_charset_collate();

    $sql = "CREATE TABLE $table_name (
        id bigint(20) unsigned NOT NULL AUTO_INCREMENT,
        form_post_id bigint(20) unsigned NOT NULL,
        form_title varchar(255) NOT NULL DEFAULT '',
        form_id varchar(191) NOT NULL DEFAULT '',
        sent_at_gmt datetime NOT NULL,
        ip_address varchar(45) NOT NULL DEFAULT '',
        admin_status varchar(20) NOT NULL DEFAULT '',
        admin_to varchar(255) NOT NULL DEFAULT '',
        admin_cc text NOT NULL,
        admin_bcc text NOT NULL,
        reply_status varchar(20) NOT NULL DEFAULT '',
        reply_skip_reason varchar(20) NOT NULL DEFAULT '',
        reply_to varchar(255) NOT NULL DEFAULT '',
        reply_bcc text NOT NULL,
        PRIMARY KEY  (id),
        KEY sent_at_gmt (sent_at_gmt),
        KEY form_post_id (form_post_id),
        KEY form_id (form_id)
    ) $charset_collate;";

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

    dbDelta($sql);

    /*
    * テーブルの実在を確認できた場合だけDBバージョンを更新します。
    * 作成・更新に失敗した場合はバージョンを進めず、次回の
    * plugins_loadedで再度dbDelta()を試みられるようにします。
    */
    if (!immf_mail_logs_table_exists()) {
        return false;
    }

    update_option(
        'immf_db_version',
        IMMF_DB_VERSION
    );

    return true;

}


/*----------------------------------------
90日削除Cronを未登録の場合だけ予約
----------------------------------------*/
function immf_schedule_mail_logs_cleanup_cron() {

    if (
        !wp_next_scheduled(
            'immf_cleanup_mail_logs'
        )
    ) {
        wp_schedule_event(
            time(),
            'daily',
            'immf_cleanup_mail_logs'
        );
    }

}


/*----------------------------------------
DBバージョンを確認し、必要な場合だけテーブルを更新
----------------------------------------*/
function immf_maybe_upgrade_mail_logs_db() {

    $installed_version = get_option(
        'immf_db_version',
        ''
    );

    if ($installed_version !== IMMF_DB_VERSION) {
        immf_create_mail_logs_table();
    }

    /*
    * DBバージョンが一致している場合でも、Cronの登録状態は
    * 毎回確認します。wp_next_scheduled()はcronオプション
    * （自動読み込み済み）を参照するだけの軽量な確認であり、
    * 何らかの理由でCronだけが失われた場合の自動復旧になります。
    */
    immf_schedule_mail_logs_cleanup_cron();

}

add_action(
    'plugins_loaded',
    'immf_maybe_upgrade_mail_logs_db'
);


/*----------------------------------------
現在のサイトにテーブル作成とCron予約を行う
----------------------------------------*/
function immf_activate_mail_logs_for_site() {

    immf_create_mail_logs_table();

    immf_schedule_mail_logs_cleanup_cron();

}


/*----------------------------------------
プラグイン有効化時の処理
----------------------------------------*/
function immf_activate_mail_logs($network_wide = false) {

    if (is_multisite() && $network_wide) {

        $site_ids = get_sites([
            'fields' => 'ids',
            'number' => 0,
        ]);

        foreach ($site_ids as $site_id) {

            switch_to_blog($site_id);

            immf_activate_mail_logs_for_site();

            restore_current_blog();
        }

        return;
    }

    immf_activate_mail_logs_for_site();

}


/*----------------------------------------
プラグイン無効化時の処理
----------------------------------------*/
function immf_deactivate_mail_logs($network_wide = false) {

    if (is_multisite() && $network_wide) {

        $site_ids = get_sites([
            'fields' => 'ids',
            'number' => 0,
        ]);

        foreach ($site_ids as $site_id) {

            switch_to_blog($site_id);

            wp_clear_scheduled_hook(
                'immf_cleanup_mail_logs'
            );

            restore_current_blog();
        }

        return;
    }

    wp_clear_scheduled_hook(
        'immf_cleanup_mail_logs'
    );

}


/*----------------------------------------
90日を超えたメール送信履歴を削除
----------------------------------------*/
function immf_cleanup_mail_logs() {

    global $wpdb;

    $table_name = immf_mail_logs_table_name();

    $threshold_gmt = gmdate(
        'Y-m-d H:i:s',
        time() - (90 * DAY_IN_SECONDS)
    );

    // 保存期間(90日)を超えた履歴を削除するための直接クエリ。
    // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching
    $wpdb->query(
        $wpdb->prepare(
            "DELETE FROM %i
            WHERE sent_at_gmt < %s",
            $table_name,
            $threshold_gmt
        )
    );

}

add_action(
    'immf_cleanup_mail_logs',
    'immf_cleanup_mail_logs'
);


/*----------------------------------------
メール送信履歴を1件保存
----------------------------------------*/
function immf_insert_mail_log($log_data) {

    global $wpdb;

    // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery -- Inserting mail log data into the plugin's custom table.
    $wpdb->insert(
        immf_mail_logs_table_name(),
        [
            'form_post_id'      => absint(
                $log_data['form_post_id'] ?? 0
            ),
            'form_title'        => sanitize_text_field(
                $log_data['form_title'] ?? ''
            ),
            'form_id'           => sanitize_key(
                $log_data['form_id'] ?? ''
            ),
            'sent_at_gmt'       => sanitize_text_field(
                $log_data['sent_at_gmt'] ?? ''
            ),
            'ip_address'        => sanitize_text_field(
                $log_data['ip_address'] ?? ''
            ),
            'admin_status'      => sanitize_key(
                $log_data['admin_status'] ?? ''
            ),
            'admin_to'          => sanitize_text_field(
                $log_data['admin_to'] ?? ''
            ),
            'admin_cc'          => sanitize_text_field(
                $log_data['admin_cc'] ?? ''
            ),
            'admin_bcc'         => sanitize_text_field(
                $log_data['admin_bcc'] ?? ''
            ),
            'reply_status'      => sanitize_key(
                $log_data['reply_status'] ?? ''
            ),
            'reply_skip_reason' => sanitize_key(
                $log_data['reply_skip_reason'] ?? ''
            ),
            'reply_to'          => sanitize_text_field(
                $log_data['reply_to'] ?? ''
            ),
            'reply_bcc'         => sanitize_text_field(
                $log_data['reply_bcc'] ?? ''
            ),
        ],
        [
            '%d',
            '%s',
            '%s',
            '%s',
            '%s',
            '%s',
            '%s',
            '%s',
            '%s',
            '%s',
            '%s',
            '%s',
            '%s',
        ]
    );

}


/*----------------------------------------
メール送信履歴を新しい順に取得
----------------------------------------*/
function immf_get_mail_logs(
    $limit = 50,
    $offset = 0
) {

    global $wpdb;

    $table_name = immf_mail_logs_table_name();

    $limit = absint($limit);
    $offset = absint($offset);

    // 一覧取得のための直接クエリ。
    // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching
    $logs = $wpdb->get_results(
        $wpdb->prepare(
            "SELECT * FROM %i
            ORDER BY sent_at_gmt DESC, id DESC
            LIMIT %d OFFSET %d",
            $table_name,
            $limit,
            $offset
        ),
        ARRAY_A
    );

    if (!is_array($logs)) {
        return [];
    }

    return $logs;

}


/*----------------------------------------
メール送信履歴を1件取得
----------------------------------------*/
function immf_get_mail_log($id) {

    global $wpdb;

    $table_name = immf_mail_logs_table_name();

    $id = absint($id);

    if ($id === 0) {
        return null;
    }

    // 詳細画面用の1件取得のための直接クエリ。
    // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching
    $log = $wpdb->get_row(
        $wpdb->prepare(
            'SELECT * FROM %i WHERE id = %d',
            $table_name,
            $id
        ),
        ARRAY_A
    );

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

    return $log;

}


/*----------------------------------------
メール送信履歴の総件数を取得
----------------------------------------*/
function immf_get_mail_logs_count() {

    global $wpdb;

    $table_name = immf_mail_logs_table_name();

    // 総件数取得のための直接クエリ。
    // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching
    $count = $wpdb->get_var(
        $wpdb->prepare(
            'SELECT COUNT(*) FROM %i',
            $table_name
        )
    );

    return absint($count);

}
