<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

/**
 * MeetingLog Model
 * 
 * Logs all Google Meet API interactions for debugging, auditing,
 * and monitoring purposes. Tracks meeting creation, test connections,
 * and token refresh operations.
 * 
 * @property int $id
 * @property string $type Log type: create_meeting, test, token_refresh, revoke_access
 * @property string $status Status: success, failed
 * @property string|null $summary Meeting title/summary
 * @property int|null $attendees_count Number of attendees
 * @property string|null $meeting_link Google Meet URL
 * @property string|null $meeting_id Google Meet ID
 * @property array|null $response_body Full API response
 * @property string|null $error_message Error description if failed
 * @property int $execution_time_ms Execution time in milliseconds
 * @property \Illuminate\Support\Carbon|null $created_at
 */
class MeetingLog extends Model
{
    use HasFactory;

    /**
     * Log type constants.
     */
    public const TYPE_CREATE_MEETING = 'create_meeting';
    public const TYPE_TEST = 'test';
    public const TYPE_TOKEN_REFRESH = 'token_refresh';
    public const TYPE_REVOKE_ACCESS = 'revoke_access';

    /**
     * Status constants.
     */
    public const STATUS_SUCCESS = 'success';
    public const STATUS_FAILED = 'failed';

    /**
     * The attributes that are mass assignable.
     *
     * @var array<int, string>
     */
    protected $fillable = [
        'type',
        'status',
        'summary',
        'attendees_count',
        'meeting_link',
        'meeting_id',
        'response_body',
        'error_message',
        'execution_time_ms',
    ];

    /**
     * The attributes that should be cast.
     *
     * @var array<string, string>
     */
    protected $casts = [
        'response_body' => 'array',
        'attendees_count' => 'integer',
        'execution_time_ms' => 'integer',
    ];

    /**
     * Indicates if the model should be timestamped.
     *
     * @var bool
     */
    public $timestamps = false;

    /**
     * The "booted" method of the model.
     */
    protected static function booted(): void
    {
        static::creating(function (self $log) {
            if (empty($log->created_at)) {
                $log->created_at = now();
            }
        });
    }

    /*
    |--------------------------------------------------------------------------
    | Query Scopes
    |--------------------------------------------------------------------------
    */

    /**
     * Scope to filter by type.
     *
     * @param \Illuminate\Database\Eloquent\Builder $query
     * @param string $type
     * @return \Illuminate\Database\Eloquent\Builder
     */
    public function scopeOfType($query, string $type)
    {
        return $query->where('type', $type);
    }

    /**
     * Scope to filter by status.
     *
     * @param \Illuminate\Database\Eloquent\Builder $query
     * @param string $status
     * @return \Illuminate\Database\Eloquent\Builder
     */
    public function scopeOfStatus($query, string $status)
    {
        return $query->where('status', $status);
    }

    /**
     * Scope to get only successful logs.
     *
     * @param \Illuminate\Database\Eloquent\Builder $query
     * @return \Illuminate\Database\Eloquent\Builder
     */
    public function scopeSuccessful($query)
    {
        return $query->where('status', self::STATUS_SUCCESS);
    }

    /**
     * Scope to get only failed logs.
     *
     * @param \Illuminate\Database\Eloquent\Builder $query
     * @return \Illuminate\Database\Eloquent\Builder
     */
    public function scopeFailed($query)
    {
        return $query->where('status', self::STATUS_FAILED);
    }

    /**
     * Scope to get only meeting creation logs.
     *
     * @param \Illuminate\Database\Eloquent\Builder $query
     * @return \Illuminate\Database\Eloquent\Builder
     */
    public function scopeMeetings($query)
    {
        return $query->where('type', self::TYPE_CREATE_MEETING);
    }

    /**
     * Scope to get only test connection logs.
     *
     * @param \Illuminate\Database\Eloquent\Builder $query
     * @return \Illuminate\Database\Eloquent\Builder
     */
    public function scopeTests($query)
    {
        return $query->where('type', self::TYPE_TEST);
    }

    /**
     * Scope to get only token refresh logs.
     *
     * @param \Illuminate\Database\Eloquent\Builder $query
     * @return \Illuminate\Database\Eloquent\Builder
     */
    public function scopeTokenRefreshes($query)
    {
        return $query->where('type', self::TYPE_TOKEN_REFRESH);
    }

    /**
     * Scope to filter by date range.
     *
     * @param \Illuminate\Database\Eloquent\Builder $query
     * @param \Illuminate\Support\Carbon|string $startDate
     * @param \Illuminate\Support\Carbon|string $endDate
     * @return \Illuminate\Database\Eloquent\Builder
     */
    public function scopeDateRange($query, $startDate, $endDate)
    {
        return $query->whereBetween('created_at', [$startDate, $endDate]);
    }

    /**
     * Scope to get recent logs.
     *
     * @param \Illuminate\Database\Eloquent\Builder $query
     * @param int $days
     * @return \Illuminate\Database\Eloquent\Builder
     */
    public function scopeRecent($query, int $days = 30)
    {
        return $query->where('created_at', '>=', now()->subDays($days));
    }

    /*
    |--------------------------------------------------------------------------
    | Helper Methods
    |--------------------------------------------------------------------------
    */

    /**
     * Check if the log entry was successful.
     *
     * @return bool
     */
    public function isSuccessful(): bool
    {
        return $this->status === self::STATUS_SUCCESS;
    }

    /**
     * Check if the log entry failed.
     *
     * @return bool
     */
    public function isFailed(): bool
    {
        return $this->status === self::STATUS_FAILED;
    }

    /**
     * Check if this is a meeting creation log.
     *
     * @return bool
     */
    public function isMeetingCreation(): bool
    {
        return $this->type === self::TYPE_CREATE_MEETING;
    }

    /**
     * Check if this is a test connection log.
     *
     * @return bool
     */
    public function isTest(): bool
    {
        return $this->type === self::TYPE_TEST;
    }

    /**
     * Check if this is a token refresh log.
     *
     * @return bool
     */
    public function isTokenRefresh(): bool
    {
        return $this->type === self::TYPE_TOKEN_REFRESH;
    }

    /**
     * Get formatted execution time.
     *
     * @return string
     */
    public function getFormattedExecutionTime(): string
    {
        $ms = $this->execution_time_ms;
        
        if ($ms < 1000) {
            return "{$ms}ms";
        }
        
        return round($ms / 1000, 2) . 's';
    }

    /**
     * Get the type label for display.
     *
     * @return string
     */
    public function getTypeLabel(): string
    {
        return match ($this->type) {
            self::TYPE_CREATE_MEETING => 'Create Meeting',
            self::TYPE_TEST => 'Test Connection',
            self::TYPE_TOKEN_REFRESH => 'Token Refresh',
            self::TYPE_REVOKE_ACCESS => 'Revoke Access',
            default => ucfirst($this->type),
        };
    }

    /**
     * Eloquent accessor for type_label (used in Blade as $log->type_label).
     */
    public function getTypeLabelAttribute(): string
    {
        return $this->getTypeLabel();
    }

    /**
     * Eloquent accessor for formatted_execution_time (used in Blade as $log->formatted_execution_time).
     */
    public function getFormattedExecutionTimeAttribute(): string
    {
        return $this->getFormattedExecutionTime();
    }

    /*
    |--------------------------------------------------------------------------
    | Static Factory Methods
    |--------------------------------------------------------------------------
    */

    /**
     * Create a log entry for meeting creation.
     *
     * @param bool $success
     * @param array $data
     * @param int $executionTimeMs
     * @param string|null $error
     * @return self
     */
    public static function logMeetingCreation(
        bool $success,
        array $data = [],
        int $executionTimeMs = 0,
        ?string $error = null
    ): self {
        return self::create([
            'type' => self::TYPE_CREATE_MEETING,
            'status' => $success ? self::STATUS_SUCCESS : self::STATUS_FAILED,
            'summary' => $data['summary'] ?? null,
            'attendees_count' => $data['attendees_count'] ?? null,
            'meeting_link' => $data['meeting_link'] ?? null,
            'meeting_id' => $data['meeting_id'] ?? null,
            'response_body' => $data['response_body'] ?? null,
            'error_message' => $error,
            'execution_time_ms' => $executionTimeMs,
        ]);
    }

    /**
     * Create a log entry for test connection.
     *
     * @param bool $success
     * @param array $data
     * @param int $executionTimeMs
     * @param string|null $error
     * @return self
     */
    public static function logTest(
        bool $success,
        array $data = [],
        int $executionTimeMs = 0,
        ?string $error = null
    ): self {
        return self::create([
            'type' => self::TYPE_TEST,
            'status' => $success ? self::STATUS_SUCCESS : self::STATUS_FAILED,
            'response_body' => $data['response_body'] ?? null,
            'error_message' => $error,
            'execution_time_ms' => $executionTimeMs,
        ]);
    }

    /**
     * Create a log entry for token refresh.
     *
     * @param bool $success
     * @param int $executionTimeMs
     * @param string|null $error
     * @return self
     */
    public static function logTokenRefresh(
        bool $success,
        int $executionTimeMs = 0,
        ?string $error = null
    ): self {
        return self::create([
            'type' => self::TYPE_TOKEN_REFRESH,
            'status' => $success ? self::STATUS_SUCCESS : self::STATUS_FAILED,
            'error_message' => $error,
            'execution_time_ms' => $executionTimeMs,
        ]);
    }
}
