<?php

namespace App\Services;

use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use App\Models\OperatorQue;
use App\Models\Device;
use Exception;

/**
 * SHJ-5 空き待ち通知処理サービス
 *
 * 駐輪場の空き状況を確認し、空き待ち予約者への通知処理を実行する
 * 仕様書に基づくバックグラウンド定期バッチ処理
 */
class ShjFiveService
{
    /**
     * ShjEightService
     *
     * @var ShjEightService
     */
    protected $shjEightService;

    /**
     * コンストラクタ
     *
     * @param ShjEightService $shjEightService
     */
    public function __construct(ShjEightService $shjEightService)
    {
        $this->shjEightService = $shjEightService;
    }
    /**
     * SHJ-5 メイン処理を実行
     * 
     * 処理フロー:
     * 1. 駐輪場の空き状況を取得する
     * 2. 空き状況判定
     * 3. 空き待ち者の情報を取得する
     * 4. 取得件数判定
     * 5. 空き待ち者への通知、またはオペレーターキュー追加処理
     * 6. バッチ処理ログを作成する
     *
     * @return array 処理結果
     */
    public function executeParkVacancyNotification(): array
    {
        try {
            $startTime = now();
            Log::info('SHJ-5 空き待ち通知処理開始');

        // 処理統計
        $processedParksCount = 0;
        $vacantParksCount = 0;
        $totalWaitingUsers = 0;
        $notificationSuccessCount = 0;
        $operatorQueueCount = 0;
        $mailErrors = [];               // メール異常終了件数専用
        $errors = [];                   // 全体エラー収集用
        $allQueueItems = [];            // 全オペレーターキュー作成用データ

            // 【処理1】駐輪場の空き状況を取得する
            $parkVacancyList = $this->getParkVacancyStatus();
            Log::info('駐輪場空き状況取得完了', [
                'total_parks' => count($parkVacancyList)
            ]);

            // 各駐輪場に対する処理
            foreach ($parkVacancyList as $parkVacancyData) {
                // 配列をオブジェクトに変換
                $parkVacancy = (object) $parkVacancyData;
                $processedParksCount++;

                Log::info('駐輪場処理開始', [
                    'park_id' => $parkVacancy->park_id,
                    'park_name' => $parkVacancy->park_name,
                    'psection_id' => $parkVacancy->psection_id,
                    'ptype_id' => $parkVacancy->ptype_id,
                    'vacant_count' => $parkVacancy->vacant_count
                ]);

                // 【判断1】空き状況判定
                if ($parkVacancy->vacant_count < 1) {
                    Log::info('空きなし - 処理スキップ', [
                        'park_id' => $parkVacancy->park_id,
                        'vacant_count' => $parkVacancy->vacant_count
                    ]);
                    continue;
                }

                $vacantParksCount++;

                // 【処理2】空き待ち者の情報を取得する
                $waitingUsers = $this->getWaitingUsersInfo(
                    $parkVacancy->park_id,
                    $parkVacancy->psection_id,
                    $parkVacancy->ptype_id
                );

                // 【判断2】取得件数判定
                if (empty($waitingUsers)) {
                    Log::info('空き待ち者なし', [
                        'park_id' => $parkVacancy->park_id
                    ]);
                    continue;
                }

                $totalWaitingUsers += count($waitingUsers);
                Log::info('空き待ち者情報取得完了', [
                    'park_id' => $parkVacancy->park_id,
                    'waiting_users_count' => count($waitingUsers)
                ]);

                // 【処理3】空き待ち者への通知、またはオペレーターキュー追加処理
                $notificationResult = $this->processWaitingUsersNotification(
                    $waitingUsers,
                    $parkVacancy
                );

                $notificationSuccessCount += $notificationResult['notification_success_count'];
                $operatorQueueCount += $notificationResult['operator_queue_count'];

                if (!empty($notificationResult['errors'])) {
                    $mailErrors = array_merge($mailErrors, $notificationResult['errors']);
                    $errors = array_merge($errors, $notificationResult['errors']);
                }

                // オペレーターキュー作成用データを収集
                if (!empty($notificationResult['queue_items'])) {
                    $allQueueItems = array_merge($allQueueItems ?? [], $notificationResult['queue_items']);
                }
            }

            // 【処理4】仕様書準拠：先に呼び出し、成功時のみ内部変数を更新
            $queueErrorCount = 0;               // キュー登録異常終了件数（累計）
            $queueSuccessCount = 0;             // キュー登録正常終了件数（累計）
            
            foreach ($allQueueItems as $queueItem) {
                // 仕様書準拠：在呼叫前先計算"如果這次成功會是第幾件"，確保記錄反映最新件數
                $predictedSuccessCount = $queueSuccessCount + 1;
                $predictedErrorCount = $queueErrorCount;  // 暂时保持当前错误计数
                
                $queueResult = $this->addToOperatorQueue(
                    $queueItem['waiting_user'],
                    $queueItem['park_vacancy'],
                    $queueItem['batch_comment'],
                    $notificationSuccessCount,     // 最終メール正常終了件数
                    $predictedSuccessCount,       // 預測成功時的件數（包含本次）
                    count($mailErrors),           // 現在のメール異常終了件数（動態計算）
                    $predictedErrorCount          // 現在のキュー登録異常終了件数
                );
                
                // 仕様書：根据实际结果决定是否采用预测值
                if ($queueResult['success']) {
                    $queueSuccessCount = $predictedSuccessCount;  // 采用预测的成功计数
                } else {
                    $queueErrorCount++;                          // 失败时递增错误计数
                    
                    // 仕様書：包含具体错误消息，满足"エラーメッセージ／スタックトレースを保持"要求
                    $errorDetail = $queueResult['error'] ?? 'Unknown error';
                    $queueErrorInfo = sprintf('キュー登録失敗:予約ID:%d - %s', 
                        $queueItem['waiting_user']->reserve_id ?? 0, 
                        $errorDetail
                    );
                    $errors[] = $queueErrorInfo;  // 加入总错误统计（包含具体原因）
                    
                    Log::error('オペレーターキュー作成失敗', [
                        'user_id' => $queueItem['waiting_user']->user_id,
                        'reserve_id' => $queueItem['waiting_user']->reserve_id ?? 0,
                        'error' => $errorDetail
                    ]);
                }
            }

            $endTime = now();
            $duration = $startTime->diffInSeconds($endTime);

            Log::info('SHJ-5 空き待ち通知処理完了', [
                'duration_seconds' => $duration,
                'processed_parks_count' => $processedParksCount,
                'vacant_parks_count' => $vacantParksCount,
                'total_waiting_users' => $totalWaitingUsers,
                'notification_success_count' => $notificationSuccessCount,
                'operator_queue_success_count' => $queueSuccessCount,  // 仕様書：正常完了件数
                'queue_error_count' => $queueErrorCount,
                'mail_error_count' => count($mailErrors),               // メール異常終了件数（分離）
                'total_error_count' => count($errors)                   // 全体エラー件数
            ]);

            // 仕様書に基づく内部変数.ステータスコメント生成
            $statusComment = sprintf(
                'メール正常終了件数：%d／メール異常終了件数：%d／キュー登録正常終了件数：%d／キュー登録異常終了件数：%d',
                $notificationSuccessCount,
                count($mailErrors),         // メール異常終了件数（キュー失敗を除外）
                $queueSuccessCount ?? 0,    // 実際のキュー登録成功件数
                $queueErrorCount ?? 0       // 実際のキュー登録失敗件数
            );

            // SHJ-8 バッチ処理ログ作成
            try {
                $device = Device::orderBy('device_id')->first();
                $deviceId = $device ? $device->device_id : 1;
                $today = now()->format('Y/m/d');

                $this->shjEightService->execute(
                    $deviceId,
                    'SHJ-5',
                    'SHJ-5空き待ち通知',
                    'success',
                    $statusComment,
                    $today,
                    $today
                );

                Log::info('SHJ-8 バッチ処理ログ作成完了');
            } catch (Exception $e) {
                Log::error('SHJ-8 バッチ処理ログ作成エラー', [
                    'error' => $e->getMessage()
                ]);
            }

            return [
                'success' => true,
                'message' => 'SHJ-5 空き待ち通知処理が正常に完了しました',
                'processed_parks_count' => $processedParksCount,
                'vacant_parks_count' => $vacantParksCount,
                'total_waiting_users' => $totalWaitingUsers,
                'notification_success_count' => $notificationSuccessCount,
                'operator_queue_count' => $queueSuccessCount ?? 0,  // 仕様書：正常完了件数を使用
                'error_count' => count($errors),
                'errors' => $errors,
                'duration_seconds' => $duration,
                'status_comment' => $statusComment  // SHJ-8用の完全なステータスコメント
            ];

        } catch (Exception $e) {
            Log::error('SHJ-5 空き待ち通知処理でエラーが発生', [
                'error' => $e->getMessage(),
                'trace' => $e->getTraceAsString()
            ]);

            return [
                'success' => false,
                'message' => 'SHJ-5 空き待ち通知処理でエラーが発生: ' . $e->getMessage(),
                'error_details' => $e->getMessage()
            ];
        }
    }

    /**
     * 【処理1】駐輪場の空き状況を取得する
     * 
     * 仕様書に基づくSQL:
     * - zone表から標準台数と現在の契約台数を比較
     * - 空きがある駐輪場の情報を取得
     *
     * @return array 駐輪場空き状況リスト
     */
    private function getParkVacancyStatus(): array
    {
        try {
            // ゾーン毎の契約台数を取得
            $contractCounts = DB::table('regular_contract as T1')
                ->select([
                    'T1.park_id',
                    'T1.psection_id',
                    'T5.ptype_id',
                    DB::raw('count(T1.contract_id) as contract_count')
                ])
                ->join('park as T2', 'T1.park_id', '=', 'T2.park_id')
                ->join('price_a as T5', function($join) {
                    $join->on('T1.park_id', '=', 'T5.park_id')
                         ->on('T1.price_parkplaceid', '=', 'T5.price_parkplaceid')
                         ->on('T1.psection_id', '=', 'T5.psection_id');
                })
                ->where([
                    ['T1.contract_flag', '=', 1],           // 有効契約
                    ['T2.park_close_flag', '=', 0],         // 駐輪場未閉鎖
                ])
                // 契約有効期間内の条件
                ->whereRaw("date_format(now(), '%Y%m%d') BETWEEN T1.contract_periods AND T1.contract_periode")
                ->groupBy(['T1.park_id', 'T1.psection_id', 'T5.ptype_id'])
                ->get()
                ->keyBy(function($item) {
                    return $item->park_id . '_' . $item->psection_id . '_' . $item->ptype_id;
                });

            // ゾーン情報と照合して空き状況を算出
            $vacancyList = DB::table('zone as T1')
                ->select([
                    'T1.park_id',
                    'T2.park_name',
                    'T1.psection_id',
                    'T1.ptype_id',
                    'T1.zone_standard',
                    'T3.psection_subject',
                    'T4.ptype_subject'
                ])
                ->join('park as T2', 'T1.park_id', '=', 'T2.park_id')
                ->join('psection as T3', 'T1.psection_id', '=', 'T3.psection_id')
                ->join('ptype as T4', 'T1.ptype_id', '=', 'T4.ptype_id')
                ->where([
                    ['T1.delete_flag', '=', 0],           // ゾーン有効
                    ['T2.park_close_flag', '=', 0],       // 駐輪場開設
                ])
                ->get()
                ->map(function($zone) use ($contractCounts) {
                    $key = $zone->park_id . '_' . $zone->psection_id . '_' . $zone->ptype_id;
                    $contractCount = isset($contractCounts[$key]) ? $contractCounts[$key]->contract_count : 0;
                    
                    $zone->contract_count = $contractCount;
                    $zone->vacant_count = max(0, $zone->zone_standard - $contractCount);
                    
                    return $zone;
                })
                ->filter(function($zone) {
                    return $zone->vacant_count > 0; // 空きがあるもののみ
                })
                ->values();

            Log::info('駐輪場空き状況算出完了', [
                'total_zones' => count($vacancyList),
                'vacant_zones' => $vacancyList->filter(function($v) { 
                    return $v->vacant_count > 0; 
                })->count()
            ]);

            return $vacancyList->toArray();

        } catch (Exception $e) {
            Log::error('駐輪場空き状況取得エラー', [
                'error' => $e->getMessage()
            ]);
            throw $e;
        }
    }

    /**
     * 【処理2】空き待ち者の情報を取得する
     * 
     * 仕様書に基づく取得条件：
     * - 契約未紐付（contract_id IS NULL）
     * - 退会でない（user_quit_flag <> 1）
     * - 有効な予約（valid_flag = 1）
     * - 予約日時順で取得（reserve_date昇順）
     *
     * @param int $parkId 駐輪場ID
     * @param int $psectionId 車種区分ID
     * @param int $ptypeId 駐輪分類ID
     * @return array 空き待ち者情報リスト
     */
    private function getWaitingUsersInfo(int $parkId, int $psectionId, int $ptypeId): array
    {
        try {
            $waitingUsers = DB::table('reserve as T1')
                ->select([
                    'T1.reserve_id',
                    'T1.user_id',
                    'T1.park_id',
                    'T1.psection_id',
                    'T1.ptype_id',
                    'T1.reserve_order',
                    'T1.reserve_date',
                    'T1.reserve_manual',            // 手動通知フラグ
                    'T1.contract_id',               // 契約紐付確認用
                    'T2.user_name',
                    'T2.user_primemail',
                    'T2.user_submail',              // 副メールアドレス
                    'T2.user_manual_regist_flag',   // 手動登録フラグ
                    'T2.user_quit_flag',            // 退会フラグ
                    'T3.park_name',
                    'T4.psection_subject',
                    'T5.ptype_subject'
                ])
                ->join('user as T2', 'T1.user_id', '=', 'T2.user_id')
                ->join('park as T3', 'T1.park_id', '=', 'T3.park_id')
                ->join('psection as T4', 'T1.psection_id', '=', 'T4.psection_id')
                ->join('ptype as T5', 'T1.ptype_id', '=', 'T5.ptype_id')
                ->where([
                    ['T1.park_id', '=', $parkId],
                    ['T1.psection_id', '=', $psectionId],
                    ['T1.ptype_id', '=', $ptypeId],
                    ['T1.valid_flag', '=', 1],              // 有効な予約
                    ['T2.user_quit_flag', '<>', 1]          // 退会でない
                ])
                ->whereNull('T1.contract_id')               // 契約未紐付
                ->orderBy('T1.reserve_date', 'asc')         // 仕様書に基づく予約日時順
                ->get()
                ->toArray();

            Log::info('空き待ち者情報取得完了', [
                'park_id' => $parkId,
                'psection_id' => $psectionId,
                'ptype_id' => $ptypeId,
                'waiting_users_count' => count($waitingUsers)
            ]);

            return $waitingUsers;

        } catch (Exception $e) {
            Log::error('空き待ち者情報取得エラー', [
                'park_id' => $parkId,
                'psection_id' => $psectionId,
                'ptype_id' => $ptypeId,
                'error' => $e->getMessage()
            ]);
            throw $e;
        }
    }

    /**
     * 【処理3】空き待ち者への通知、またはオペレーターキュー追加処理
     * 
     * 仕様書に基づく分岐処理：
     * - 手動通知フラグ判定（reserve_manual）
     * - メール送信成功時のreserve.sent_date更新
     * - 失敗時のオペレーターキュー追加（最終統計で処理）
     *
     * @param array $waitingUsers 空き待ち者リスト
     * @param object $parkVacancy 駐輪場空き情報
     * @return array 通知処理結果
     */
    private function processWaitingUsersNotification(array $waitingUsers, object $parkVacancy): array
    {
        $notificationSuccessCount = 0;
        $operatorQueueCount = 0;
        $errors = [];
        $queueItems = [];  // オペレーターキュー作成用データ収集

        try {
            // 空きがある分だけ処理（先着順）
            $availableSpots = min($parkVacancy->vacant_count, count($waitingUsers));
            
            for ($i = 0; $i < $availableSpots; $i++) {
                $waitingUserData = $waitingUsers[$i];
                // 配列をオブジェクトに変換
                $waitingUser = (object) $waitingUserData;
                
                try {
                    // 【仕様判断】手動通知フラグチェック
                    if ($waitingUser->reserve_manual == 1) {
                        // 手動通知 → オペレーターキュー作成データ収集
                        $batchComment = '手動通知フラグ設定のため予約ID:' . $waitingUser->reserve_id;
                        $queueItems[] = [
                            'waiting_user' => $waitingUser,
                            'park_vacancy' => $parkVacancy,
                            'batch_comment' => $batchComment
                        ];
                        $operatorQueueCount++;
                        
                        Log::info('手動通知フラグによりオペレーターキュー登録予定', [
                            'user_id' => $waitingUser->user_id,
                            'reserve_id' => $waitingUser->reserve_id
                        ]);
                    } else {
                        // 自動通知 → メール送信を試行
                        $mailResult = $this->sendVacancyNotificationMail($waitingUser, $parkVacancy);
                        
                        if ($mailResult['success']) {
                            // メール送信成功 → reserve.sent_date更新
                            $this->updateReserveSentDate($waitingUser->reserve_id);
                            $notificationSuccessCount++;
                            
                            Log::info('空き待ち通知メール送信成功', [
                                'user_id' => $waitingUser->user_id,
                                'reserve_id' => $waitingUser->reserve_id,
                                'park_id' => $parkVacancy->park_id
                            ]);
                        } else {
                            // メール送信失敗 → オペレーターキュー作成データ収集
                            $shjSevenError = $mailResult['error'] ?? $mailResult['message'] ?? 'SHJ-7メール送信エラー';
                            $batchComment = $shjSevenError . '予約ID:' . $waitingUser->reserve_id;
                            $queueItems[] = [
                                'waiting_user' => $waitingUser,
                                'park_vacancy' => $parkVacancy,
                                'batch_comment' => $batchComment
                            ];
                            $operatorQueueCount++;
                            $errors[] = $shjSevenError;
                        }
                    }

                } catch (Exception $e) {
                    Log::error('空き待ち者通知処理エラー', [
                        'user_id' => $waitingUser->user_id,
                        'reserve_id' => $waitingUser->reserve_id,
                        'error' => $e->getMessage()
                    ]);
                    
                    // エラー発生時もオペレーターキュー作成データ収集
                    $batchComment = 'システムエラー:' . $e->getMessage() . '予約ID:' . $waitingUser->reserve_id;
                    $queueItems[] = [
                        'waiting_user' => $waitingUser,
                        'park_vacancy' => $parkVacancy,
                        'batch_comment' => $batchComment
                    ];
                    $operatorQueueCount++;
                    $errors[] = $e->getMessage();
                }
            }

            return [
                'notification_success_count' => $notificationSuccessCount,
                'operator_queue_count' => $operatorQueueCount,
                'errors' => $errors,
                'queue_items' => $queueItems  // 後でキュー作成用
            ];

        } catch (Exception $e) {
            Log::error('空き待ち者通知処理全体エラー', [
                'park_id' => $parkVacancy->park_id,
                'error' => $e->getMessage()
            ]);
            throw $e;
        }
    }

    /**
     * 空き待ち通知メールを送信
     * 
     * 仕様書に基づくSHJ-7呼び出し：
     * - 主メールアドレス・副メールアドレスを正しく渡す
     * - 必要なパラメータを全て設定
     *
     * @param object $waitingUser 空き待ち者情報
     * @param object $parkVacancy 駐輪場空き情報
     * @return array 送信結果
     */
    private function sendVacancyNotificationMail(object $waitingUser, object $parkVacancy): array
    {
        try {
            // ShjMailSendServiceを利用してメール送信
            $mailService = app(ShjMailSendService::class);
            
            // 空き待ち通知用のメールテンプレートID（予約告知通知）
            // OperatorQueの定数と合わせて4番を使用
            $mailTemplateId = 4; // 予約告知通知のテンプレートID
            
            // 仕様書No1/No2に基づく主メール・副メール設定
            $mainEmail = $waitingUser->user_primemail ?? '';
            $subEmail = $waitingUser->user_submail ?? '';
            
            // メール送信実行（仕様書準拠）
            $mailResult = $mailService->executeMailSend(
                $mainEmail,
                $subEmail,
                $mailTemplateId
            );

            // SHJ-7の結果を標準形式に変換（result: 0=成功, 1=失敗）
            $success = ($mailResult['result'] ?? 1) === 0;

            Log::info('空き待ち通知メール送信試行完了', [
                'user_id' => $waitingUser->user_id,
                'main_email' => $mainEmail,
                'sub_email' => $subEmail,
                'mail_template_id' => $mailTemplateId,
                'result' => $mailResult['result'] ?? 1,
                'success' => $success
            ]);

            return [
                'success' => $success,
                'result' => $mailResult['result'] ?? 1,
                'error' => $mailResult['error_info'] ?? null,
                'message' => $success ? 'メール送信成功' : ($mailResult['error_info'] ?? 'メール送信失敗')
            ];

        } catch (Exception $e) {
            Log::error('空き待ち通知メール送信エラー', [
                'user_id' => $waitingUser->user_id,
                'main_email' => $waitingUser->user_primemail ?? '',
                'sub_email' => $waitingUser->user_submail ?? '',
                'error' => $e->getMessage()
            ]);

            return [
                'success' => false,
                'error' => $e->getMessage()
            ];
        }
    }

    /**
     * reserve.sent_date及びvalid_flag更新
     * 
     * 仕様書準拠：メール送信成功時にreserve.sent_dateとvalid_flag=0を同時更新
     * 重複通知を防ぎ、処理済みマークを設定
     *
     * @param int $reserveId 予約ID
     * @return void
     */
    private function updateReserveSentDate(int $reserveId): void
    {
        try {
            DB::table('reserve')
                ->where('reserve_id', $reserveId)
                ->update([
                    'sent_date' => now()->format('Y-m-d H:i:s'),
                    'valid_flag' => 0,                          // 仕様書：メール送信成功時に0に更新
                    'updated_at' => now()
                ]);

            Log::info('reserve.sent_date及びvalid_flag更新完了', [
                'reserve_id' => $reserveId,
                'sent_date' => now()->format('Y-m-d H:i:s'),
                'valid_flag' => 0
            ]);

        } catch (Exception $e) {
            Log::error('reserve.sent_date及びvalid_flag更新エラー', [
                'reserve_id' => $reserveId,
                'error' => $e->getMessage()
            ]);
            throw $e;
        }
    }

    /**
     * オペレーターキューに追加
     * 
     * 仕様書に基づくキュー登録：
     * - que_comment: 空文字列
     * - que_status_comment: 仕様書完全準拠形式（統計情報含む）
     * - operator_id: 9999999固定
     *
     * @param object $waitingUser 空き待ち者情報
     * @param object $parkVacancy 駐輪場空き情報
     * @param string $batchComment 内部変数.バッチコメント
     * @param int $mailSuccessCount メール正常終了件数
     * @param int $queueSuccessCount キュー登録正常終了件数
     * @param int $mailErrorCount メール異常終了件数
     * @param int $queueErrorCount キュー登録異常終了件数
     * @return array 追加結果
     */
    private function addToOperatorQueue(object $waitingUser, object $parkVacancy, string $batchComment, int $mailSuccessCount, int $queueSuccessCount, int $mailErrorCount, int $queueErrorCount): array
    {
        try {
            // 仕様書完全準拠：駐輪場名／駐輪分類名／車種区分名／空き台数…／対象予約ID…／内部変数.バッチコメント／内部変数.メール正常終了件数…メール異常終了件数…キュー登録正常終了件数…キュー登録異常終了件数…
            $statusComment = sprintf(
                '%s／%s／%s／空き台数：%d台／対象予約ID：%d／%s／メール正常終了件数：%d／メール異常終了件数：%d／キュー登録正常終了件数：%d／キュー登録異常終了件数：%d',
                $waitingUser->park_name ?? '',
                $waitingUser->ptype_subject ?? '',    // 駐輪分類名
                $waitingUser->psection_subject ?? '', // 車種区分名
                $parkVacancy->vacant_count ?? 0,
                $waitingUser->reserve_id ?? 0,
                $batchComment,                         // 内部変数.バッチコメント
                $mailSuccessCount,                     // 内部変数.メール正常終了件数
                $mailErrorCount,
                $queueSuccessCount,
                $queueErrorCount
            );

            OperatorQue::create([
                'que_class' => 4,                           // 予約告知通知
                'user_id' => $waitingUser->user_id,
                'contract_id' => null,
                'park_id' => $waitingUser->park_id,
                'que_comment' => '',                        // 仕様書：空文字列
                'que_status' => 1,                          // キュー発生
                'que_status_comment' => $statusComment,     // 仕様書：完全準拠形式
                'work_instructions' => '空き待ち者への連絡をお願いします。',
                'operator_id' => 9999999,                   // 仕様書：固定値9999999
            ]);

            Log::info('オペレーターキュー追加成功', [
                'user_id' => $waitingUser->user_id,
                'park_id' => $waitingUser->park_id,
                'reserve_id' => $waitingUser->reserve_id,
                'que_class' => 4,
                'operator_id' => 9999999,
                'batch_comment' => $batchComment,
                'mail_success_count' => $mailSuccessCount,
                'mail_error_count' => $mailErrorCount,
                'queue_success_count' => $queueSuccessCount,
                'queue_error_count' => $queueErrorCount,
                'status_comment' => $statusComment
            ]);

            return ['success' => true];

        } catch (Exception $e) {
            Log::error('オペレーターキュー追加エラー', [
                'user_id' => $waitingUser->user_id,
                'park_id' => $waitingUser->park_id,
                'reserve_id' => $waitingUser->reserve_id ?? null,
                'batch_comment' => $batchComment,
                'error' => $e->getMessage()
            ]);

            return [
                'success' => false,
                'error' => $e->getMessage()
            ];
        }
    }
}
