<?php
namespace BLR\Backline\Core;

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

final class Sanitizer {
    public static function single_line($value): string {
        return sanitize_text_field((string) $value);
    }

    public static function rich_text($value): string {
        return wp_kses_post((string) $value);
    }

    public static function email($value): string {
        return sanitize_email((string) $value);
    }

    public static function url($value): string {
        return esc_url_raw((string) $value);
    }

    public static function absint_value($value): int {
        return absint($value);
    }

    public static function datetime_ymd_hi($value): string {
        return self::exact_date_format($value, 'Y-m-d H:i');
    }

    public static function date_ymd($value): string {
        return self::exact_date_format($value, 'Y-m-d');
    }

    public static function time_hi($value): string {
        return self::exact_date_format($value, 'H:i');
    }

    private static function exact_date_format($value, string $format): string {
        $value = trim((string) $value);
        if ($value === '') {
            return '';
        }

        $date = \DateTimeImmutable::createFromFormat('!' . $format, $value, wp_timezone());
        if (!$date instanceof \DateTimeImmutable) {
            return '';
        }

        $errors = \DateTimeImmutable::getLastErrors();
        if (is_array($errors) && (((int) ($errors['warning_count'] ?? 0)) > 0 || ((int) ($errors['error_count'] ?? 0)) > 0)) {
            return '';
        }

        return $date->format($format) === $value ? $value : '';
    }

    public static function csv_ids($value): string {
        $items = is_array($value) ? $value : preg_split('/[\s,]+/', (string) $value);
        if (!is_array($items)) {
            return '';
        }

        $out = [];
        foreach ($items as $item) {
            $id = absint($item);
            if ($id > 0) {
                $out[] = $id;
            }
        }

        $out = array_values(array_unique($out));
        return implode(',', $out);
    }

    public static function id_array($value): array {
        if (!is_array($value)) {
            return [];
        }

        $out = [];
        foreach ($value as $item) {
            $id = absint($item);
            if ($id > 0) {
                $out[] = $id;
            }
        }

        return array_values(array_unique($out));
    }

    public static function bool_string($value): string {
        return empty($value) ? '0' : '1';
    }

    public static function contact_filters_json($value): string {
        if (is_string($value)) {
            $decoded = json_decode($value, true);
        } elseif (is_array($value)) {
            $decoded = $value;
        } else {
            $decoded = null;
        }

        if (!is_array($decoded)) {
            return wp_json_encode([
                'contact_type' => [],
                'state' => [],
                'company' => [],
                'role' => [],
                'newsletter_only' => false,
                'has_email' => true,
            ]);
        }

        $clean_list = static function ($items): array {
            $items = is_array($items) ? $items : [$items];
            $out = [];
            foreach ($items as $item) {
                $item = sanitize_text_field((string) $item);
                if ($item !== '') {
                    $out[] = $item;
                }
            }
            $out = array_values(array_unique($out));
            natcasesort($out);
            return array_values($out);
        };

        return wp_json_encode([
            'contact_type' => $clean_list($decoded['contact_type'] ?? []),
            'state' => $clean_list($decoded['state'] ?? []),
            'company' => $clean_list($decoded['company'] ?? []),
            'role' => $clean_list($decoded['role'] ?? []),
            'newsletter_only' => !empty($decoded['newsletter_only']),
            'has_email' => !isset($decoded['has_email']) || !empty($decoded['has_email']),
        ]);
    }

    public static function header_text($value): string {
        $value = wp_strip_all_tags((string) $value, true);
        $value = preg_replace('/[\r\n:]+/', ' ', (string) $value);
        $value = str_replace(["\0", '<', '>', '"'], '', (string) $value);
        $value = preg_replace('/\s+/', ' ', (string) $value);
        return trim((string) $value);
    }

    public static function meta_value(string $key, $value, string $type = 'string') {
        if ($type === 'integer' || $type === 'number') {
            return self::absint_value($value);
        }

        if ($key === 'blr_contact_newsletter_signup') {
            return self::bool_string($value);
        }

        if (in_array($key, ['blr_outreach_attachment_ids', 'blr_outreach_visual_ids', 'blr_outreach_manual_contact_ids'], true)) {
            return self::csv_ids($value);
        }

        if ($key === 'blr_outreach_filter_payload') {
            return self::contact_filters_json($value);
        }

        if (strpos($key, '_email') !== false || strpos($key, 'reply_to') !== false) {
            return self::email($value);
        }

        if (strpos($key, '_url') !== false || strpos($key, '_website') !== false) {
            return self::url($value);
        }

        if (in_array($key, [
            'blr_contact_notes',
            'blr_description_short',
            'blr_credits',
            'blr_release_notes',
            'blr_lyrics',
            'blr_notes',
            'blr_outreach_log_note',
            'blr_outreach_log_error',
        ], true)) {
            return self::rich_text($value);
        }

        if (strpos($key, '_filename') !== false) {
            return sanitize_file_name((string) $value);
        }

        return self::single_line($value);
    }
}
