<?php

namespace Kylin\Payment\Services;

use Illuminate\Support\Str;
use Illuminate\Contracts\Container\Container;

/**
 * 支付数据脱敏服务类
 */
class PaymentDataMaskingService
{
    /**
     * 默认脱敏配置
     */
    const DEFAULT_MASKING_CONFIG = [
        'card_number' => [
            'pattern' => '/(\d{4})\d{0,12}(\d{4})/',
            'replacement' => '$1****$2',
        ],
        'phone' => [
            'pattern' => '/(\d{3})\d{0,4}(\d{4})/',
            'replacement' => '$1****$2',
        ],
        'email' => [
            'pattern' => '/(\w{1,3})\w{0,}(@\w+)/',
            'replacement' => '$1****$2',
        ],
        'id_card' => [
            'pattern' => '/(\d{6})\d{0,8}(\d{4})/',
            'replacement' => '$1****$2',
        ],
        'name' => [
            'pattern' => '/(.).*/',
            'replacement' => '$1**',
        ],
    ];

    /**
     * 构造函数
     */
    public function __construct(
        protected readonly Container $app,
        protected array $config = []
    ) {
        $this->config = array_merge(self::DEFAULT_MASKING_CONFIG, $config);
    }

    /**
     * 脱敏卡卡号
     */
    public function maskCardNumber(?string $cardNumber): ?string
    {
        if (empty($cardNumber)) {
            return $cardNumber;
        }

        $config = $this->config['card_number'];
        return preg_replace($config['pattern'], $config['replacement'], $cardNumber);
    }

    /**
     * 脱敏手机号
     */
    public function maskPhone(?string $phone): ?string
    {
        if (empty($phone)) {
            return $phone;
        }

        $config = $this->config['phone'];
        return preg_replace($config['pattern'], $config['replacement'], $phone);
    }

    /**
     * 脱敏邮箱
     */
    public function maskEmail(?string $email): ?string
    {
        if (empty($email)) {
            return $email;
        }

        $config = $this->config['email'];
        return preg_replace($config['pattern'], $config['replacement'], $email);
    }

    /**
     * 脱敏身份证号
     */
    public function maskIdCard(?string $idCard): ?string
    {
        if (empty($idCard)) {
            return $idCard;
        }

        $config = $this->config['id_card'];
        return preg_replace($config['pattern'], $config['replacement'], $idCard);
    }

    /**
     * 脱敏姓名
     */
    public function maskName(?string $name): ?string
    {
        if (empty($name)) {
            return $name;
        }

        $config = $this->config['name'];
        return preg_replace($config['pattern'], $config['replacement'], $name);
    }

    /**
     * 脱敏支付参数
     */
    public function maskPaymentParams(array $params, array $fields = []): array
    {
        $maskedParams = $params;

        // 自动检测需要脱敏的字段
        if (empty($fields)) {
            $fields = $this->detectSensitiveFields($params);
        }

        foreach ($fields as $field) {
            if (isset($maskedParams[$field])) {
                $maskedParams[$field] = $this->maskField($field, $maskedParams[$field]);
            }
        }

        return $maskedParams;
    }

    /**
     * 脱敏指定字段
     */
    public function maskField(string $field, mixed $value): mixed
    {
        if (is_array($value)) {
            return $this->maskPaymentParams($value);
        }

        if (!is_string($value)) {
            return $value;
        }

        $field = strtolower($field);

        return match (true) {
            str_contains($field, 'card') || str_contains($field, 'number') => $this->maskCardNumber($value),
            str_contains($field, 'phone') || str_contains($field, 'mobile') => $this->maskPhone($value),
            str_contains($field, 'email') => $this->maskEmail($value),
            str_contains($field, 'id') && str_contains($field, 'card') => $this->maskIdCard($value),
            str_contains($field, 'name') || str_contains($field, 'user') => $this->maskName($value),
            default => $value,
        };
    }

    /**
     * 检测敏感字段
     */
    protected function detectSensitiveFields(array $params): array
    {
        $sensitiveFields = [];
        $keywords = [
            'card', 'number', 'phone', 'mobile', 'email', 'id_card', 'name', 'user',
        ];

        foreach ($params as $key => $value) {
            $key = strtolower($key);
            foreach ($keywords as $keyword) {
                if (str_contains($key, $keyword)) {
                    $sensitiveFields[] = $key;
                    break;
                }
            }

            if (is_array($value)) {
                $nestedFields = $this->detectSensitiveFields($value);
                foreach ($nestedFields as $nestedField) {
                    $sensitiveFields[] = "{$key}.{$nestedField}";
                }
            }
        }

        return $sensitiveFields;
    }

    /**
     * 脱敏支付记录
     */
    public function maskPaymentRecord(array $record): array
    {
        $maskedRecord = $record;

        // 脱敏payload字段
        if (isset($maskedRecord['payload'])) {
            $payload = is_string($maskedRecord['payload']) ? json_decode($maskedRecord['payload'], true) : $maskedRecord['payload'];
            if (is_array($payload)) {
                $maskedRecord['payload'] = $this->maskPaymentParams($payload);
            }
        }

        // 脱敏其他可能的敏感字段
        $sensitiveFields = ['card_number', 'phone', 'email', 'id_card', 'name'];
        foreach ($sensitiveFields as $field) {
            if (isset($maskedRecord[$field])) {
                $maskedRecord[$field] = $this->maskField($field, $maskedRecord[$field]);
            }
        }

        return $maskedRecord;
    }

    /**
     * 脱敏回调日志
     */
    public function maskCallbackLog(array $log): array
    {
        $maskedLog = $log;

        // 脱敏请求体
        if (isset($maskedLog['body'])) {
            $body = is_string($maskedLog['body']) ? json_decode($maskedLog['body'], true) : $maskedLog['body'];
            if (is_array($body)) {
                $maskedLog['body'] = $this->maskPaymentParams($body);
            }
        }

        // 脱敏响应体
        if (isset($maskedLog['response'])) {
            $response = is_string($maskedLog['response']) ? json_decode($maskedLog['response'], true) : $maskedLog['response'];
            if (is_array($response)) {
                $maskedLog['response'] = $this->maskPaymentParams($response);
            }
        }

        return $maskedLog;
    }

    /**
     * 自定义脱敏规则
     */
    public function maskWithCustomRule(string $pattern, string $replacement, ?string $value): ?string
    {
        if (empty($value)) {
            return $value;
        }

        return preg_replace($pattern, $replacement, $value);
    }

    /**
     * 获取脱敏配置
     */
    public function getConfig(): array
    {
        return $this->config;
    }

    /**
     * 设置脱敏配置
     */
    public function setConfig(array $config): self
    {
        $this->config = array_merge($this->config, $config);
        return $this;
    }
}
