<?php

namespace App\Http\Controllers\Admin;

use App\Http\Controllers\Concerns\ResolvesPlatformAdminContext;
use App\Http\Controllers\Controller;
use App\Models\SiteSubscription;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Http\Request;
use Illuminate\View\View;
use Symfony\Component\HttpFoundation\StreamedResponse;
use App\Models\PlatformOrder;

class SiteSubscriptionController extends Controller
{
    use ResolvesPlatformAdminContext;

    public function show(Request $request, SiteSubscription $subscription): View
    {
        $this->ensurePlatformAdmin($request);

        $subscription->loadMissing(['merchant', 'plan']);

        $baseOrdersQuery = PlatformOrder::query()
            ->where('site_subscription_id', $subscription->id);

        // 可治理摘要：订阅下的订单同步情况（基于全量关联订单，不受页面筛选影响）
        $summaryStats = [
            'total_orders' => (clone $baseOrdersQuery)->count(),
            'synced_orders' => (clone $baseOrdersQuery)
                ->whereRaw("JSON_EXTRACT(meta, '$.subscription_activation.subscription_id') IS NOT NULL")
                ->whereRaw("JSON_EXTRACT(meta, '$.subscription_activation_error.message') IS NULL")
                ->count(),
            'failed_orders' => (clone $baseOrdersQuery)
                ->whereRaw("JSON_EXTRACT(meta, '$.subscription_activation_error.message') IS NOT NULL")
                ->count(),
            'unsynced_orders' => (clone $baseOrdersQuery)
                ->whereRaw("JSON_EXTRACT(meta, '$.subscription_activation.subscription_id') IS NULL")
                ->whereRaw("JSON_EXTRACT(meta, '$.subscription_activation_error.message') IS NULL")
                ->count(),
            'syncable_orders' => (clone $baseOrdersQuery)
                ->where('payment_status', 'paid')
                ->where('status', 'activated')
                ->whereRaw("JSON_EXTRACT(meta, '$.subscription_activation.subscription_id') IS NULL")
                // 口径对齐平台订单页：可同步 = 未同步且非失败
                ->whereRaw("JSON_EXTRACT(meta, '$.subscription_activation_error.message') IS NULL")
                ->count(),
        ];

        // 可治理摘要：订阅维度的回执/退款汇总（口径与平台订单列表一致：优先 summary，缺省回退 receipts）
        $metaOrders = (clone $baseOrdersQuery)->get(['id', 'paid_amount', 'payment_status', 'meta']);

        $totalReceiptAmount = 0.0;
        $receiptOrders = 0;
        $noReceiptOrders = 0;

        $totalRefundedAmount = 0.0;
        $refundOrders = 0;
        $noRefundOrders = 0;

        // 订阅维度：退款不一致订单数（与平台订单列表 refund_inconsistent 口径保持一致）
        $refundInconsistentOrders = 0;

        // 订阅维度：对账不一致订单数（与平台订单列表 reconcile_mismatch 口径保持一致）
        $reconcileMismatchOrders = 0;

        foreach ($metaOrders as $o) {
            $meta = $o->meta ?? [];

            $receiptTotal = (float) $o->receiptTotal();

            if ($receiptTotal > 0) {
                $receiptOrders++;
                $totalReceiptAmount += $receiptTotal;
            } else {
                $noReceiptOrders++;
            }

            if ($o->isReconcileMismatch()) {
                $reconcileMismatchOrders++;
            }

            $refundTotal = (float) $o->refundTotal();

            if ($refundTotal > 0) {
                $refundOrders++;
                $totalRefundedAmount += $refundTotal;
            } else {
                $noRefundOrders++;
            }

            if ($o->isRefundInconsistent()) {
                $refundInconsistentOrders++;
            }
        }

        // 订阅维度：BMPA（批量标记支付并生效）成功/失败订单数
        // - 失败口径与平台订单列表 bmpa_failed_only 一致：error.message 存在
        // - 成功口径与 bmpa_success_only 一致：存在 run_id 且 error.message 为空
        $bmpaFailedOrders = (clone $baseOrdersQuery)
            ->whereRaw("JSON_EXTRACT(meta, '$.batch_mark_paid_and_activate_error.message') IS NOT NULL")
            ->count();

        $bmpaSuccessOrders = (clone $baseOrdersQuery)
            ->whereRaw("JSON_EXTRACT(meta, '$.batch_mark_paid_and_activate.run_id') IS NOT NULL")
            ->whereRaw("JSON_EXTRACT(meta, '$.batch_mark_paid_and_activate_error.message') IS NULL")
            ->count();

        $summaryStats = $summaryStats + [
            'receipt_orders' => $receiptOrders,
            'no_receipt_orders' => $noReceiptOrders,
            'total_receipt_amount' => (float) $totalReceiptAmount,
            'refund_orders' => $refundOrders,
            'no_refund_orders' => $noRefundOrders,
            'total_refunded_amount' => (float) $totalRefundedAmount,
            // 退款不一致订单（订阅维度）
            'refund_inconsistent_orders' => (int) $refundInconsistentOrders,
            // 对账不一致订单（订阅维度）
            'reconcile_mismatch_orders' => (int) $reconcileMismatchOrders,
            // BMPA 成功/失败订单（订阅维度）
            'bmpa_success_orders' => (int) $bmpaSuccessOrders,
            'bmpa_failed_orders' => (int) $bmpaFailedOrders,
            // 对账差额：回执总额 - 已付总额（订阅维度）
            'reconciliation_delta' => (float) ($totalReceiptAmount - (float) $metaOrders->sum('paid_amount')),
        ];

        // 同步失败原因聚合（Top3）：订阅维度快速判断“常见失败原因”
        $failedReasonRows = (clone $baseOrdersQuery)
            ->whereRaw("JSON_EXTRACT(meta, '$.subscription_activation_error.message') IS NOT NULL")
            ->selectRaw("JSON_EXTRACT(meta, '$.subscription_activation_error.message') as reason, count(*) as cnt")
            ->groupBy('reason')
            ->orderByDesc('cnt')
            ->limit(3)
            ->get();

        $failedReasonStats = $failedReasonRows->map(function ($row) {
            $reason = (string) ($row->reason ?? '');
            $reason = trim($reason, "\" ");

            return [
                'reason' => $reason !== '' ? $reason : '（空）',
                'count' => (int) ($row->cnt ?? 0),
            ];
        })->values()->all();

        // BMPA 失败原因聚合（Top3）：订阅维度快速判断“常见批量标记支付失败原因”
        $bmpaFailedReasonRows = (clone $baseOrdersQuery)
            ->whereRaw("JSON_EXTRACT(meta, '$.batch_mark_paid_and_activate_error.message') IS NOT NULL")
            ->selectRaw("JSON_EXTRACT(meta, '$.batch_mark_paid_and_activate_error.message') as reason, count(*) as cnt")
            ->groupBy('reason')
            ->orderByDesc('cnt')
            ->limit(3)
            ->get();

        $bmpaFailedReasonStats = $bmpaFailedReasonRows->map(function ($row) {
            $reason = (string) ($row->reason ?? '');
            $reason = trim($reason, "\" ");

            return [
                'reason' => $reason !== '' ? $reason : '（空）',
                'count' => (int) ($row->cnt ?? 0),
            ];
        })->values()->all();

        // 页面列表筛选：仅影响“关联平台订单”列表展示，不影响摘要统计
        $orderSyncStatus = trim((string) $request->query('order_sync_status', ''));

        $displayOrdersQuery = (clone $baseOrdersQuery);
        if ($orderSyncStatus === 'synced') {
            $displayOrdersQuery
                ->whereRaw("JSON_EXTRACT(meta, '$.subscription_activation.subscription_id') IS NOT NULL")
                ->whereRaw("JSON_EXTRACT(meta, '$.subscription_activation_error.message') IS NULL");
        } elseif ($orderSyncStatus === 'failed') {
            $displayOrdersQuery
                ->whereRaw("JSON_EXTRACT(meta, '$.subscription_activation_error.message') IS NOT NULL");
        } elseif ($orderSyncStatus === 'unsynced') {
            $displayOrdersQuery
                ->whereRaw("JSON_EXTRACT(meta, '$.subscription_activation.subscription_id') IS NULL")
                ->whereRaw("JSON_EXTRACT(meta, '$.subscription_activation_error.message') IS NULL");
        } elseif ($orderSyncStatus === 'syncable') {
            // 口径对齐平台订单页：可同步 = 已支付 + 已生效 + 未同步 + 非失败
            $displayOrdersQuery
                ->where('payment_status', 'paid')
                ->where('status', 'activated')
                ->whereRaw("JSON_EXTRACT(meta, '$.subscription_activation.subscription_id') IS NULL")
                ->whereRaw("JSON_EXTRACT(meta, '$.subscription_activation_error.message') IS NULL");
        }

        $platformOrders = $displayOrdersQuery
            ->latest('id')
            ->paginate(10)
            ->withQueryString();

        // 可治理摘要：订阅下的订单同步情况
        $summaryStats = $summaryStats + [
            'current_order_sync_status' => $orderSyncStatus,
        ];

        $endsAt = $subscription->ends_at;
        $expiryLabel = '无到期';
        if ($endsAt) {
            if ($endsAt->lt(now())) {
                $expiryLabel = '已过期';
            } elseif ($endsAt->lt(now()->addDays(7))) {
                $expiryLabel = '7天内到期';
            } else {
                $expiryLabel = '未到期';
            }
        }

        return view('admin.site_subscriptions.show', [
            'subscription' => $subscription,
            'platformOrders' => $platformOrders,
            'summaryStats' => $summaryStats,
            'failedReasonStats' => $failedReasonStats,
            'bmpaFailedReasonStats' => $bmpaFailedReasonStats,
            'statusLabels' => $this->statusLabels(),
            'expiryLabel' => $expiryLabel,
        ]);
    }

    public function export(Request $request): StreamedResponse
    {
        $this->ensurePlatformAdmin($request);

        // 安全阀：必须显式声明 download=1，避免浏览器预取/误触发导致频繁导出
        if ((string) $request->query('download', '') !== '1') {
            abort(400, 'download=1 required');
        }

        $filters = [
            'status' => trim((string) $request->query('status', '')),
            'keyword' => trim((string) $request->query('keyword', '')),
            'merchant_id' => trim((string) $request->query('merchant_id', '')),
            'plan_id' => trim((string) $request->query('plan_id', '')),
            'expiry' => trim((string) $request->query('expiry', '')),
            'ends_from' => trim((string) $request->query('ends_from', '')),
            'ends_to' => trim((string) $request->query('ends_to', '')),
        ];

        $query = $this->applyFilters(
            SiteSubscription::query()->with(['merchant', 'plan'])->withCount('platformOrders'),
            $filters
        )->orderBy('id');

        $filename = 'site_subscriptions_' . now()->format('Ymd_His') . '.csv';

        return response()->streamDownload(function () use ($query) {
            $out = fopen('php://output', 'w');

            // UTF-8 BOM，避免 Excel 打开中文乱码
            fwrite($out, "\xEF\xBB\xBF");

            fputcsv($out, [
                'ID',
                '订阅号',
                '站点',
                '套餐',
                '关联订单数',
                '状态',
                '计费周期',
                '周期(月)',
                '金额',
                '开始时间',
                '到期时间',
                '到期状态',
                '试用到期',
                '生效时间',
                '取消时间',
            ]);

            $statusLabels = $this->statusLabels();

            $query->chunkById(500, function ($subs) use ($out, $statusLabels) {
                foreach ($subs as $sub) {
                    $endsAt = $sub->ends_at;
                    $expiryLabel = '无到期';
                    if ($endsAt) {
                        if ($endsAt->lt(now())) {
                            $expiryLabel = '已过期';
                        } elseif ($endsAt->lt(now()->addDays(7))) {
                            $expiryLabel = '7天内到期';
                        } else {
                            $expiryLabel = '未到期';
                        }
                    }

                    $status = (string) ($sub->status ?? '');
                    $statusText = ($statusLabels[$status] ?? $status);
                    $statusText = $statusText . ' (' . $status . ')';

                    fputcsv($out, [
                        $sub->id,
                        $sub->subscription_no,
                        $sub->merchant?->name ?? '',
                        $sub->plan_name ?: ($sub->plan?->name ?? ''),
                        (int) ($sub->platform_orders_count ?? 0),
                        $statusText,
                        $sub->billing_cycle ?: '',
                        (int) $sub->period_months,
                        (float) $sub->amount,
                        optional($sub->starts_at)->format('Y-m-d H:i:s') ?: '',
                        optional($sub->ends_at)->format('Y-m-d H:i:s') ?: '',
                        $expiryLabel,
                        optional($sub->trial_ends_at)->format('Y-m-d H:i:s') ?: '',
                        optional($sub->activated_at)->format('Y-m-d H:i:s') ?: '',
                        optional($sub->cancelled_at)->format('Y-m-d H:i:s') ?: '',
                    ]);
                }
            });

            fclose($out);
        }, $filename, [
            'Content-Type' => 'text/csv; charset=UTF-8',
        ]);
    }

    public function index(Request $request): View
    { 
        $this->ensurePlatformAdmin($request);

        $filters = [
            'status' => trim((string) $request->query('status', '')),
            'keyword' => trim((string) $request->query('keyword', '')),
            'merchant_id' => trim((string) $request->query('merchant_id', '')),
            'plan_id' => trim((string) $request->query('plan_id', '')),
            // 到期辅助筛选（不改变 status 字段，仅按 ends_at 计算）
            // - expired：已过期（ends_at < now）
            // - expiring_7d：7 天内到期（now <= ends_at < now+7d）
            'expiry' => trim((string) $request->query('expiry', '')),
            // 到期时间范围筛选（用于到期治理更精确定位 ends_at）
            'ends_from' => trim((string) $request->query('ends_from', '')),
            'ends_to' => trim((string) $request->query('ends_to', '')),
        ];

        $query = $this->applyFilters(
            SiteSubscription::query()->with(['merchant', 'plan'])->withCount('platformOrders'),
            $filters
        );

        $subscriptions = (clone $query)
            ->latest('id')
            ->paginate(10)
            ->withQueryString();

        $baseQuery = $this->applyFilters(SiteSubscription::query(), $filters);

        $expiryMerchantRows = [];
        $expiryMerchantPlanRows = [];
        if ((string) ($filters['expiry'] ?? '') === 'expiring_7d') {
            // 到期提醒清单：站点维度 Top10（用于运营快速触达/续费跟进）
            $expiryMerchantRows = $this->applyFilters(SiteSubscription::query(), $filters)
                ->leftJoin('merchants', 'site_subscriptions.merchant_id', '=', 'merchants.id')
                ->whereNotNull('site_subscriptions.ends_at')
                ->selectRaw('site_subscriptions.merchant_id as merchant_id, merchants.name as merchant_name, count(*) as cnt, min(site_subscriptions.ends_at) as min_ends_at')
                ->groupBy('site_subscriptions.merchant_id', 'merchants.name')
                ->orderByDesc('cnt')
                ->orderBy('min_ends_at')
                ->limit(10)
                ->get()
                ->map(function ($row) {
                    return [
                        'merchant_id' => (int) ($row->merchant_id ?? 0),
                        'merchant_name' => (string) ($row->merchant_name ?? ''),
                        'count' => (int) ($row->cnt ?? 0),
                        'min_ends_at' => (string) ($row->min_ends_at ?? ''),
                    ];
                })
                ->values()
                ->all();

            // 到期提醒清单：站点+套餐维度 Top10（更精确的续费下单入口）
            $expiryMerchantPlanRows = $this->applyFilters(SiteSubscription::query(), $filters)
                ->leftJoin('merchants', 'site_subscriptions.merchant_id', '=', 'merchants.id')
                ->leftJoin('plans', 'site_subscriptions.plan_id', '=', 'plans.id')
                ->whereNotNull('site_subscriptions.ends_at')
                ->selectRaw('site_subscriptions.merchant_id as merchant_id, merchants.name as merchant_name, site_subscriptions.plan_id as plan_id, plans.name as plan_name, count(*) as cnt, min(site_subscriptions.ends_at) as min_ends_at')
                ->groupBy('site_subscriptions.merchant_id', 'merchants.name', 'site_subscriptions.plan_id', 'plans.name')
                ->orderByDesc('cnt')
                ->orderBy('min_ends_at')
                ->limit(10)
                ->get()
                ->map(function ($row) {
                    return [
                        'merchant_id' => (int) ($row->merchant_id ?? 0),
                        'merchant_name' => (string) ($row->merchant_name ?? ''),
                        'plan_id' => (int) ($row->plan_id ?? 0),
                        'plan_name' => (string) ($row->plan_name ?? ''),
                        'count' => (int) ($row->cnt ?? 0),
                        'min_ends_at' => (string) ($row->min_ends_at ?? ''),
                    ];
                })
                ->values()
                ->all();
        }

        // ends_at 快捷入口日期范围：由 Controller 统一注入，避免 Blade 内多次 now() 调用跨天漂移。
        $baseToday = now();
        $endsRangeToday = $baseToday->format('Y-m-d');
        $endsRange7d = $baseToday->copy()->addDays(7)->format('Y-m-d');
        $endsRange30d = $baseToday->copy()->addDays(30)->format('Y-m-d');

        return view('admin.site_subscriptions.index', [
            'subscriptions' => $subscriptions,
            'filters' => $filters,
            'statusLabels' => $this->statusLabels(),
            'filterOptions' => [
                'statuses' => $this->statusLabels(),
            ],
            'merchants' => SiteSubscription::query()->with('merchant')->select('merchant_id')->distinct()->get()->pluck('merchant')->filter()->unique('id')->values(),
            'plans' => SiteSubscription::query()->with('plan')->select('plan_id')->whereNotNull('plan_id')->distinct()->get()->pluck('plan')->filter()->unique('id')->values(),
            'summaryStats' => [
                'total_subscriptions' => (clone $baseQuery)->count(),
                'activated_subscriptions' => (clone $baseQuery)->where('status', 'activated')->count(),
                'pending_subscriptions' => (clone $baseQuery)->where('status', 'pending')->count(),
                'cancelled_subscriptions' => (clone $baseQuery)->where('status', 'cancelled')->count(),
                // 可治理辅助指标：按 ends_at 计算
                'expired_subscriptions' => (clone $baseQuery)
                    ->whereNotNull('ends_at')
                    ->where('ends_at', '<', now())
                    ->count(),
                'expiring_7d_subscriptions' => (clone $baseQuery)
                    ->whereNotNull('ends_at')
                    ->where('ends_at', '>=', now())
                    ->where('ends_at', '<', now()->addDays(7))
                    ->count(),
            ],
            'expiryMerchantRows' => $expiryMerchantRows,
            'expiryMerchantPlanRows' => $expiryMerchantPlanRows,

            // ends_at 快捷入口日期范围
            'endsRangeToday' => $endsRangeToday,
            'endsRange7d' => $endsRange7d,
            'endsRange30d' => $endsRange30d,
        ]);
    }

    protected function statusLabels(): array
    {
        return [
            'pending' => '待生效',
            'activated' => '已生效',
            'cancelled' => '已取消',
            'expired' => '已过期',
        ];
    }

    public function setStatus(Request $request, SiteSubscription $subscription): \Illuminate\Http\RedirectResponse
    {
        $this->ensurePlatformAdmin($request);

        $data = $request->validate([
            'status' => ['required', \Illuminate\Validation\Rule::in(array_keys($this->statusLabels()))],
        ]);

        $subscription->status = (string) $data['status'];
        $subscription->save();

        return redirect()->back()->with('success', '订阅状态已更新：' . ($this->statusLabels()[$subscription->status] ?? $subscription->status));
    }

    public function batchMarkExpired(Request $request): \Illuminate\Http\RedirectResponse
    {
        $this->ensurePlatformAdmin($request);

        // 仅支持在“已过期（expiry=expired）集合”上执行，避免误把正常订阅批量标记为已过期。
        $filters = [
            'status' => trim((string) $request->input('status', '')),
            'keyword' => trim((string) $request->input('keyword', '')),
            'merchant_id' => trim((string) $request->input('merchant_id', '')),
            'plan_id' => trim((string) $request->input('plan_id', '')),
            'expiry' => trim((string) $request->input('expiry', '')),
            // 到期时间范围筛选：批量动作必须与当前列表口径一致
            'ends_from' => trim((string) $request->input('ends_from', '')),
            'ends_to' => trim((string) $request->input('ends_to', '')),
        ];

        if ((string) ($filters['expiry'] ?? '') !== 'expired') {
            return redirect()->back()->with('warning', '为避免误操作：批量标记已过期仅允许在「已过期（expiry=expired）」集合视图下执行。');
        }

        // 防误操作：需要二次确认
        if ((string) $request->input('confirm', '') !== 'YES') {
            return redirect()->back()->with('warning', '为避免误操作，请在确认框输入 YES 后再批量标记已过期。');
        }

        $query = $this->applyFilters(SiteSubscription::query(), $filters);

        // 再加一道硬条件：ends_at 必须 < now（与 expiry=expired 一致）
        $query->whereNotNull('ends_at')->where('ends_at', '<', now());

        // 仅把“非已过期”的订阅更新为 expired
        $affected = (clone $query)
            ->where('status', '!=', 'expired')
            ->update([
                'status' => 'expired',
            ]);

        return redirect()->back()->with('success', '已批量标记已过期：' . (int) $affected . ' 条。');
    }

    protected function applyFilters(Builder $query, array $filters): Builder
    {
        // 说明：该方法既会用于普通列表查询（无 join），也会用于「到期提醒 Top10」统计（有 join merchants/plans）。
        // 为避免在 SQLite 下出现 "ambiguous column name"，这里统一对 site_subscriptions 的字段加上表前缀。
        $t = 'site_subscriptions';

        return $query
            ->when($filters['status'] !== '', fn (Builder $builder) => $builder->where($t . '.status', $filters['status']))
            ->when(($filters['merchant_id'] ?? '') !== '', fn (Builder $builder) => $builder->where($t . '.merchant_id', (int) $filters['merchant_id']))
            ->when(($filters['plan_id'] ?? '') !== '', fn (Builder $builder) => $builder->where($t . '.plan_id', (int) $filters['plan_id']))
            ->when(($filters['expiry'] ?? '') !== '', function (Builder $builder) use ($filters, $t) {
                $expiry = (string) ($filters['expiry'] ?? '');
                if ($expiry === 'expired') {
                    $builder->whereNotNull($t . '.ends_at')->where($t . '.ends_at', '<', now());
                } elseif ($expiry === 'expiring_7d') {
                    $builder->whereNotNull($t . '.ends_at')
                        ->where($t . '.ends_at', '>=', now())
                        ->where($t . '.ends_at', '<', now()->addDays(7));
                }
            })
            ->when(($filters['ends_from'] ?? '') !== '' || ($filters['ends_to'] ?? '') !== '', function (Builder $builder) use ($filters, $t) {
                // 到期时间范围筛选：用于运营按 ends_at 精确定位
                // 容错：仅接受 YYYY-MM-DD
                $from = trim((string) ($filters['ends_from'] ?? ''));
                $to = trim((string) ($filters['ends_to'] ?? ''));

                if ($from !== '' && !preg_match('/^\d{4}-\d{2}-\d{2}$/', $from)) {
                    $from = '';
                }
                if ($to !== '' && !preg_match('/^\d{4}-\d{2}-\d{2}$/', $to)) {
                    $to = '';
                }

                if ($from !== '' && $to !== '') {
                    $builder->whereBetween($t . '.ends_at', [$from . ' 00:00:00', $to . ' 23:59:59']);
                } elseif ($from !== '') {
                    $builder->where($t . '.ends_at', '>=', $from . ' 00:00:00');
                } elseif ($to !== '') {
                    $builder->where($t . '.ends_at', '<=', $to . ' 23:59:59');
                }
            })
            ->when($filters['keyword'] !== '', function (Builder $builder) use ($filters, $t) {
                // 关键词搜索：订阅号 / 站点 / 套餐 / 计费周期
                $keyword = trim((string) ($filters['keyword'] ?? ''));
                if ($keyword === '') {
                    return;
                }

                $builder->where(function (Builder $q) use ($keyword, $t) {
                    $q->where($t . '.subscription_no', 'like', '%' . $keyword . '%')
                        ->orWhere($t . '.plan_name', 'like', '%' . $keyword . '%')
                        ->orWhere($t . '.billing_cycle', 'like', '%' . $keyword . '%')
                        ->orWhereHas('merchant', function (Builder $mq) use ($keyword) {
                            $mq->where('name', 'like', '%' . $keyword . '%')
                                ->orWhere('slug', 'like', '%' . $keyword . '%');
                        })
                        ->orWhereHas('plan', function (Builder $pq) use ($keyword) {
                            $pq->where('name', 'like', '%' . $keyword . '%')
                                ->orWhere('code', 'like', '%' . $keyword . '%');
                        });

                    if (ctype_digit($keyword)) {
                        $q->orWhere($t . '.id', (int) $keyword);
                    }
                });
            });
    }
}

