<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;

class PaymentEvent extends Model
{
    protected $fillable = [
        'event_type',
        'level',
        'data',
        'user_type',
        'user_id',
        'request_id',
        'ip_address',
        'user_agent',
        'expires_at',
        'provider',
        'webhook_event_type',
        'payload',
        'success',
        'stored_at',
    ];

    protected $casts = [
        'data' => 'array',
        'expires_at' => 'datetime',
    ];

    /**
     * Scope to get only security events
     */
    public function scopeSecurity(Builder $query): Builder
    {
        return $query->where('event_type', 'like', 'security_%');
    }

    /**
     * Scope to get only compliance events
     */
    public function scopeCompliance(Builder $query): Builder
    {
        return $query->where('event_type', 'like', 'compliance_%');
    }

    /**
     * Scope to get only webhook events
     */
    public function scopeWebhooks(Builder $query): Builder
    {
        return $query->where('event_type', 'like', 'webhook_%');
    }

    /**
     * Scope to get only error events
     */
    public function scopeErrors(Builder $query): Builder
    {
        return $query->where('level', 'error');
    }

    /**
     * Scope to get events for a specific provider
     */
    public function scopeForProvider(Builder $query, string $provider): Builder
    {
        return $query->whereJsonContains('data->provider', $provider);
    }

    /**
     * Scope to get events for a specific subscription
     */
    public function scopeForSubscription(Builder $query, int $subscriptionId): Builder
    {
        return $query->whereJsonContains('data->subscription_id', $subscriptionId);
    }

    /**
     * Scope to get events that require review
     */
    public function scopeRequiresReview(Builder $query): Builder
    {
        return $query->whereJsonContains('data->requires_review', true);
    }

    /**
     * Scope to get events that haven't expired
     */
    public function scopeNotExpired(Builder $query): Builder
    {
        return $query->where(function ($q) {
            $q->whereNull('expires_at')
                ->orWhere('expires_at', '>', now());
        });
    }

    /**
     * Scope to get expired events (for cleanup)
     */
    public function scopeExpired(Builder $query): Builder
    {
        return $query->where('expires_at', '<', now());
    }

    /**
     * Get the user relationship
     */
    public function user()
    {
        return $this->morphTo();
    }

    /**
     * Check if event is security-related
     */
    public function isSecurityEvent(): bool
    {
        return str_starts_with($this->event_type, 'security_');
    }

    /**
     * Check if event is compliance-related
     */
    public function isComplianceEvent(): bool
    {
        return str_starts_with($this->event_type, 'compliance_');
    }

    /**
     * Check if event is webhook-related
     */
    public function isWebhookEvent(): bool
    {
        return str_starts_with($this->event_type, 'webhook_');
    }

    /**
     * Check if event requires review
     */
    public function requiresReview(): bool
    {
        return ($this->data['requires_review'] ?? false) ||
               $this->isSecurityEvent() ||
               $this->level === 'error';
    }

    /**
     * Get the provider from event data
     */
    public function getProvider(): ?string
    {
        return $this->data['provider'] ?? null;
    }

    /**
     * Get the subscription ID from event data
     */
    public function getSubscriptionId(): ?int
    {
        return $this->data['subscription_id'] ?? null;
    }

    /**
     * Get the action from event data
     */
    public function getAction(): ?string
    {
        return $this->data['action'] ?? null;
    }

    /**
     * Check if event contains sensitive data
     */
    public function containsSensitiveData(): bool
    {
        $sensitiveKeys = ['payment_method', 'card_number', 'bank_account', 'ssn', 'full_credit_card'];

        foreach ($sensitiveKeys as $key) {
            if (isset($this->data[$key])) {
                return true;
            }
        }

        return false;
    }

    /**
     * Get sanitized data for display (removes sensitive information)
     */
    public function getSanitizedData(): array
    {
        $data = $this->data;

        // Remove or mask sensitive fields
        $sensitivePatterns = [
            '/payment_method.*?number/i',
            '/card_?number/i',
            '/cvv/i',
            '/cvc/i',
            '/ssn/i',
            '/bank_?account/i',
            '/routing_?number/i',
        ];

        foreach ($sensitivePatterns as $pattern) {
            $data = array_map(function ($value) use ($pattern) {
                if (is_string($value) && preg_match($pattern, $value)) {
                    return str_repeat('*', strlen($value) - 4).substr($value, -4);
                }

                return $value;
            }, $data);
        }

        return $data;
    }

    /**
     * Export event for compliance reporting
     */
    public function toComplianceArray(): array
    {
        return [
            'id' => $this->id,
            'event_type' => $this->event_type,
            'level' => $this->level,
            'created_at' => $this->created_at->toISOString(),
            'user_id' => $this->user_id,
            'user_type' => $this->user_type,
            'request_id' => $this->request_id,
            'ip_address' => $this->ip_address,
            'provider' => $this->getProvider(),
            'subscription_id' => $this->getSubscriptionId(),
            'action' => $this->getAction(),
            'requires_review' => $this->requiresReview(),
            'is_security_event' => $this->isSecurityEvent(),
            'is_compliance_event' => $this->isComplianceEvent(),
            'contains_sensitive_data' => $this->containsSensitiveData(),
        ];
    }

    /**
     * Clean up old events based on retention policy
     */
    public static function cleanup(): array
    {
        $results = [];

        // Clean up expired webhook payloads
        $webhookCleanup = static::webhooks()
            ->expired()
            ->delete();

        $results['webhook_payloads'] = $webhookCleanup;

        // Clean up old debug events
        $debugCleanup = static::where('level', 'debug')
            ->where('created_at', '<', now()->subDays(90))
            ->delete();

        $results['debug_events'] = $debugCleanup;

        // Clean up old info events (keep for 1 year)
        $infoCleanup = static::where('level', 'info')
            ->where('created_at', '<', now()->subYear())
            ->whereNot(function ($query) {
                $query->security()
                    ->compliance();
            })
            ->delete();

        $results['info_events'] = $infoCleanup;

        return $results;
    }

    /**
     * Get events by date range for reporting
     */
    public static function getByDateRange(\DateTime $start, \DateTime $end, array $filters = []): Builder
    {
        $query = static::whereBetween('created_at', [$start, $end]);

        if (! empty($filters['event_types'])) {
            $query->whereIn('event_type', $filters['event_types']);
        }

        if (! empty($filters['levels'])) {
            $query->whereIn('level', $filters['levels']);
        }

        if (! empty($filters['user_id'])) {
            $query->where('user_id', $filters['user_id']);
        }

        if (! empty($filters['provider'])) {
            $query->forProvider($filters['provider']);
        }

        return $query;
    }
}
