<?php

namespace App\Services;

use App\Models\BadDebts\BadDebt;
use App\Models\NotificationSetting;
use App\Models\Orders\Client;
use App\Models\Orders\Order;
use App\Models\PushDeviceToken;
use App\Models\Tenants\Approval;
use App\Models\Tenants\ApprovalStep;
use App\Models\Tenants\Deposit;
use App\Models\Tenants\ExpectedExpense;
use App\Models\Tenants\Stock;
use App\Models\Tenants\TodayIssue;
use App\Models\Tenants\Withdrawal;
use App\Services\Fcm\FcmSender;
use Carbon\Carbon;
use Illuminate\Support\Facades\Log;

/**
 * 오늘의 이슈 Observer 서비스
 *
 * 모델 이벤트 발생 시 TodayIssue 테이블에 실시간 저장/삭제
 * FCM 푸시 알림 연동
 */
class TodayIssueObserverService
{
    public function __construct(
        private readonly FcmSender $fcmSender
    ) {}

    /**
     * 수주 성공 이슈 생성/삭제
     */
    public function handleOrderChange(Order $order): void
    {
        Log::info('TodayIssue: Order change detected', [
            'order_id' => $order->id,
            'status_code' => $order->status_code,
            'tenant_id' => $order->tenant_id,
        ]);

        // 확정 상태이고 최근 7일 이내인 경우만 이슈 생성
        $isConfirmed = $order->status_code === Order::STATUS_CONFIRMED;
        $isRecent = $order->created_at?->gte(Carbon::now()->subDays(7));

        if ($isConfirmed && $isRecent) {
            $clientName = $order->client?->name ?? __('message.today_issue.unknown_client');
            $amount = number_format($order->total_amount ?? 0);

            Log::info('TodayIssue: Creating order success issue', [
                'order_id' => $order->id,
                'client' => $clientName,
                'amount' => $amount,
            ]);

            $this->createIssueWithFcm(
                tenantId: $order->tenant_id,
                sourceType: TodayIssue::SOURCE_ORDER,
                sourceId: $order->id,
                badge: TodayIssue::BADGE_ORDER_REGISTER,
                content: __('message.today_issue.order_register', [
                    'client' => $clientName,
                    'amount' => $amount,
                ]),
                path: "/sales/order-management-sales/{$order->id}",
                needsApproval: false,
                expiresAt: Carbon::now()->addDays(7)
            );
        } else {
            Log::info('TodayIssue: Order does not meet criteria, removing issue if exists', [
                'order_id' => $order->id,
                'is_confirmed' => $isConfirmed,
                'is_recent' => $isRecent,
            ]);
            // 조건에 맞지 않으면 이슈 삭제
            TodayIssue::removeBySource($order->tenant_id, TodayIssue::SOURCE_ORDER, $order->id);
        }
    }

    /**
     * 수주 삭제 시 이슈 삭제
     */
    public function handleOrderDeleted(Order $order): void
    {
        TodayIssue::removeBySource($order->tenant_id, TodayIssue::SOURCE_ORDER, $order->id);
    }

    /**
     * 미수금(추심 이슈) 생성/삭제
     *
     * is_active가 true로 설정(토글 ON)되면 오늘의 이슈에 추가
     * is_active가 false로 설정(토글 OFF)되면 오늘의 이슈에서 삭제
     */
    public function handleBadDebtChange(BadDebt $badDebt): void
    {
        // is_active(설정 토글)이 켜져 있고, 추심중 또는 법적조치 상태인 경우 이슈 생성
        $isActiveStatus = in_array($badDebt->status, [BadDebt::STATUS_COLLECTING, BadDebt::STATUS_LEGAL_ACTION]);

        if ($badDebt->is_active && $isActiveStatus) {
            $clientName = $badDebt->client?->name ?? __('message.today_issue.unknown_client');
            $amount = number_format($badDebt->debt_amount ?? 0);
            $days = $badDebt->overdue_days ?? 0;

            $this->createIssueWithFcm(
                tenantId: $badDebt->tenant_id,
                sourceType: TodayIssue::SOURCE_BAD_DEBT,
                sourceId: $badDebt->id,
                badge: TodayIssue::BADGE_COLLECTION_ISSUE,
                content: __('message.today_issue.collection_issue', [
                    'client' => $clientName,
                    'amount' => $amount,
                    'days' => $days,
                ]),
                path: "/accounting/bad-debt-collection/{$badDebt->id}",
                needsApproval: false,
                expiresAt: null // 해결될 때까지 유지
            );
        } else {
            // is_active가 false이거나 상태가 회수완료/대손처리인 경우 이슈 삭제
            TodayIssue::removeBySource($badDebt->tenant_id, TodayIssue::SOURCE_BAD_DEBT, $badDebt->id);
        }
    }

    /**
     * 미수금 삭제 시 이슈 삭제
     */
    public function handleBadDebtDeleted(BadDebt $badDebt): void
    {
        TodayIssue::removeBySource($badDebt->tenant_id, TodayIssue::SOURCE_BAD_DEBT, $badDebt->id);
    }

    /**
     * 재고 이슈(직정 제고) 생성/삭제
     */
    public function handleStockChange(Stock $stock): void
    {
        // 안전재고 미달인 경우만 이슈 생성
        if ($stock->safety_stock > 0 && $stock->stock_qty < $stock->safety_stock) {
            $itemName = $stock->item?->name ?? $stock->item?->code ?? __('message.today_issue.unknown_item');

            $this->createIssueWithFcm(
                tenantId: $stock->tenant_id,
                sourceType: TodayIssue::SOURCE_STOCK,
                sourceId: $stock->id,
                badge: TodayIssue::BADGE_SAFETY_STOCK,
                content: __('message.today_issue.safety_stock_alert', [
                    'item' => $itemName,
                ]),
                path: "/material/stock-status/{$stock->id}",
                needsApproval: false,
                expiresAt: null // 재고 보충 시까지 유지
            );
        } else {
            TodayIssue::removeBySource($stock->tenant_id, TodayIssue::SOURCE_STOCK, $stock->id);
        }
    }

    /**
     * 재고 삭제 시 이슈 삭제
     */
    public function handleStockDeleted(Stock $stock): void
    {
        TodayIssue::removeBySource($stock->tenant_id, TodayIssue::SOURCE_STOCK, $stock->id);
    }

    /**
     * 지출예상내역서 이슈 생성/삭제
     */
    public function handleExpectedExpenseChange(ExpectedExpense $expense): void
    {
        // 매입(purchases)에서 동기화된 예상 지출은 알림 제외
        // 매입 알림은 결재 상신 시에만 발송
        if ($expense->source_type === 'purchases') {
            return;
        }

        // 승인 대기 상태인 경우만 이슈 생성
        if ($expense->payment_status === 'pending') {
            $title = $expense->description ?? __('message.today_issue.expense_item');
            $amount = number_format($expense->amount ?? 0);

            $this->createIssueWithFcm(
                tenantId: $expense->tenant_id,
                sourceType: TodayIssue::SOURCE_EXPENSE,
                sourceId: $expense->id,
                badge: TodayIssue::BADGE_EXPENSE_PENDING,
                content: __('message.today_issue.expense_pending', [
                    'title' => $title,
                    'amount' => $amount,
                ]),
                path: '/approval/inbox',
                needsApproval: true,
                expiresAt: null // 처리 완료 시까지 유지
            );
        } else {
            TodayIssue::removeBySource($expense->tenant_id, TodayIssue::SOURCE_EXPENSE, $expense->id);
        }
    }

    /**
     * 지출예상내역서 삭제 시 이슈 삭제
     */
    public function handleExpectedExpenseDeleted(ExpectedExpense $expense): void
    {
        TodayIssue::removeBySource($expense->tenant_id, TodayIssue::SOURCE_EXPENSE, $expense->id);
    }

    /**
     * 결재 요청 이슈 생성/삭제
     *
     * 결재자(ApprovalStep.user_id)에게만 알림 발송
     */
    public function handleApprovalStepChange(ApprovalStep $step): void
    {
        // 승인 대기 상태이고, 결재 문서도 pending 상태인 경우만 이슈 생성
        $approval = $step->approval;

        if ($step->status === 'pending' && $approval && $approval->status === 'pending') {
            $drafterName = $approval->drafter?->name ?? __('message.today_issue.unknown_user');
            $title = $approval->title ?? __('message.today_issue.approval_request');

            $this->createIssueWithFcm(
                tenantId: $approval->tenant_id,
                sourceType: TodayIssue::SOURCE_APPROVAL,
                sourceId: $step->id,
                badge: TodayIssue::BADGE_APPROVAL_REQUEST,
                content: __('message.today_issue.approval_pending', [
                    'title' => $title,
                    'drafter' => $drafterName,
                ]),
                path: '/approval/inbox',
                needsApproval: true,
                expiresAt: null, // 결재 완료 시까지 유지
                targetUserId: $step->user_id // 결재자에게만 발송
            );
        } else {
            if ($approval) {
                TodayIssue::removeBySource($approval->tenant_id, TodayIssue::SOURCE_APPROVAL, $step->id);
            }
        }
    }

    /**
     * 결재 단계 삭제 시 이슈 삭제
     */
    public function handleApprovalStepDeleted(ApprovalStep $step): void
    {
        if ($step->approval) {
            TodayIssue::removeBySource($step->approval->tenant_id, TodayIssue::SOURCE_APPROVAL, $step->id);
        }
    }

    /**
     * 결재 상태 변경 시 기안자에게 알림 발송
     *
     * 승인(approved), 반려(rejected), 완료(approved 최종) 시 기안자에게만 발송
     */
    public function handleApprovalStatusChange(Approval $approval): void
    {
        // 상태에 따른 뱃지 결정
        $badge = match ($approval->status) {
            Approval::STATUS_APPROVED => TodayIssue::BADGE_DRAFT_APPROVED,
            Approval::STATUS_REJECTED => TodayIssue::BADGE_DRAFT_REJECTED,
            default => null,
        };

        if (! $badge) {
            return;
        }

        // 메시지 키 결정
        $messageKey = match ($approval->status) {
            Approval::STATUS_APPROVED => 'message.today_issue.draft_approved',
            Approval::STATUS_REJECTED => 'message.today_issue.draft_rejected',
            default => null,
        };

        if (! $messageKey) {
            return;
        }

        $title = $approval->title ?? __('message.today_issue.approval_request');

        $this->createIssueWithFcm(
            tenantId: $approval->tenant_id,
            sourceType: TodayIssue::SOURCE_APPROVAL,
            sourceId: $approval->id,
            badge: $badge,
            content: __($messageKey, [
                'title' => $title,
            ]),
            path: '/approval/draft',
            needsApproval: false,
            expiresAt: Carbon::now()->addDays(7),
            targetUserId: $approval->drafter_id // 기안자에게만 발송
        );
    }

    /**
     * 신규 거래처 이슈 생성
     */
    public function handleClientCreated(Client $client): void
    {
        $this->createIssueWithFcm(
            tenantId: $client->tenant_id,
            sourceType: TodayIssue::SOURCE_CLIENT,
            sourceId: $client->id,
            badge: TodayIssue::BADGE_NEW_CLIENT,
            content: __('message.today_issue.new_client', [
                'name' => $client->name,
            ]),
            path: "/accounting/vendors/{$client->id}?modal=credit",
            needsApproval: false,
            expiresAt: Carbon::now()->addDays(7)
        );
    }

    /**
     * 거래처 삭제 시 이슈 삭제
     */
    public function handleClientDeleted(Client $client): void
    {
        TodayIssue::removeBySource($client->tenant_id, TodayIssue::SOURCE_CLIENT, $client->id);
    }

    /**
     * 입금 등록 이슈 생성
     */
    public function handleDepositCreated(Deposit $deposit): void
    {
        Log::info('TodayIssue: Deposit created detected', [
            'deposit_id' => $deposit->id,
            'tenant_id' => $deposit->tenant_id,
            'amount' => $deposit->amount,
        ]);

        $clientName = $deposit->display_client_name ?: __('message.today_issue.unknown_client');
        $amount = number_format($deposit->amount ?? 0);

        Log::info('TodayIssue: Creating deposit issue', [
            'deposit_id' => $deposit->id,
            'client' => $clientName,
            'amount' => $amount,
        ]);

        $this->createIssueWithFcm(
            tenantId: $deposit->tenant_id,
            sourceType: TodayIssue::SOURCE_DEPOSIT,
            sourceId: $deposit->id,
            badge: TodayIssue::BADGE_DEPOSIT,
            content: __('message.today_issue.deposit_registered', [
                'client' => $clientName,
                'amount' => $amount,
            ]),
            path: "/accounting/deposits/{$deposit->id}",
            needsApproval: false,
            expiresAt: Carbon::now()->addDays(7)
        );
    }

    /**
     * 입금 삭제 시 이슈 삭제
     */
    public function handleDepositDeleted(Deposit $deposit): void
    {
        TodayIssue::removeBySource($deposit->tenant_id, TodayIssue::SOURCE_DEPOSIT, $deposit->id);
    }

    /**
     * 출금 등록 이슈 생성 (일일 누계 방식)
     *
     * - 첫 번째 출금: "거래처명 출금 금액원"
     * - 두 번째 이후: "첫번째거래처명 외 N건 출금 합계 금액원"
     * - source_id=null로 일일 1건만 유지 (upsert)
     * - FCM 푸시 미발송 (알림 설정 미구현)
     */
    public function handleWithdrawalCreated(Withdrawal $withdrawal): void
    {
        Log::info('TodayIssue: Withdrawal created detected', [
            'withdrawal_id' => $withdrawal->id,
            'tenant_id' => $withdrawal->tenant_id,
            'amount' => $withdrawal->amount,
        ]);

        $this->upsertWithdrawalDailyIssue($withdrawal->tenant_id);
    }

    /**
     * 출금 삭제 시 일일 누계 이슈 갱신
     */
    public function handleWithdrawalDeleted(Withdrawal $withdrawal): void
    {
        $this->upsertWithdrawalDailyIssue($withdrawal->tenant_id);
    }

    /**
     * 출금 일일 누계 이슈 upsert
     *
     * 오늘 날짜의 출금 건수/합계를 집계하여 이슈 1건으로 관리
     */
    private function upsertWithdrawalDailyIssue(int $tenantId): void
    {
        // 기존 개별 출금 이슈 정리 (source_id가 있는 레거시 데이터)
        TodayIssue::where('tenant_id', $tenantId)
            ->where('source_type', TodayIssue::SOURCE_WITHDRAWAL)
            ->whereNotNull('source_id')
            ->delete();

        // 오늘 날짜 출금 조회 (출금일 기준, soft delete 제외)
        $todayWithdrawals = Withdrawal::withoutGlobalScopes()
            ->where('tenant_id', $tenantId)
            ->whereDate('withdrawal_date', Carbon::today())
            ->whereNull('deleted_at')
            ->orderBy('created_at', 'asc')
            ->get();

        $count = $todayWithdrawals->count();
        $totalAmount = $todayWithdrawals->sum('amount');

        Log::info('TodayIssue: Withdrawal daily summary', [
            'tenant_id' => $tenantId,
            'count' => $count,
            'total_amount' => $totalAmount,
        ]);

        // 출금이 없으면 이슈 삭제
        if ($count === 0) {
            TodayIssue::where('tenant_id', $tenantId)
                ->where('source_type', TodayIssue::SOURCE_WITHDRAWAL)
                ->whereNull('source_id')
                ->delete();

            return;
        }

        // 첫 번째 출금의 거래처명
        $first = $todayWithdrawals->first();
        $firstClientName = $first->display_client_name
            ?: $first->merchant_name
            ?: __('message.today_issue.unknown_client');

        // 1건이면 단건 메시지+상세경로, 2건 이상이면 누계 메시지+목록경로
        if ($count === 1) {
            $content = __('message.today_issue.withdrawal_registered', [
                'client' => $firstClientName,
                'amount' => number_format($totalAmount),
            ]);
            $path = "/accounting/withdrawals/{$first->id}";
        } else {
            $content = __('message.today_issue.withdrawal_daily_summary', [
                'client' => $firstClientName,
                'count' => $count - 1,
                'amount' => number_format($totalAmount),
            ]);
            $path = '/accounting/withdrawals';
        }

        // source_id=null 로 일일 1건 upsert (FCM 미발송)
        TodayIssue::createIssue(
            tenantId: $tenantId,
            sourceType: TodayIssue::SOURCE_WITHDRAWAL,
            sourceId: null,
            badge: TodayIssue::BADGE_WITHDRAWAL,
            content: $content,
            path: $path,
            needsApproval: false,
            expiresAt: Carbon::now()->addDays(7)
        );
    }

    /**
     * 세금 신고 이슈 업데이트 (스케줄러에서 호출)
     * 이 메서드는 일일 스케줄러에서 호출하여 세금 신고 이슈를 업데이트합니다.
     */
    public function updateTaxIssues(int $tenantId): void
    {
        $today = Carbon::today();

        // 부가세 신고 마감일 계산 (분기별: 1/25, 4/25, 7/25, 10/25)
        $quarter = $today->quarter;
        $deadlineMonth = match ($quarter) {
            1 => 1,
            2 => 4,
            3 => 7,
            4 => 10,
        };

        $deadlineYear = $today->year;
        if ($today->month > $deadlineMonth || ($today->month == $deadlineMonth && $today->day > 25)) {
            $deadlineMonth = match ($quarter) {
                1 => 4,
                2 => 7,
                3 => 10,
                4 => 1,
            };
            if ($deadlineMonth == 1) {
                $deadlineYear++;
            }
        }

        $deadline = Carbon::create($deadlineYear, $deadlineMonth, 25);
        $daysUntil = $today->diffInDays($deadline, false);

        // 기존 세금 신고 이슈 삭제
        TodayIssue::where('tenant_id', $tenantId)
            ->where('source_type', TodayIssue::SOURCE_TAX)
            ->delete();

        // D-30 이내인 경우에만 표시
        if ($daysUntil <= 30 && $daysUntil >= 0) {
            $quarterName = match ($deadlineMonth) {
                1 => '4',
                4 => '1',
                7 => '2',
                10 => '3',
            };

            $this->createIssueWithFcm(
                tenantId: $tenantId,
                sourceType: TodayIssue::SOURCE_TAX,
                sourceId: null, // 세금 신고는 특정 소스 ID가 없음
                badge: TodayIssue::BADGE_TAX_REPORT,
                content: __('message.today_issue.tax_vat_deadline', [
                    'quarter' => $quarterName,
                    'days' => $daysUntil,
                ]),
                path: '/accounting/tax',
                needsApproval: false,
                expiresAt: $deadline
            );
        }
    }

    // ============================================================
    // FCM 푸시 알림 발송 헬퍼
    // ============================================================

    /**
     * TodayIssue 생성 후 FCM 푸시 알림 발송
     *
     * target_user_id가 있으면 해당 사용자에게만, 없으면 테넌트 전체에게 발송
     * 알림 설정이 활성화된 사용자에게만 발송
     * 중요 알림(수주등록, 신규거래처, 결재요청)은 알림음 다르게 발송
     */
    public function sendFcmNotification(TodayIssue $issue): void
    {
        if (! $issue->notification_type) {
            return;
        }

        try {
            // 해당 테넌트의 활성 토큰 조회 (알림 설정 활성화된 사용자만)
            // target_user_id가 있으면 해당 사용자만, 없으면 테넌트 전체
            $tokens = $this->getEnabledUserTokens(
                $issue->tenant_id,
                $issue->notification_type,
                $issue->target_user_id
            );

            if (empty($tokens)) {
                Log::info('[TodayIssue] No enabled tokens found for FCM', [
                    'tenant_id' => $issue->tenant_id,
                    'notification_type' => $issue->notification_type,
                    'target_user_id' => $issue->target_user_id,
                ]);

                return;
            }

            // 알림 타입에 따른 채널 결정
            $channelId = $this->getChannelForNotificationType($issue->notification_type);

            $result = $this->fcmSender->sendToMany(
                $tokens,
                $issue->badge,
                $issue->content,
                $channelId,
                [
                    'type' => 'today_issue',
                    'issue_id' => $issue->id,
                    'notification_type' => $issue->notification_type,
                    'path' => $issue->path,
                ]
            );

            Log::info('[TodayIssue] FCM notification sent', [
                'issue_id' => $issue->id,
                'notification_type' => $issue->notification_type,
                'target_user_id' => $issue->target_user_id,
                'channel_id' => $channelId,
                'token_count' => count($tokens),
                'success_count' => $result->getSuccessCount(),
                'failure_count' => $result->getFailureCount(),
            ]);

        } catch (\Exception $e) {
            Log::error('[TodayIssue] FCM notification failed', [
                'issue_id' => $issue->id,
                'notification_type' => $issue->notification_type,
                'target_user_id' => $issue->target_user_id,
                'error' => $e->getMessage(),
            ]);
        }
    }

    /**
     * 알림 설정이 활성화된 사용자들의 FCM 토큰 조회
     *
     * @param  int  $tenantId  테넌트 ID
     * @param  string  $notificationType  알림 타입
     * @param  int|null  $targetUserId  특정 대상 사용자 ID (null이면 테넌트 전체)
     */
    private function getEnabledUserTokens(int $tenantId, string $notificationType, ?int $targetUserId = null): array
    {
        // 해당 테넌트의 활성 토큰 조회
        $query = PushDeviceToken::withoutGlobalScopes()
            ->where('tenant_id', $tenantId)
            ->where('is_active', true)
            ->whereNull('deleted_at');

        // 특정 대상자가 지정된 경우 해당 사용자만 조회
        if ($targetUserId !== null) {
            $query->where('user_id', $targetUserId);
        }

        $tokens = $query->get();

        if ($tokens->isEmpty()) {
            return [];
        }

        // 각 사용자의 알림 설정 확인
        $enabledTokens = [];
        foreach ($tokens as $token) {
            if ($this->isNotificationEnabledForUser($tenantId, $token->user_id, $notificationType)) {
                $enabledTokens[] = $token->token;
            }
        }

        return $enabledTokens;
    }

    /**
     * 특정 사용자의 특정 알림 타입 활성화 여부 확인
     *
     * 설정이 없으면 기본값 true (알림 활성화)
     */
    private function isNotificationEnabledForUser(int $tenantId, int $userId, string $notificationType): bool
    {
        $setting = NotificationSetting::withoutGlobalScopes()
            ->where('tenant_id', $tenantId)
            ->where('user_id', $userId)
            ->where('notification_type', $notificationType)
            ->first();

        // 설정이 없으면 기본값 true
        if (! $setting) {
            return true;
        }

        // push_enabled 또는 in_app_enabled 중 하나라도 활성화되어 있으면 true
        return $setting->push_enabled || $setting->in_app_enabled;
    }

    /**
     * TodayIssue 생성 시 FCM 발송 포함 (래퍼 메서드)
     *
     * createIssue 호출 후 자동으로 FCM 발송
     *
     * @param  int  $tenantId  테넌트 ID
     * @param  string  $sourceType  소스 타입
     * @param  int|null  $sourceId  소스 ID
     * @param  string  $badge  뱃지 타입
     * @param  string  $content  알림 내용
     * @param  string|null  $path  이동 경로
     * @param  bool  $needsApproval  승인 필요 여부
     * @param  \DateTime|null  $expiresAt  만료 시간
     * @param  int|null  $targetUserId  특정 대상 사용자 ID (null이면 테넌트 전체)
     */
    public function createIssueWithFcm(
        int $tenantId,
        string $sourceType,
        ?int $sourceId,
        string $badge,
        string $content,
        ?string $path = null,
        bool $needsApproval = false,
        ?\DateTime $expiresAt = null,
        ?int $targetUserId = null
    ): TodayIssue {
        $issue = TodayIssue::createIssue(
            tenantId: $tenantId,
            sourceType: $sourceType,
            sourceId: $sourceId,
            badge: $badge,
            content: $content,
            path: $path,
            needsApproval: $needsApproval,
            expiresAt: $expiresAt,
            targetUserId: $targetUserId
        );

        // FCM 발송
        $this->sendFcmNotification($issue);

        return $issue;
    }

    /**
     * 알림 타입에 따른 FCM 채널 ID 반환
     *
     * 채널별 알림음:
     * - push_vendor_register: 거래처등록(신규업체)
     * - push_approval_request: 결재요청
     * - push_income: 입금
     * - push_sales_order: 수주
     * - push_purchase_order: 발주
     * - push_contract: 계약
     * - push_default: 일반 (출금, 카드 등)
     */
    private function getChannelForNotificationType(?string $notificationType): string
    {
        return match ($notificationType) {
            'new_vendor' => config('fcm.channels.vendor_register'),       // 거래처등록(신규업체)
            'approval_request' => config('fcm.channels.approval_request'), // 결재요청
            'income' => config('fcm.channels.income'),                     // 입금
            'sales_order' => config('fcm.channels.sales_order'),           // 수주
            'purchase_order' => config('fcm.channels.purchase_order'),     // 발주
            'contract' => config('fcm.channels.contract'),                 // 계약
            default => config('fcm.channels.default'),                     // 일반 (출금, 카드 등)
        };
    }
}
