<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Carbon\Carbon;

/**
 * ハードウェアチェックログモデル - hardware_check_logテーブル
 * 
 * デバイスのハードウェア状態監視ログを管理
 */
class HardwareCheckLog extends Model
{
    /**
     * テーブル名
     *
     * @var string
     */
    protected $table = 'hardware_check_log';

    /**
     * プライマリキー
     *
     * @var string
     */
    protected $primaryKey = 'log_id';

    /**
     * 一括代入可能な属性
     *
     * @var array
     */
    protected $fillable = [
        'device_id',          // デバイスID
        'status',             // ステータス
        'status_comment',     // ステータスコメント
        'created_at',         // 作成日時
        'updated_at',         // 更新日時
        'operator_id'         // オペレータID
    ];

    /**
     * キャストする属性
     *
     * @var array
     */
    protected $casts = [
        'log_id' => 'integer',
        'device_id' => 'integer',
        'status' => 'integer',
        'operator_id' => 'integer',
        'created_at' => 'datetime',
        'updated_at' => 'datetime'
    ];

    /**
     * ステータスの定数
     */
    const STATUS_NORMAL = 1;        // 正常
    const STATUS_WARNING = 2;       // 警告
    const STATUS_ERROR = 3;         // エラー
    const STATUS_UNKNOWN = 0;       // 不明

    /**
     * デバイスとの関連
     * 
     * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
     */
    public function device()
    {
        return $this->belongsTo(Device::class, 'device_id', 'device_id');
    }

    /**
     * 指定デバイスの最新ハードウェア状態を取得
     * 
     * @param int $deviceId デバイスID
     * @return HardwareCheckLog|null 最新ログ
     */
    public static function getLatestStatusByDevice(int $deviceId): ?HardwareCheckLog
    {
        return self::where('device_id', $deviceId)
            ->orderBy('created_at', 'desc')
            ->first();
    }

    /**
     * 全デバイスの最新ハードウェア状態を取得
     * 
     * @return \Illuminate\Database\Eloquent\Collection
     */
    public static function getLatestStatusForAllDevices()
    {
        return self::select('device_id')
            ->selectRaw('MAX(created_at) as latest_created_at')
            ->groupBy('device_id')
            ->with(['device'])
            ->get()
            ->map(function ($log) {
                return self::where('device_id', $log->device_id)
                    ->where('created_at', $log->latest_created_at)
                    ->with(['device'])
                    ->first();
            })
            ->filter();
    }

    /**
     * 異常状態のデバイスを取得
     * 
     * @return \Illuminate\Database\Eloquent\Collection
     */
    public static function getAbnormalDevices()
    {
        $latestLogs = self::getLatestStatusForAllDevices();
        
        return $latestLogs->filter(function ($log) {
            return $log->status !== self::STATUS_NORMAL;
        });
    }

    /**
     * 指定期間内のログを取得
     * 
     * @param int $deviceId デバイスID
     * @param string $startTime 開始時刻
     * @param string $endTime 終了時刻
     * @return \Illuminate\Database\Eloquent\Collection
     */
    public static function getLogsByPeriod(int $deviceId, string $startTime, string $endTime)
    {
        return self::where('device_id', $deviceId)
            ->whereBetween('created_at', [$startTime, $endTime])
            ->orderBy('created_at', 'desc')
            ->get();
    }

    /**
     * ハードウェア状態ログを作成
     * 
     * @param int $deviceId デバイスID
     * @param int $status ステータス
     * @param string $statusComment ステータスコメント
     * @param int|null $operatorId オペレータID
     * @return HardwareCheckLog 作成されたログ
     */
    public static function createLog(
        int $deviceId,
        int $status,
        string $statusComment = '',
        ?int $operatorId = null
    ): HardwareCheckLog {
        return self::create([
            'device_id' => $deviceId,
            'status' => $status,
            'status_comment' => $statusComment,
            'operator_id' => $operatorId ?? 0
        ]);
    }

    /**
     * ステータス名を取得
     * 
     * @param int $status ステータス
     * @return string ステータス名
     */
    public static function getStatusName(int $status): string
    {
        switch ($status) {
            case self::STATUS_NORMAL:
                return '正常';
            case self::STATUS_WARNING:
                return '警告';
            case self::STATUS_ERROR:
                return 'エラー';
            case self::STATUS_UNKNOWN:
                return '不明';
            default:
                return "ステータス{$status}";
        }
    }

    /**
     * 現在のステータス名を取得
     * 
     * @return string ステータス名
     */
    public function getStatusNameAttribute(): string
    {
        return self::getStatusName($this->status);
    }

    /**
     * 正常状態かどうかを判定
     * 
     * @return bool 正常状態かどうか
     */
    public function isNormal(): bool
    {
        return $this->status === self::STATUS_NORMAL;
    }

    /**
     * 異常状態かどうかを判定
     * 
     * @return bool 異常状態かどうか
     */
    public function isAbnormal(): bool
    {
        return $this->status !== self::STATUS_NORMAL;
    }

    /**
     * 文字列表現
     * 
     * @return string
     */
    public function __toString(): string
    {
        return sprintf(
            'HardwareCheckLog[ID:%d, Device:%d, Status:%s, Time:%s]',
            $this->log_id,
            $this->device_id,
            $this->getStatusNameAttribute(),
            $this->created_at ? $this->created_at->format('Y-m-d H:i:s') : 'N/A'
        );
    }
}
