<?php

namespace App\Services;

use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use App\Models\RegularContract;
use App\Models\Park;
use App\Models\Psection;
use App\Models\Ptype;
use App\Models\Setting;
use App\Models\Device;
use Carbon\Carbon;

/**
 * SHJ-11 現在契約台数集計サービス
 *
 * 集計単位每个の契約台数を算出し、ゾーンマスタとの管理処理を実行
 * bat_job_logへの書き込みはSHJ-8を呼び出す
 */
class ShjElevenService
{
    /**
     * ShjEightService
     *
     * @var ShjEightService
     */
    protected $shjEightService;

    /**
     * コンストラクタ
     *
     * @param ShjEightService $shjEightService
     */
    public function __construct(ShjEightService $shjEightService)
    {
        $this->shjEightService = $shjEightService;
    }

    /**
     * バッチ処理用の有効なデバイスIDを取得
     *
     * deviceテーブルから最初の有効なdevice_idを取得する。
     * データが存在しない場合は例外をスローする。
     *
     * @return int 有効なdevice_id
     * @throws \Exception deviceテーブルにレコードが存在しない場合
     */
    private function getBatchDeviceId(): int
    {
        $device = Device::orderBy('device_id')->first();

        if (!$device) {
            throw new \Exception('deviceテーブルにレコードが存在しません。SHJ-8バッチログ作成に必要なデバイスIDを取得できません。');
        }

        Log::debug('SHJ-11 バッチ用デバイスID取得', [
            'device_id' => $device->device_id
        ]);

        return $device->device_id;
    }

    /**
     * 現在使用中のprice主表名を取得する
     *
     * setting.web_master から価格マスタテーブル名を決定
     * web_master の値（'_a' または '_b'）から 'price_a' または 'price_b' を返す
     *
     * @return string price主表名（'price_a' または 'price_b'）
     * @throws \Exception setting取得失敗時
     */
    private function getPriceTableName(): string
    {
        try {
            $setting = Setting::getSettings();

            if (!$setting || empty($setting->web_master)) {
                throw new \Exception('setting.web_masterの取得に失敗しました');
            }

            // web_master の値：'_a' または '_b'
            $webMaster = $setting->web_master;

            // 'price_' + ('_a' → 'a' / '_b' → 'b')
            $priceTable = 'price_' . ltrim($webMaster, '_');

            Log::info('SHJ-11 price主表名決定', [
                'web_master' => $webMaster,
                'price_table' => $priceTable
            ]);

            return $priceTable;

        } catch (\Exception $e) {
            Log::error('SHJ-11 price主表名取得エラー', [
                'error' => $e->getMessage()
            ]);
            throw $e;
        }
    }

    /**
     * 【処理1】集計単位每个の契約台数を算出する
     *
     * 集計単位: 駐輪場ID + 車種区分ID + 駐輪分類ID + ゾーンID
     *
     * SQL仕様に基づく複雑なJOIN処理:
     * - regular_contract (T1)
     * - park (T2)
     * - psection (T4)
     * - price_a/price_b (T5) ※web_master設定により動的に決定
     * - ptype (T3)
     *
     * @return array 契約台数集計結果
     */
    public function calculateContractCounts(): array
    {
        try {
            // setting.web_master から使用するprice主表を決定
            $priceTable = $this->getPriceTableName();

            $query = DB::table('regular_contract as T1')
                ->select([
                    'T1.park_id',               // 駐輪場ID
                    'T2.park_name',             // 駐輪場名
                    'T5.psection_id',           // 車種区分ID
                    'T4.psection_subject',      // 車種区分名
                    'T5.ptype_id',              // 駐輪分類ID
                    'T3.ptype_subject',         // 駐輪分類名
                    'T1.zone_id',               // ゾーンID
                    DB::raw('count(T1.contract_id) as cnt')  // 契約台数
                ])
                // park テーブルとの JOIN
                ->join('park as T2', 'T1.park_id', '=', 'T2.park_id')
                // psection テーブルとの JOIN
                ->join('psection as T4', 'T1.psection_id', '=', 'T4.psection_id')
                // price_a/price_b テーブルとの複合条件 JOIN（動的テーブル名）
                ->join(DB::raw($priceTable . ' 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');
                })
                // ptype テーブルとの JOIN
                ->join('ptype as T3', 'T5.ptype_id', '=', 'T3.ptype_id')
                ->where([
                    ['T1.contract_flag', '=', 1],           // 授受フラグ = 1
                    ['T2.park_close_flag', '=', 0],         // 閉設フラグ = 0
                ])
                // 契約有効期間内の条件（仕様書指定：'%y.%m.%d'形式）
                ->whereRaw("date_format(now(), '%y.%m.%d') BETWEEN T1.contract_periods AND T1.contract_periode")
                // zone_idがNULLのレコードは除外（ゾーンマスタ更新不可のため）
                ->whereNotNull('T1.zone_id')
                ->groupBy([
                    'T1.park_id',
                    'T2.park_name',
                    'T5.psection_id',
                    'T4.psection_subject',
                    'T5.ptype_id',
                    'T3.ptype_subject',
                    'T1.zone_id'
                ])
                ->get();

            Log::info('SHJ-11 契約台数算出完了', [
                'count' => $query->count(),
                'price_table' => $priceTable,
                'sql_conditions' => [
                    'contract_flag' => 1,
                    'park_close_flag' => 0,
                    'date_format' => '%y.%m.%d',
                    'contract_period_check' => 'BETWEEN contract_periods AND contract_periode'
                ]
            ]);

            return $query->toArray();

        } catch (\Exception $e) {
            Log::error('SHJ-11 契約台数算出エラー', [
                'error' => $e->getMessage(),
                'trace' => $e->getTraceAsString()
            ]);
            throw $e;
        }
    }

    /**
     * 【処理2・3】ゾーンマスタ管理処理
     *
     * 処理フロー（仕様書準拠）:
     * 処理1の取得レコード数分繰り返し:
     *   【処理2】ゾーンマスタを取得する
     *   【判断2】取得判定
     *     - ゾーンマスタなし → INSERT（トランザクション内） → commit → 【処理4】SHJ-8（トランザクション外） → 次へ
     *     - ゾーンマスタあり → 【判断3】契約台数チェック → 【処理3】UPDATE（トランザクション内） → commit → 【処理4】SHJ-8（トランザクション外） → 次へ
     *
     * ※SHJ-8ログは各レコード処理後に確実に記録するため、トランザクション外で実行
     *
     * @param array $contractCounts 契約台数集計結果
     * @return array 処理結果
     */
    public function processZoneManagement(array $contractCounts): array
    {
        $createdZones = 0;
        $updatedZones = 0;
        $overCapacityCount = 0;
        $batchLogErrors = [];

        try {

            // 処理1の取得レコード数分繰り返し
            foreach ($contractCounts as $contractData) {
                try {
                    // 【防御的チェック】必須キーがNULLの場合はスキップ
                    if (empty($contractData->zone_id) || empty($contractData->psection_id) || empty($contractData->ptype_id)) {
                        Log::warning('SHJ-11 必須キー欠落のためスキップ', [
                            'park_id' => $contractData->park_id ?? null,
                            'zone_id' => $contractData->zone_id ?? null,
                            'psection_id' => $contractData->psection_id ?? null,
                            'ptype_id' => $contractData->ptype_id ?? null
                        ]);

                        $batchLogErrors[] = [
                            'park_id' => $contractData->park_id ?? null,
                            'zone_id' => $contractData->zone_id ?? null,
                            'error' => '必須キー欠落（zone_id/psection_id/ptype_id）'
                        ];

                        continue;
                    }

                    // 各レコードごとに独立したトランザクションを開始
                    DB::beginTransaction();

                    // 【処理2】ゾーンマスタを取得する
                    $zoneData = $this->getZoneData($contractData);

                    // 【判断2】取得判定
                    if (!$zoneData) {
                        // ゾーンマスタなし → INSERT
                        $createResult = $this->createZoneData($contractData);

                        if (!$createResult['success']) {
                            // INSERT失敗時のエラー処理
                            DB::rollBack();

                            Log::error('SHJ-11 ゾーンマスタINSERT失敗', [
                                'park_id' => $contractData->park_id,
                                'zone_id' => $contractData->zone_id,
                                'error' => $createResult['message']
                            ]);

                            $batchLogErrors[] = [
                                'park_id' => $contractData->park_id,
                                'zone_id' => $contractData->zone_id,
                                'error' => 'INSERT失敗: ' . $createResult['message']
                            ];

                            // INSERT失敗時も次の繰り返しへ
                            continue;
                        }

                        // INSERTトランザクションをcommit
                        DB::commit();

                        $createdZones++;

                        // status_comment作成（INSERT分岐）
                        $statusComment = $this->formatStatusComment(
                            $contractData->park_name,
                            $contractData->ptype_subject,
                            $contractData->psection_subject,
                            $contractData->zone_id,
                            '' // INSERT分岐では台数アラートなし
                        );

                        // 【処理4】bat_job_logに直接書き込み（トランザクション外・INSERT分岐）
                        $batchLogResult = $this->writeBatJobLog(
                            $contractData,
                            $statusComment,
                            false // 限界台数超過なし
                        );

                        // bat_job_log書き込み結果チェック
                        if (!$batchLogResult['success']) {
                            Log::warning('bat_job_log書き込み失敗（INSERT分岐）', [
                                'park_id' => $contractData->park_id,
                                'zone_id' => $contractData->zone_id,
                                'error_message' => $batchLogResult['error_message'] ?? null
                            ]);

                            // bat_job_log書き込み失敗をbatch_log_errorsに記録
                            $batchLogErrors[] = [
                                'park_id' => $contractData->park_id,
                                'zone_id' => $contractData->zone_id,
                                'error' => 'bat_job_log書き込み失敗（INSERT分岐）: ' . ($batchLogResult['error_message'] ?? 'unknown error')
                            ];
                        }

                        // INSERT分岐は【処理4】後に次の繰り返しへ
                        continue;
                    }

                    // ゾーンマスタあり → 【判断3】契約台数チェック
                    $isOverCapacity = $this->checkCapacityLimit($contractData, $zoneData);
                    if ($isOverCapacity) {
                        $overCapacityCount++;
                        Log::warning('SHJ-11 限界台数超過検出', [
                            'park_id' => $contractData->park_id,
                            'zone_id' => $contractData->zone_id,
                            'current_count' => $contractData->cnt,
                            'limit_capacity' => $zoneData->zone_tolerance ?? 0
                        ]);
                    }

                    // 【処理3】契約台数を反映する（UPDATE）
                    $updateResult = $this->updateZoneContractCount($contractData);

                    if (!$updateResult['success']) {
                        // UPDATE失敗時のエラー処理
                        DB::rollBack();

                        Log::error('SHJ-11 ゾーンマスタUPDATE失敗', [
                            'park_id' => $contractData->park_id,
                            'zone_id' => $contractData->zone_id,
                            'error' => $updateResult['message']
                        ]);

                        $batchLogErrors[] = [
                            'park_id' => $contractData->park_id,
                            'zone_id' => $contractData->zone_id,
                            'error' => 'UPDATE失敗: ' . $updateResult['message']
                        ];

                        // UPDATE失敗時も次の繰り返しへ
                        continue;
                    }

                    // UPDATEトランザクションをcommit
                    DB::commit();

                    $updatedZones++;

                    // status_comment作成（UPDATE分岐）
                    $capacityAlert = $isOverCapacity ? '限界収容台数を超えています。' : '';
                    $statusComment = $this->formatStatusComment(
                        $contractData->park_name,
                        $contractData->ptype_subject,
                        $contractData->psection_subject,
                        $contractData->zone_id,
                        $capacityAlert
                    );

                    // 【処理4】bat_job_logに直接書き込み（トランザクション外・UPDATE分岐）
                    $batchLogResult = $this->writeBatJobLog(
                        $contractData,
                        $statusComment,
                        $isOverCapacity
                    );

                    // bat_job_log書き込み結果チェック
                    if (!$batchLogResult['success']) {
                        Log::warning('bat_job_log書き込み失敗（UPDATE分岐）', [
                            'park_id' => $contractData->park_id,
                            'zone_id' => $contractData->zone_id,
                            'error_message' => $batchLogResult['error_message'] ?? null
                        ]);

                        // bat_job_log書き込み失敗をbatch_log_errorsに記録
                        $batchLogErrors[] = [
                            'park_id' => $contractData->park_id,
                            'zone_id' => $contractData->zone_id,
                            'error' => 'bat_job_log書き込み失敗（UPDATE分岐）: ' . ($batchLogResult['error_message'] ?? 'unknown error')
                        ];
                    }

                } catch (\Exception $e) {
                    // 例外時はロールバック（アクティブなトランザクションがある場合のみ）
                    if (DB::transactionLevel() > 0) {
                        DB::rollBack();
                    }

                    // 個別レコードエラーもログ記録して次へ進む
                    $batchLogErrors[] = [
                        'park_id' => $contractData->park_id ?? null,
                        'zone_id' => $contractData->zone_id ?? null,
                        'error' => $e->getMessage()
                    ];

                    Log::warning('SHJ-11 個別レコード処理エラー', [
                        'park_id' => $contractData->park_id ?? null,
                        'zone_id' => $contractData->zone_id ?? null,
                        'error' => $e->getMessage()
                    ]);

                    // エラーでも次の繰り返しへ続行
                    continue;
                }
            }

            return [
                'success' => true,
                'created_zones' => $createdZones,
                'updated_zones' => $updatedZones,
                'over_capacity_count' => $overCapacityCount,
                'batch_log_errors' => $batchLogErrors,
                'message' => '現在契約台数集計処理完了'
            ];

        } catch (\Exception $e) {
            // 外層エラー時のロールバック
            // ※各レコード処理は独立トランザクションのため、
            // ここでのrollBackは不要だが安全のため実行
            if (DB::transactionLevel() > 0) {
                DB::rollBack();
            }

            Log::error('SHJ-11 ゾーンマスタ管理処理全体エラー', [
                'error' => $e->getMessage(),
                'created_zones' => $createdZones,
                'updated_zones' => $updatedZones
            ]);

            return [
                'success' => false,
                'created_zones' => $createdZones,
                'updated_zones' => $updatedZones,
                'over_capacity_count' => $overCapacityCount,
                'batch_log_errors' => $batchLogErrors,
                'message' => 'ゾーンマスタ管理処理エラー: ' . $e->getMessage(),
                'details' => $e->getTraceAsString()
            ];
        }
    }

    /**
     * ゾーンマスタデータ取得
     * 
     * 集計単位に対応するゾーンマスタを取得
     *
     * @param object $contractData 契約台数集計データ
     * @return object|null ゾーンマスタデータ
     */
    private function getZoneData($contractData)
    {
        try {
            return DB::table('zone')
                ->select([
                    'zone_id',
                    'park_id',
                    'ptype_id',
                    'psection_id',
                    'zone_name',
                    'zone_number',          // 現在契約台数
                    'zone_standard',        // 標準収容台数
                    'zone_tolerance'        // 限界収容台数
                ])
                ->where([
                    ['park_id', '=', $contractData->park_id],
                    ['psection_id', '=', $contractData->psection_id],
                    ['ptype_id', '=', $contractData->ptype_id],
                    ['zone_id', '=', $contractData->zone_id]
                ])
                ->first();

        } catch (\Exception $e) {
            Log::error('SHJ-11 ゾーンマスタ取得エラー', [
                'park_id' => $contractData->park_id,
                'zone_id' => $contractData->zone_id,
                'error' => $e->getMessage()
            ]);
            throw $e;
        }
    }

    /**
     * ゾーンマスタ新規作成
     * 
     * 仕様書に基づくINSERT処理
     *
     * @param object $contractData 契約台数集計データ
     * @return array 作成結果
     */
    private function createZoneData($contractData): array
    {
        try {
            // 新規ゾーンマスタのデフォルト値設定
            $newZoneData = [
                'zone_id' => $contractData->zone_id,
                'park_id' => $contractData->park_id,
                'ptype_id' => $contractData->ptype_id,
                'psection_id' => $contractData->psection_id,
                'zone_name' => null,                           // デフォルトnull
                'zone_number' => $contractData->cnt,           // 算出した契約台数
                'zone_standard' => null,                       // デフォルトnull
                'zone_tolerance' => null,                      // デフォルトnull
                'zone_sort' => null,                          // デフォルトnull
                'delete_flag' => 0,                           // 削除フラグOFF
                'created_at' => now(),
                'updated_at' => now(),
                'ope_id' => 9999999                           // 仕様書指定値
            ];

            DB::table('zone')->insert($newZoneData);

            Log::info('SHJ-11 ゾーンマスタ新規作成完了', [
                'zone_id' => $contractData->zone_id,
                'park_id' => $contractData->park_id,
                'contract_count' => $contractData->cnt
            ]);

            return [
                'success' => true,
                'zone_data' => (object) $newZoneData,
                'message' => 'ゾーンマスタを新規作成しました'
            ];

        } catch (\Exception $e) {
            Log::error('SHJ-11 ゾーンマスタ新規作成エラー', [
                'zone_id' => $contractData->zone_id,
                'park_id' => $contractData->park_id,
                'error' => $e->getMessage()
            ]);

            return [
                'success' => false,
                'zone_data' => null,
                'message' => 'ゾーンマスタ新規作成エラー: ' . $e->getMessage()
            ];
        }
    }

    /**
     * 契約台数限界チェック
     * 
     * 【判断3】契約台数 > 限界収容台数の判定
     *
     * @param object $contractData 契約台数集計データ
     * @param object|null $zoneData ゾーンマスタデータ
     * @return bool 限界台数超過フラグ
     */
    private function checkCapacityLimit($contractData, $zoneData = null): bool
    {
        if (!$zoneData || is_null($zoneData->zone_tolerance)) {
            // ゾーンデータが存在しないか、限界収容台数が未設定の場合は超過判定しない
            return false;
        }

        // 契約台数 > 限界収容台数の判定
        return $contractData->cnt > $zoneData->zone_tolerance;
    }

    /**
     * ゾーンマスタ契約台数更新
     *
     * 【処理3】現在契約台数をゾーンマスタに反映
     *
     * @param object $contractData 契約台数集計データ
     * @return array 更新結果
     */
    private function updateZoneContractCount($contractData): array
    {
        try {
            $updateData = [
                'zone_number' => $contractData->cnt,           // 現在契約台数を更新
                'updated_at' => now(),                         // 更新日時
                'ope_id' => 9999999                           // 更新オペレータID（INSERT時と同様、DB型int unsignedに対応）
            ];

            $updated = DB::table('zone')
                ->where([
                    ['park_id', '=', $contractData->park_id],
                    ['psection_id', '=', $contractData->psection_id],
                    ['ptype_id', '=', $contractData->ptype_id],
                    ['zone_id', '=', $contractData->zone_id]
                ])
                ->update($updateData);

            if ($updated > 0) {
                Log::info('SHJ-11 ゾーンマスタ更新完了', [
                    'zone_id' => $contractData->zone_id,
                    'park_id' => $contractData->park_id,
                    'new_contract_count' => $contractData->cnt
                ]);

                return [
                    'success' => true,
                    'message' => 'ゾーンマスタ契約台数を更新しました'
                ];
            } else {
                Log::warning('SHJ-11 ゾーンマスタ更新対象なし', [
                    'zone_id' => $contractData->zone_id,
                    'park_id' => $contractData->park_id
                ]);

                return [
                    'success' => false,
                    'message' => 'ゾーンマスタ更新対象が見つかりません'
                ];
            }

        } catch (\Exception $e) {
            Log::error('SHJ-11 ゾーンマスタ更新エラー', [
                'zone_id' => $contractData->zone_id,
                'park_id' => $contractData->park_id,
                'error' => $e->getMessage()
            ]);

            return [
                'success' => false,
                'message' => 'ゾーンマスタ更新エラー: ' . $e->getMessage()
            ];
        }
    }

    /**
     * status_commentを仕様書指定フォーマットで作成
     *
     * フォーマット: 駐輪場名／駐輪分類名／車種区分名／ゾーンID[台数アラート]
     *
     * @param string $parkName 駐輪場名
     * @param string $ptypeSubject 駐輪分類名
     * @param string $psectionSubject 車種区分名
     * @param int $zoneId ゾーンID
     * @param string $capacityAlert 台数アラート（「限界収容台数を超えています。」または空文字）
     * @return string フォーマット済みstatus_comment
     */
    private function formatStatusComment(
        string $parkName,
        string $ptypeSubject,
        string $psectionSubject,
        int $zoneId,
        string $capacityAlert
    ): string {
        $baseComment = $parkName . '／' . $ptypeSubject . '／' . $psectionSubject . '／' . $zoneId;

        if (!empty($capacityAlert)) {
            return $baseComment . '　' . $capacityAlert;
        }

        return $baseComment;
    }

    /**
     * 【処理4】個別レコードのバッチ処理ログを作成する
     *
     * SHJ-11は業務固有のstatus_commentを記録するため、SHJ-8を使わずbat_job_logに直接書き込む
     *
     * bat_job_log登録内容:
     * 1. デバイスID
     * 2. プロセス名: SHJ-11
     * 3. ジョブ名: SHJ-11現在契約台数集計
     * 4. ステータス: success
     * 5. ステータスコメント: 業務固有（駐輪場名／駐輪分類名／車種区分名／ゾーンID[台数アラート]）
     * 6. 登録日時: 現在の日付
     * 7. 更新日時: 現在の日付
     *
     * @param object $contractData 契約台数集計データ
     * @param string $statusComment status_comment（台数アラート含む）
     * @param bool $isOverCapacity 限界台数超過フラグ
     * @return array 処理結果 ['success' => bool, 'error_message' => string|null]
     */
    private function writeBatJobLog(
        $contractData,
        string $statusComment,
        bool $isOverCapacity
    ): array {
        try {
            // SHJ-8バッチ処理ログ作成パラメータ設定
            $deviceId = $this->getBatchDeviceId();  // deviceテーブルから有効なIDを取得
            $processName = 'SHJ-11';
            $jobName = 'SHJ-11現在契約台数集計';
            $status = 'success';
            $today = now()->format('Y/m/d');

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

            // SHJ-8サービスを呼び出し
            $this->shjEightService->execute(
                $deviceId,
                $processName,
                $jobName,
                $status,
                $statusComment,
                $today,
                $today
            );

            Log::info('SHJ-8バッチ処理ログ作成完了', [
                'park_id' => $contractData->park_id,
                'zone_id' => $contractData->zone_id
            ]);

            return [
                'success' => true,
                'error_message' => null
            ];

        } catch (\Exception $e) {
            Log::error('bat_job_log書き込みエラー', [
                'park_id' => $contractData->park_id ?? null,
                'zone_id' => $contractData->zone_id ?? null,
                'error' => $e->getMessage(),
                'trace' => $e->getTraceAsString()
            ]);

            // エラーが発生してもメイン処理は継続
            return [
                'success' => false,
                'error_message' => $e->getMessage()
            ];
        }
    }

    /**
     * 【判断1】取得件数=0時のバッチログ作成
     *
     * 取得件数が0件の場合に呼び出される特別なバッチログ作成
     * bat_job_logに直接書き込み
     *
     * bat_job_log登録内容:
     * 1. デバイスID
     * 2. プロセス名: SHJ-11
     * 3. ジョブ名: SHJ-11現在契約台数集計
     * 4. ステータス: success
     * 5. ステータスコメント: 全駐輪場契約なし
     * 6. 登録日時: 現在の日付
     * 7. 更新日時: 現在の日付
     *
     * @return array 処理結果 ['success' => bool, 'error_message' => string|null]
     */
    public function writeBatJobLogForNoContracts(): array
    {
        try {
            // SHJ-8バッチ処理ログ作成パラメータ設定
            $deviceId = $this->getBatchDeviceId();  // deviceテーブルから有効なIDを取得
            $processName = 'SHJ-11';
            $jobName = 'SHJ-11現在契約台数集計';
            $status = 'success';
            $statusComment = '全駐輪場契約なし';
            $today = now()->format('Y/m/d');

            Log::info('SHJ-8バッチ処理ログ作成（対象なし）', [
                'device_id' => $deviceId,
                'process_name' => $processName,
                'job_name' => $jobName,
                'status' => $status,
                'status_comment' => $statusComment
            ]);

            // SHJ-8サービスを呼び出し
            $this->shjEightService->execute(
                $deviceId,
                $processName,
                $jobName,
                $status,
                $statusComment,
                $today,
                $today
            );

            Log::info('SHJ-8バッチ処理ログ作成完了（対象なし）');

            return [
                'success' => true,
                'error_message' => null
            ];

        } catch (\Exception $e) {
            Log::error('bat_job_log書き込みエラー（対象なし）', [
                'error' => $e->getMessage(),
                'trace' => $e->getTraceAsString()
            ]);

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