<?php

namespace App\Services;

use App\Models\Park;
use App\Models\User;
use App\Models\RegularContract;
use App\Models\Batch\BatchLog;
use App\Services\ShjMailSendService;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\DB;
use Carbon\Carbon;

/**
 * SHJ-3 定期更新リマインダー処理サービス
 * 
 * 駐輪場の定期契約更新対象者に対するリマインダー処理を実行するビジネスロジック
 * バッチ処理「SHJ-3定期更新リマインダー」の核となる処理を担当
 */
class ShjThreeService
{
    /**
     * Park モデル
     *
     * @var Park
     */
    protected $parkModel;

    /**
     * User モデル
     *
     * @var User
     */
    protected $userModel;

    /**
     * RegularContract モデル
     *
     * @var RegularContract
     */
    protected $contractModel;

    /**
     * BatchLog モデル
     *
     * @var BatchLog
     */
    protected $batchLogModel;

    /**
     * ShjMailSendService
     *
     * @var ShjMailSendService
     */
    protected $mailSendService;

    /**
     * コンストラクタ
     *
     * @param Park $parkModel
     * @param User $userModel
     * @param RegularContract $contractModel
     * @param BatchLog $batchLogModel
     * @param ShjMailSendService $mailSendService
     */
    public function __construct(
        Park $parkModel,
        User $userModel,
        RegularContract $contractModel,
        BatchLog $batchLogModel,
        ShjMailSendService $mailSendService
    ) {
        $this->parkModel = $parkModel;
        $this->userModel = $userModel;
        $this->contractModel = $contractModel;
        $this->batchLogModel = $batchLogModel;
        $this->mailSendService = $mailSendService;
    }

    /**
     * SHJ-3 定期更新リマインダー処理メイン実行
     * 
     * 処理フロー:
     * 【処理0】駐輪場マスタの情報を取得する
     * 【判断0】当該駐輪場実行タイミングチェック
     * 【処理2】定期更新対象者を取得する
     * 【判断2】利用者有無をチェック
     * 【処理3】対象者向けにメール送信、またはオペレーターキュー追加処理
     * 【処理4】バッチ処理ログを作成する
     *
     * @return array 処理結果
     */
    public function executeReminderProcess(): array
    {
        $batchLogId = null;
        $processedParksCount = 0;
        $totalTargetUsers = 0;
        $mailSuccessCount = 0;
        $mailErrorCount = 0;
        $operatorQueueCount = 0;
        
        try {
            // バッチ処理開始ログ作成
            $batchLog = BatchLog::createBatchLog(
                'shj3',
                BatchLog::STATUS_START,
                [],
                'SHJ-3 定期更新リマインダー処理開始'
            );
            $batchLogId = $batchLog->id;

            Log::info('SHJ-3 定期更新リマインダー処理開始', [
                'batch_log_id' => $batchLogId
            ]);

            // 【処理0】駐輪場マスタの情報を取得する
            $parkList = $this->getParkMasterInfo();

            if (empty($parkList)) {
                $message = '対象の駐輪場マスタが見つかりません';
                
                $batchLog->update([
                    'status' => BatchLog::STATUS_ERROR,
                    'end_time' => now(),
                    'message' => $message,
                    'error_details' => $message,
                    'error_count' => 1
                ]);
                
                return [
                    'success' => false,
                    'message' => $message,
                    'processed_parks_count' => 0,
                    'total_target_users' => 0,
                    'mail_success_count' => 0,
                    'mail_error_count' => 0,
                    'operator_queue_count' => 0,
                    'batch_log_id' => $batchLogId
                ];
            }

            // 各駐輪場に対する処理ループ
            foreach ($parkList as $park) {
                Log::info('駐輪場処理開始', [
                    'park_id' => $park->park_id,
                    'park_name' => $park->park_name
                ]);

                // 【判断0】当該駐輪場実行タイミングチェック
                $timingCheckResult = $this->checkExecutionTiming($park);
                
                if (!$timingCheckResult['should_execute']) {
                    Log::info('実行タイミング対象外', [
                        'park_id' => $park->park_id,
                        'reason' => $timingCheckResult['reason']
                    ]);
                    continue;
                }

                $processedParksCount++;

                // 【処理2】定期更新対象者を取得する
                $targetUsers = $this->getRegularUpdateTargetUsers($park->park_id);

                // 【判断2】利用者有無をチェック
                if (empty($targetUsers)) {
                    Log::info('利用者なし', [
                        'park_id' => $park->park_id
                    ]);
                    continue;
                }

                $totalTargetUsers += count($targetUsers);

                // 【処理3】対象者向けにメール送信、またはオペレーターキュー追加処理
                foreach ($targetUsers as $targetUser) {
                    $processResult = $this->processTargetUser($targetUser);
                    
                    if ($processResult['type'] === 'mail_success') {
                        $mailSuccessCount++;
                    } elseif ($processResult['type'] === 'mail_error') {
                        $mailErrorCount++;
                    } elseif ($processResult['type'] === 'operator_queue') {
                        $operatorQueueCount++;
                    }
                }

                Log::info('駐輪場処理完了', [
                    'park_id' => $park->park_id,
                    'target_users_count' => count($targetUsers)
                ]);
            }

            // 【処理4】バッチ処理ログを作成する（SHJ-8呼び出し）
            $this->createShjBatchLog([
                'processed_parks_count' => $processedParksCount,
                'total_target_users' => $totalTargetUsers,
                'mail_success_count' => $mailSuccessCount,
                'mail_error_count' => $mailErrorCount,
                'operator_queue_count' => $operatorQueueCount
            ]);

            // バッチ処理完了ログ更新
            $batchLog->update([
                'status' => BatchLog::STATUS_SUCCESS,
                'end_time' => now(),
                'message' => 'SHJ-3 定期更新リマインダー処理正常完了',
                'success_count' => 1,
                'parameters' => [
                    'processed_parks_count' => $processedParksCount,
                    'total_target_users' => $totalTargetUsers,
                    'mail_success_count' => $mailSuccessCount,
                    'mail_error_count' => $mailErrorCount,
                    'operator_queue_count' => $operatorQueueCount,
                    'executed_at' => now()->toISOString()
                ]
            ]);

            Log::info('SHJ-3 定期更新リマインダー処理完了', [
                'batch_log_id' => $batchLogId,
                'processed_parks_count' => $processedParksCount,
                'total_target_users' => $totalTargetUsers
            ]);

            return [
                'success' => true,
                'message' => 'SHJ-3 定期更新リマインダー処理が正常に完了しました',
                'processed_parks_count' => $processedParksCount,
                'total_target_users' => $totalTargetUsers,
                'mail_success_count' => $mailSuccessCount,
                'mail_error_count' => $mailErrorCount,
                'operator_queue_count' => $operatorQueueCount,
                'batch_log_id' => $batchLogId
            ];

        } catch (\Exception $e) {
            $errorMessage = 'SHJ-3 定期更新リマインダー処理でエラーが発生: ' . $e->getMessage();
            
            if (isset($batchLog) && $batchLog) {
                $batchLog->update([
                    'status' => BatchLog::STATUS_ERROR,
                    'end_time' => now(),
                    'message' => $errorMessage,
                    'error_details' => $e->getMessage(),
                    'error_count' => 1
                ]);
            }

            Log::error('SHJ-3 定期更新リマインダー処理エラー', [
                'batch_log_id' => $batchLogId,
                'exception' => $e->getMessage(),
                'trace' => $e->getTraceAsString()
            ]);

            return [
                'success' => false,
                'message' => $errorMessage,
                'details' => $e->getMessage(),
                'processed_parks_count' => $processedParksCount,
                'total_target_users' => $totalTargetUsers,
                'mail_success_count' => $mailSuccessCount,
                'mail_error_count' => $mailErrorCount,
                'operator_queue_count' => $operatorQueueCount,
                'batch_log_id' => $batchLogId
            ];
        }
    }

    /**
     * 【処理0】駐輪場マスタの情報を取得する
     * 
     * 仕様書に基づくSQLクエリ:
     * SELECT 駐輪場ID, 駐輪場名, 更新期間開始日, 更新期間開始時, 
     *        更新期間終了日, 更新期間終了時, リマインダー種別, リマインダー時間
     * FROM 駐輪場マスタ
     * WHERE 閉設フラグ = 0
     * ORDER BY 駐輪場ふりがな asc
     *
     * @return array 駐輪場マスタ情報
     */
    private function getParkMasterInfo(): array
    {
        try {
            $parkInfo = DB::table('park')
                ->select([
                    'park_id',
                    'park_name', 
                    'renew_start_date',
                    'renew_start_time',
                    'renew_end_date',
                    'renew_end_time',
                    'reminder_type',
                    'reminder_time'
                ])
                ->where('park_close_flag', 0)
                ->orderBy('park_ruby', 'asc')
                ->get()
                ->toArray();

            Log::info('駐輪場マスタ情報取得完了', [
                'park_count' => count($parkInfo)
            ]);

            return $parkInfo;

        } catch (\Exception $e) {
            Log::error('駐輪場マスタ情報取得エラー', [
                'error' => $e->getMessage()
            ]);

            throw $e;
        }
    }

    /**
     * 【判断0】当該駐輪場実行タイミングチェック
     * 
     * 仕様書に基づく複雑なリマインダー時期判定:
     * - パターンA: 月を跨らない場合（更新期間開始日 <= 更新期間終了日）
     * - パターンB: 月を跨る場合（更新期間開始日 > 更新期間終了日）
     * - リマインダー種別による実行判定
     *
     * @param object $park 駐輪場情報
     * @return array 実行タイミング判定結果
     */
    private function checkExecutionTiming($park): array
    {
        try {
            $today = Carbon::now();
            $currentDate = $today->format('Y-m-d');
            
            // 更新期間の日付を取得
            $startDate = Carbon::parse($park->renew_start_date);
            $endDate = Carbon::parse($park->renew_end_date);
            
            Log::info('実行タイミングチェック開始', [
                'park_id' => $park->park_id,
                'current_date' => $currentDate,
                'start_date' => $startDate->format('Y-m-d'),
                'end_date' => $endDate->format('Y-m-d'),
                'reminder_type' => $park->reminder_type
            ]);

            // パターン判定: 月を跨るかどうか
            $isPatternA = $startDate->lte($endDate); // パターンA: 月を跨らない
            $isPatternB = !$isPatternA; // パターンB: 月を跨る

            // 現在日付が更新期間内かチェック
            $isWithinUpdatePeriod = false;
            
            if ($isPatternA) {
                // パターンA: 更新期間開始日 <= 現在日 <= 更新期間終了日
                $isWithinUpdatePeriod = $today->between($startDate, $endDate);
            } else {
                // パターンB: 月を跨る場合の判定
                // 現在日 >= 更新期間開始日 OR 現在日 <= 更新期間終了日
                $isWithinUpdatePeriod = $today->gte($startDate) || $today->lte($endDate);
            }

            if (!$isWithinUpdatePeriod) {
                return [
                    'should_execute' => false,
                    'reason' => '更新期間外のため実行対象外',
                    'pattern' => $isPatternA ? 'A' : 'B'
                ];
            }

            // リマインダー種別による実行判定
            $reminderExecutionResult = $this->checkReminderTiming($park, $today, $startDate, $endDate, $isPatternA);

            Log::info('実行タイミングチェック完了', [
                'park_id' => $park->park_id,
                'should_execute' => $reminderExecutionResult['should_execute'],
                'pattern' => $isPatternA ? 'A' : 'B',
                'reminder_result' => $reminderExecutionResult
            ]);

            return $reminderExecutionResult;

        } catch (\Exception $e) {
            Log::error('実行タイミングチェックエラー', [
                'park_id' => $park->park_id,
                'error' => $e->getMessage()
            ]);

            throw $e;
        }
    }

    /**
     * リマインダー時期の詳細判定
     * 
     * 仕様書の複雑なリマインダー種別判定を実装
     * パターンA/Bに基づく詳細な日付計算ロジック
     *
     * @param object $park 駐輪場情報
     * @param Carbon $today 現在日
     * @param Carbon $startDate 更新期間開始日
     * @param Carbon $endDate 更新期間終了日
     * @param bool $isPatternA パターンAかどうか
     * @return array リマインダー実行判定結果
     */
    private function checkReminderTiming($park, Carbon $today, Carbon $startDate, Carbon $endDate, bool $isPatternA): array
    {
        $reminderType = $park->reminder_type ?? 0;
        
        // リマインダー種別 = 0 の場合は実行しない
        if ($reminderType == 0) {
            return [
                'should_execute' => false,
                'reason' => 'リマインダー種別=0のため実行対象外'
            ];
        }

        // 仕様書に基づく詳細なリマインダー時期判定
        $executionCheck = $this->performDetailedReminderCheck($park, $today, $startDate, $endDate, $isPatternA);

        return [
            'should_execute' => $executionCheck['should_execute'],
            'reason' => $executionCheck['reason'],
            'reminder_type' => $reminderType,
            'pattern' => $isPatternA ? 'A' : 'B',
            'execution_details' => $executionCheck
        ];
    }

    /**
     * 仕様書に基づく詳細なリマインダー実行判定
     * 
     * 複雑な条件分岐を含む実行フラグ判定処理
     * - パターンA/Bによる分岐
     * - リマインダー種別による日数計算
     * - 月跨ぎ処理の考慮
     *
     * @param object $park 駐輪場情報
     * @param Carbon $today 現在日
     * @param Carbon $startDate 更新期間開始日
     * @param Carbon $endDate 更新期間終了日
     * @param bool $isPatternA パターンAかどうか
     * @return array 実行判定詳細結果
     */
    private function performDetailedReminderCheck($park, Carbon $today, Carbon $startDate, Carbon $endDate, bool $isPatternA): array
    {
        $reminderType = $park->reminder_type ?? 0;
        
        // 内部変数 更新パターン判定
        $updatePattern = '';
        
        if ($isPatternA) {
            // パターンA: 月を跨らない場合
            if ($startDate->lte($endDate)) {
                $updatePattern = 'A';
            } else {
                $updatePattern = 'B'; // 実際はパターンBになる
            }
        } else {
            // パターンB: 月を跨る場合  
            $updatePattern = 'B';
        }

        // 実行フラグ判定処理
        $executionFlag = $this->calculateExecutionFlag($today, $startDate, $endDate, $reminderType, $updatePattern);

        Log::info('詳細リマインダー判定完了', [
            'park_id' => $park->park_id,
            'reminder_type' => $reminderType,
            'update_pattern' => $updatePattern,
            'execution_flag' => $executionFlag,
            'today' => $today->format('Y-m-d'),
            'start_date' => $startDate->format('Y-m-d'),
            'end_date' => $endDate->format('Y-m-d')
        ]);

        return [
            'should_execute' => $executionFlag['should_execute'],
            'reason' => $executionFlag['reason'],
            'update_pattern' => $updatePattern,
            'execution_details' => $executionFlag
        ];
    }

    /**
     * 実行フラグ計算処理
     * 
     * 仕様書の複雑な分岐条件に基づく実行判定
     *
     * @param Carbon $today 現在日
     * @param Carbon $startDate 更新期間開始日
     * @param Carbon $endDate 更新期間終了日
     * @param int $reminderType リマインダー種別
     * @param string $updatePattern 更新パターン（A/B）
     * @return array 実行フラグ判定結果
     */
    private function calculateExecutionFlag(Carbon $today, Carbon $startDate, Carbon $endDate, int $reminderType, string $updatePattern): array
    {
        // リマインダー種別による実行判定
        switch ($reminderType) {
            case 1: // -1日前
                return $this->checkReminderType1($today, $startDate, $endDate, $updatePattern);
            case 2: // -2日前
                return $this->checkReminderType2($today, $startDate, $endDate, $updatePattern);
            default:
                return [
                    'should_execute' => false,
                    'reason' => "未対応のリマインダー種別: {$reminderType}"
                ];
        }
    }

    /**
     * リマインダー種別=1（-1日前）の判定
     *
     * @param Carbon $today 現在日
     * @param Carbon $startDate 更新期間開始日
     * @param Carbon $endDate 更新期間終了日
     * @param string $updatePattern 更新パターン
     * @return array 判定結果
     */
    private function checkReminderType1(Carbon $today, Carbon $startDate, Carbon $endDate, string $updatePattern): array
    {
        // 更新期間終了日の1日前が実行日
        $executionDate = $endDate->copy()->subDay();
        
        if ($today->isSameDay($executionDate)) {
            return [
                'should_execute' => true,
                'reason' => '-1日前のリマインダー実行日',
                'execution_date' => $executionDate->format('Y-m-d')
            ];
        }

        return [
            'should_execute' => false,
            'reason' => "リマインダー実行日({$executionDate->format('Y-m-d')})ではない（現在: {$today->format('Y-m-d')}）",
            'execution_date' => $executionDate->format('Y-m-d')
        ];
    }

    /**
     * リマインダー種別=2（-2日前）の判定
     *
     * @param Carbon $today 現在日
     * @param Carbon $startDate 更新期間開始日
     * @param Carbon $endDate 更新期間終了日
     * @param string $updatePattern 更新パターン
     * @return array 判定結果
     */
    private function checkReminderType2(Carbon $today, Carbon $startDate, Carbon $endDate, string $updatePattern): array
    {
        // 更新期間終了日の2日前が実行日
        $executionDate = $endDate->copy()->subDays(2);
        
        if ($today->isSameDay($executionDate)) {
            return [
                'should_execute' => true,
                'reason' => '-2日前のリマインダー実行日',
                'execution_date' => $executionDate->format('Y-m-d')
            ];
        }

        return [
            'should_execute' => false,
            'reason' => "リマインダー実行日({$executionDate->format('Y-m-d')})ではない（現在: {$today->format('Y-m-d')}）",
            'execution_date' => $executionDate->format('Y-m-d')
        ];
    }

    /**
     * 【処理2】定期更新対象者を取得する
     * 
     * 仕様書に基づく複雑なSQLクエリ:
     * 定期契約マスタ T1 と 利用者マスタ T2 を結合して
     * 更新対象者の情報を取得する
     *
     * @param int $parkId 駐輪場ID
     * @return array 定期更新対象者情報
     */
    private function getRegularUpdateTargetUsers(int $parkId): array
    {
        try {
            $currentDate = Carbon::now()->format('Y-m-d');

            // 仕様書に記載されたSQLクエリに基づく対象者取得
            $targetUsers = DB::table('regular_contract as T1')
                ->select([
                    'T1.contract_id as 定期契約内ID',
                    'T1.park_id as 駐輪場ID',
                    'T2.user_id as 利用者ID',
                    'T2.user_manual_regist_flag as 手動登録フラグ',
                    'T2.user_primemail as メールアドレス',
                    'T2.user_submail as 予備メールアドレス',
                    'T2.user_name as 氏名',
                    'T1.contract_periode as 有効期間E'
                ])
                ->join('user as T2', 'T1.user_id', '=', 'T2.user_id')
                ->where('T1.park_id', $parkId)
                ->where('T1.contract_periode', '<=', $currentDate) // 更新可能日チェック
                ->where('T1.contract_cancel_flag', 0) // 解約フラグ = 0
                ->where('T2.user_quit_flag', 0) // 退会フラグ = 0
                ->where('T1.contract_flag', 1) // 承認フラグ = 1
                ->whereNull('T1.contract_permission') // 更新済フラグ is null
                ->get()
                ->toArray();

            Log::info('定期更新対象者取得完了', [
                'park_id' => $parkId,
                'target_users_count' => count($targetUsers)
            ]);

            return $targetUsers;

        } catch (\Exception $e) {
            Log::error('定期更新対象者取得エラー', [
                'park_id' => $parkId,
                'error' => $e->getMessage()
            ]);

            throw $e;
        }
    }

    /**
     * 【処理3】対象者の処理実行
     * 
     * 手動登録フラグによって処理を分岐:
     * - = 0 (ウェブ申込み): SHJ-7メール送信を呼び出し
     * - その他: 内部変数のカウントアップ（オペレーターキュー処理）
     *
     * @param object $targetUser 対象者情報
     * @return array 処理結果
     */
    private function processTargetUser($targetUser): array
    {
        try {
            $manualRegistFlag = $targetUser->手動登録フラグ ?? 1;

            if ($manualRegistFlag == 0) {
                // ウェブ申込み: SHJ-7メール送信処理
                return $this->sendReminderMail($targetUser);
            } else {
                // その他: オペレーターキュー追加処理（内部変数カウントアップ）
                Log::info('オペレーターキュー対象者', [
                    'user_id' => $targetUser->利用者ID,
                    'contract_id' => $targetUser->定期契約内ID,
                    'manual_regist_flag' => $manualRegistFlag
                ]);

                return [
                    'type' => 'operator_queue',
                    'success' => true,
                    'message' => 'オペレーターキュー対象として処理'
                ];
            }

        } catch (\Exception $e) {
            Log::error('対象者処理エラー', [
                'user_id' => $targetUser->利用者ID ?? 'unknown',
                'error' => $e->getMessage()
            ]);

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

    /**
     * リマインダーメール送信処理
     * 
     * SHJ-7メール送信処理を呼び出し、使用プログラムID=200を使用
     *
     * @param object $targetUser 対象者情報
     * @return array 送信結果
     */
    private function sendReminderMail($targetUser): array
    {
        try {
            $mailAddress = $targetUser->メールアドレス ?? '';
            $backupMailAddress = $targetUser->予備メールアドレス ?? '';
            $mailTemplateId = 200; // 使用プログラムID

            Log::info('SHJ-7メール送信処理呼び出し', [
                'user_id' => $targetUser->利用者ID,
                'contract_id' => $targetUser->定期契約内ID,
                'mail_address' => $mailAddress,
                'backup_mail_address' => $backupMailAddress,
                'mail_template_id' => $mailTemplateId
            ]);

            // SHJ-7メール送信処理実行
            $mailResult = $this->mailSendService->executeMailSend(
                $mailAddress,
                $backupMailAddress,
                $mailTemplateId
            );

            if ($mailResult['success']) {
                return [
                    'type' => 'mail_success',
                    'success' => true,
                    'message' => 'メール送信成功',
                    'mail_result' => $mailResult
                ];
            } else {
                return [
                    'type' => 'mail_error',
                    'success' => false,
                    'message' => 'メール送信失敗: ' . $mailResult['message'],
                    'mail_result' => $mailResult
                ];
            }

        } catch (\Exception $e) {
            Log::error('リマインダーメール送信エラー', [
                'user_id' => $targetUser->利用者ID ?? 'unknown',
                'error' => $e->getMessage()
            ]);

            return [
                'type' => 'mail_error',
                'success' => false,
                'message' => 'メール送信エラー: ' . $e->getMessage()
            ];
        }
    }

    /**
     * 【処理4】SHJ-8バッチ処理ログ作成
     * 
     * 仕様書に基づくSHJ-8共通処理呼び出し
     *
     * @param array $statistics 処理統計情報
     * @return void
     */
    private function createShjBatchLog(array $statistics): void
    {
        try {
            // 仕様書に基づくSHJ-8パラメータ設定
            $deviceId = 9999; // テスト用デバイスID（規格書では"-"だが、既存実装に合わせて9999使用）
            $processName = 'SHJ-3定期更新リマインダー';
            $jobName = 'success';
            $status = 'success';
            
            // ステータスコメント生成
            $statusComment = "メール正常終了件数: {$statistics['mail_success_count']}" . 
                           " + メール異常終了件数: {$statistics['mail_error_count']}" .
                           " + キュー登録正常終了件数: {$statistics['operator_queue_count']}";
            
            $createdDate = now()->format('Y/m/d');
            $updatedDate = now()->format('Y/m/d');

            Log::info('SHJ-8バッチ処理ログ作成', [
                'device_id' => $deviceId,
                'process_name' => $processName,
                'job_name' => $jobName,
                'status' => $status,
                'status_comment' => $statusComment,
                'created_date' => $createdDate,
                'updated_date' => $updatedDate
            ]);

            // 共通処理SHJ-8バッチ処理ログ作成を呼び出し
            // 注意: 実際の運用では外部コマンド呼び出しまたは専用サービス経由で実行
            BatchLog::createBatchLog(
                $processName,
                $status,
                [
                    'device_id' => $deviceId,
                    'job_name' => $jobName,
                    'status_comment' => $statusComment,
                    'statistics' => $statistics,
                    'shj8_params' => [
                        'device_id' => $deviceId,
                        'process_name' => $processName,
                        'job_name' => $jobName,
                        'status' => $status,
                        'created_date' => $createdDate,
                        'updated_date' => $updatedDate
                    ]
                ],
                $statusComment
            );

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

            // SHJ-8でエラーが発生してもメイン処理は継続
            // エラーログのみ出力
        }
    }
}
