<?php

namespace App\Console\Commands;

use Illuminate\Console\Command;
use Illuminate\Support\Facades\Log;
use App\Services\ShjFourCService;

/**
 * SHJ-4C 室割当処理コマンド
 * 
 * 駐輪場の区画別利用率状況に基づく室割当処理を実行する
 * バックグラウンドで実行される定期バッチ処理
 */
class ShjFourCCommand extends Command
{
    /**
     * コンソールコマンドの名前とシグネチャ
     * 
     * 引数:
     * - park_id: 駐輪場ID (必須)
     * - ptype_id: 駐輪分類ID (必須) 
     * - psection_id: 車種区分ID (必須)
     *
     * @var string
     */
    protected $signature = 'shj:4c {park_id : 駐輪場ID} {ptype_id : 駐輪分類ID} {psection_id : 車種区分ID}';

    /**
     * コンソールコマンドの説明
     *
     * @var string
     */
    protected $description = 'SHJ-4C 室割当処理 - ゾーン情報取得及び割当処理を実行';

    /**
     * SHJ-4Cサービスクラス
     *
     * @var ShjFourCService
     */
    protected $shjFourCService;

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

    /**
     * コンソールコマンドを実行
     * 
     * 処理フロー:
     * 1. パラメータ取得と検証
     * 2. ゾーン情報取得処理
     * 3. 割当判定処理
     * 4. バッチログ作成
     * 5. 処理結果返却
     *
     * @return int
     */
    public function handle()
    {
        try {
            // 開始ログ出力
            $startTime = now();
            $this->info('SHJ-4C 室割当処理を開始します。');
            Log::info('SHJ-4C 室割当処理開始', [
                'start_time' => $startTime,
                'park_id' => $this->argument('park_id'),
                'ptype_id' => $this->argument('ptype_id'),
                'psection_id' => $this->argument('psection_id')
            ]);

            // 引数取得
            $parkId = $this->argument('park_id');
            $ptypeId = $this->argument('ptype_id');
            $psectionId = $this->argument('psection_id');

            // パラメータ検証
            if (!$this->validateParameters($parkId, $ptypeId, $psectionId)) {
                $this->error('パラメータが不正です。');
                return self::FAILURE;
            }

            // SHJ-4C処理実行
            $result = $this->shjFourCService->executeRoomAllocation($parkId, $ptypeId, $psectionId);

            // 処理結果確認
            if ($result['success']) {
                $endTime = now();
                $this->info('SHJ-4C 室割当処理が正常に完了しました。');
                $this->info("処理時間: {$startTime->diffInSeconds($endTime)}秒");
                
                Log::info('SHJ-4C 室割当処理完了', [
                    'end_time' => $endTime,
                    'duration_seconds' => $startTime->diffInSeconds($endTime),
                    'result' => $result
                ]);

                return self::SUCCESS;
            } else {
                $this->error('SHJ-4C 室割当処理でエラーが発生しました: ' . $result['message']);
                Log::error('SHJ-4C 室割当処理エラー', [
                    'error' => $result['message'],
                    'details' => $result['details'] ?? null
                ]);

                return self::FAILURE;
            }

        } catch (\Exception $e) {
            $this->error('SHJ-4C 室割当処理で予期しないエラーが発生しました: ' . $e->getMessage());
            Log::error('SHJ-4C 室割当処理例外エラー', [
                'exception' => $e->getMessage(),
                'trace' => $e->getTraceAsString()
            ]);

            return self::FAILURE;
        }
    }

    /**
     * パラメータの妥当性を検証
     *
     * @param mixed $parkId 駐輪場ID
     * @param mixed $ptypeId 駐輪分類ID  
     * @param mixed $psectionId 車種区分ID
     * @return bool 検証結果
     */
    private function validateParameters($parkId, $ptypeId, $psectionId): bool
    {
        // 必須パラメータチェック
        if (empty($parkId) || empty($ptypeId) || empty($psectionId)) {
            $this->error('全てのパラメータは必須です。');
            return false;
        }

        // 数値形式チェック
        if (!is_numeric($parkId) || !is_numeric($ptypeId) || !is_numeric($psectionId)) {
            $this->error('全てのパラメータは数値である必要があります。');
            return false;
        }

        // 正の整数チェック
        if ($parkId <= 0 || $ptypeId <= 0 || $psectionId <= 0) {
            $this->error('全てのパラメータは正の整数である必要があります。');
            return false;
        }

        return true;
    }
}
