<?php

namespace WPSN\Modules\Redirects;

defined('ABSPATH') || exit;

/**
 * Stores redirect migration run summaries (so the report survives transient expiry).
 */
final class RedirectMigrationRunRepository
{
    private function tableName(): string
    {
        global $wpdb;
        return $wpdb->prefix . 'wpsn_redirect_migration_runs';
    }

    /**
     * @param array<string,mixed> $run
     */
    public function insert(array $run): bool
    {
        global $wpdb;

        $jobId = isset($run['job_id']) ? sanitize_text_field((string) $run['job_id']) : '';
        if ($jobId === '') {
            return false;
        }

        $data = [
            'job_id' => $jobId,
            'source' => isset($run['source']) ? sanitize_key((string) $run['source']) : '',
            'overwrite' => !empty($run['overwrite']) ? 1 : 0,
            'include_disabled' => !empty($run['include_disabled']) ? 1 : 0,
            'total' => (int) ($run['total'] ?? 0),
            'processed' => (int) ($run['processed'] ?? 0),
            'imported' => (int) ($run['imported'] ?? 0),
            'updated' => (int) ($run['updated'] ?? 0),
            'skipped' => (int) ($run['skipped'] ?? 0),
            'unsupported' => (int) ($run['unsupported'] ?? 0),
            'disabled' => (int) ($run['disabled'] ?? 0),
            'errors' => (int) ($run['errors'] ?? 0),
            'last_error' => isset($run['last_error']) ? sanitize_text_field((string) $run['last_error']) : '',
            'started_at' => isset($run['started_at']) ? (string) $run['started_at'] : current_time('mysql'),
            'finished_at' => isset($run['finished_at']) ? (string) $run['finished_at'] : null,
        ];

        $formats = [
            '%s', '%s',
            '%d', '%d',
            '%d', '%d',
            '%d', '%d',
            '%d', '%d',
            '%d', '%d',
            '%d', '%s',
            '%s', '%s',
        ];

        $table = $this->tableName();

        $ok = $wpdb->replace($table, $data, $formats);
        return $ok !== false;
    }

    /**
     * @param array<string,mixed> $fields
     */
    public function update(string $jobId, array $fields): bool
    {
        global $wpdb;

        $jobId = sanitize_text_field($jobId);
        if ($jobId === '') {
            return false;
        }

        $allowed = [
            'processed', 'total', 'imported', 'updated', 'skipped', 'unsupported', 'disabled', 'errors',
            'last_error', 'finished_at',
        ];

        $data = [];
        $formats = [];

        foreach ($allowed as $k) {
            if (!array_key_exists($k, $fields)) {
                continue;
            }

            if (in_array($k, ['last_error'], true)) {
                $data[$k] = sanitize_text_field((string) $fields[$k]);
                $formats[] = '%s';
                continue;
            }
            if (in_array($k, ['finished_at'], true)) {
                $data[$k] = $fields[$k] !== null ? (string) $fields[$k] : null;
                $formats[] = '%s';
                continue;
            }

            $data[$k] = (int) $fields[$k];
            $formats[] = '%d';
        }

        if (empty($data)) {
            return true;
        }

        $table = $this->tableName();
        $ok = $wpdb->update($table, $data, ['job_id' => $jobId], $formats, ['%s']);
        return $ok !== false;
    }

    /**
     * @return array<string,mixed>|null
     */
    public function get(string $jobId): ?array
    {
        global $wpdb;
        $jobId = sanitize_text_field($jobId);
        if ($jobId === '') {
            return null;
        }

        $table = $this->tableName();
        $sql = $wpdb->prepare("SELECT * FROM {$table} WHERE job_id = %s LIMIT 1", $jobId);
        $row = $wpdb->get_row($sql, ARRAY_A);
        return is_array($row) ? $row : null;
    }

    public function delete(string $jobId): int
    {
        global $wpdb;
        $jobId = sanitize_text_field($jobId);
        if ($jobId === '') {
            return 0;
        }

        $table = $this->tableName();
        $ok = $wpdb->delete($table, ['job_id' => $jobId], ['%s']);
        return $ok !== false ? (int) $ok : 0;
    }
}
