<?php

namespace Kylin\Payment\Services;

use Kylin\Payment\Models\PaymentCallbackLog;
use Illuminate\Http\Request;
use Illuminate\Contracts\Container\Container;
use Illuminate\Pagination\LengthAwarePaginator;
use Carbon\Carbon;

/**
 * 支付回调日志服务
 */
class PaymentCallbackLogService
{
    /**
     * 构造函数
     */
    public function __construct(
        protected readonly Container $app
    ) {
    }

    /**
     * 创建回调日志
     */
    public function createFromRequest(Request $request, string $paymentType, string $outTradeNo = '', string $tradeNo = ''): PaymentCallbackLog
    {
        return PaymentCallbackLog::create([
            'payment_type' => $paymentType,
            'out_trade_no' => $outTradeNo,
            'trade_no' => $tradeNo,
            'method' => $request->method(),
            'uri' => $request->fullUrl(),
            'headers' => $this->getHeaders($request),
            'query' => $request->query(),
            'body' => $request->getContent(),
            'ip' => $request->ip(),
            'user_agent' => $request->userAgent(),
        ]);
    }

    /**
     * 创建回调日志（手动）
     */
    public function create(array $data): PaymentCallbackLog
    {
        return PaymentCallbackLog::create([
            'payment_type' => $data['payment_type'],
            'out_trade_no' => $data['out_trade_no'] ?? '',
            'trade_no' => $data['trade_no'] ?? '',
            'method' => $data['method'] ?? 'POST',
            'uri' => $data['uri'] ?? '',
            'headers' => $data['headers'] ?? [],
            'query' => $data['query'] ?? [],
            'body' => $data['body'] ?? '',
            'ip' => $data['ip'] ?? '',
            'user_agent' => $data['user_agent'] ?? '',
        ]);
    }

    /**
     * 根据ID获取回调日志
     */
    public function getById(int $id): ?PaymentCallbackLog
    {
        return PaymentCallbackLog::find($id);
    }

    /**
     * 根据商户订单号获取回调日志
     */
    public function getByOutTradeNo(string $outTradeNo, ?string $paymentType = null): ?PaymentCallbackLog
    {
        return PaymentCallbackLog::findByOutTradeNo($outTradeNo, $paymentType);
    }

    /**
     * 根据支付平台订单号获取回调日志
     */
    public function getByTradeNo(string $tradeNo, ?string $paymentType = null): ?PaymentCallbackLog
    {
        return PaymentCallbackLog::findByTradeNo($tradeNo, $paymentType);
    }

    /**
     * 标记为处理成功
     */
    public function markAsSuccess(int $id, array $response = [], int $processingTime = 0): bool
    {
        $log = $this->getById($id);
        return $log?->markAsSuccess($response, $processingTime) ?? false;
    }

    /**
     * 标记为处理失败
     */
    public function markAsFailed(int $id, string $errorMessage = '', int $processingTime = 0): bool
    {
        $log = $this->getById($id);
        return $log?->markAsFailed($errorMessage, $processingTime) ?? false;
    }

    /**
     * 获取回调日志列表
     */
    public function getList(array $where = [], array $order = ['created_at' => 'desc'], int $page = 1, int $limit = 20): LengthAwarePaginator
    {
        $query = PaymentCallbackLog::query();

        // 构建查询条件
        foreach ($where as $key => $value) {
            if (is_array($value)) {
                $query->whereIn($key, $value);
            } else {
                $query->where($key, $value);
            }
        }

        // 构建排序
        foreach ($order as $key => $value) {
            $query->orderBy($key, $value);
        }

        // 分页查询
        return $query->paginate($limit, ['*'], 'page', $page);
    }

    /**
     * 获取回调统计数据
     */
    public function getStatistics(array $where = []): array
    {
        $query = PaymentCallbackLog::query();

        // 构建查询条件
        foreach ($where as $key => $value) {
            if (is_array($value)) {
                $query->whereIn($key, $value);
            } else {
                $query->where($key, $value);
            }
        }

        // 统计数据
        $totalCount = $query->count();
        $successCount = $query->where('status', PaymentCallbackLog::STATUS_SUCCESS)->count();
        $failedCount = $query->where('status', PaymentCallbackLog::STATUS_FAILED)->count();
        $pendingCount = $query->where('status', PaymentCallbackLog::STATUS_PENDING)->count();

        // 统计处理时间
        $avgProcessingTime = $query->where('processing_time', '>', 0)->avg('processing_time') ?? 0;
        $maxProcessingTime = $query->where('processing_time', '>', 0)->max('processing_time') ?? 0;
        $minProcessingTime = $query->where('processing_time', '>', 0)->min('processing_time') ?? 0;

        return [
            'total_count' => $totalCount,
            'success_count' => $successCount,
            'failed_count' => $failedCount,
            'pending_count' => $pendingCount,
            'success_rate' => $totalCount > 0 ? round(($successCount / $totalCount) * 100, 2) : 0,
            'avg_processing_time' => round($avgProcessingTime, 2),
            'max_processing_time' => $maxProcessingTime,
            'min_processing_time' => $minProcessingTime,
        ];
    }

    /**
     * 删除回调日志
     */
    public function delete(int $id): bool
    {
        $log = $this->getById($id);
        return $log?->delete() ?? false;
    }

    /**
     * 批量删除回调日志
     */
    public function batchDelete(array $ids): int
    {
        return PaymentCallbackLog::whereIn('id', $ids)->delete();
    }

    /**
     * 清理过期的回调日志
     */
    public function cleanExpired(int $days = 30): int
    {
        return PaymentCallbackLog::where('created_at', '<', Carbon::now()->subDays($days))->delete();
    }

    /**
     * 获取请求头
     */
    protected function getHeaders(Request $request): array
    {
        $headers = [];
        foreach ($request->headers->all() as $name => $value) {
            $headers[$name] = $value[0];
        }
        return $headers;
    }
}
