<?php
/**
 * Submission tracking service for managing contact form submissions
 */

require_once 'Database.php';
require_once 'Logger.php';

class SubmissionTracker {
    private $db;
    
    public function __construct() {
        $this->db = Database::getInstance();
    }
    
    /**
     * Save new submission to database
     */
    public function saveSubmission($data) {
        try {
            $this->db->beginTransaction();
            
            // Generate unique submission ID
            $submissionId = $this->generateSubmissionId();
            
            // Save main submission
            $submissionData = [
                'submission_id' => $submissionId,
                'name' => $data['name'],
                'email' => $data['email'],
                'message' => $data['message'],
                'ip_address' => $data['ip_address'],
                'user_agent' => $data['user_agent'] ?? null,
                'referrer' => $data['referrer'] ?? null,
                'submission_status' => 'pending'
            ];
            
            $this->db->insert('contact_submissions', $submissionData);
            
            // Update IP tracking
            $this->updateIpTracking($data['ip_address'], $data);
            
            // Log security event if suspicious
            $this->checkForSuspiciousActivity($data);
            
            $this->db->commit();
            
            Logger::info('Submission saved successfully', [
                'submission_id' => $submissionId,
                'email' => $data['email'],
                'ip_address' => $data['ip_address']
            ]);
            
            return $submissionId;
            
        } catch (Exception $e) {
            $this->db->rollback();
            Logger::error('Failed to save submission', [
                'error' => $e->getMessage(),
                'data' => $data
            ]);
            throw new Exception('Failed to save submission: ' . $e->getMessage());
        }
    }
    
    /**
     * Update submission status
     */
    public function updateSubmissionStatus($submissionId, $status, $notes = null) {
        $updateData = [
            'submission_status' => $status,
            'updated_at' => date('Y-m-d H:i:s')
        ];
        
        if ($notes) {
            $updateData['processing_notes'] = $notes;
        }
        
        return $this->db->update(
            'contact_submissions',
            $updateData,
            'submission_id = ?',
            [$submissionId]
        );
    }
    
    /**
     * Mark email as sent
     */
    public function markEmailSent($submissionId, $emailType = 'notification') {
        $this->db->update(
            'contact_submissions',
            [
                'email_sent' => true,
                'email_sent_at' => date('Y-m-d H:i:s')
            ],
            'submission_id = ?',
            [$submissionId]
        );
        
        // Track email in email_tracking table
        $emailData = [
            'submission_id' => $submissionId,
            'email_type' => $emailType,
            'recipient_email' => $this->getSubmissionEmail($submissionId),
            'email_status' => 'sent',
            'sent_at' => date('Y-m-d H:i:s')
        ];
        
        $this->db->insert('email_tracking', $emailData);
    }
    
    /**
     * Log email failure
     */
    public function logEmailFailure($submissionId, $emailType, $errorMessage) {
        $emailData = [
            'submission_id' => $submissionId,
            'email_type' => $emailType,
            'recipient_email' => $this->getSubmissionEmail($submissionId),
            'email_status' => 'failed',
            'error_message' => $errorMessage
        ];
        
        $this->db->insert('email_tracking', $emailData);
    }
    
    /**
     * Get submission by ID
     */
    public function getSubmission($submissionId) {
        return $this->db->fetch(
            'SELECT * FROM contact_submissions WHERE submission_id = ?',
            [$submissionId]
        );
    }
    
    /**
     * Get recent submissions
     */
    public function getRecentSubmissions($limit = 50, $offset = 0) {
        return $this->db->fetchAll(
            'SELECT * FROM recent_submissions LIMIT ? OFFSET ?',
            [$limit, $offset]
        );
    }
    
    /**
     * Get submission statistics
     */
    public function getSubmissionStats($days = 30) {
        return $this->db->fetchAll(
            'SELECT * FROM submission_stats WHERE submission_date >= DATE_SUB(CURDATE(), INTERVAL ? DAY) ORDER BY submission_date DESC',
            [$days]
        );
    }
    
    /**
     * Get IP information
     */
    public function getIpInfo($ipAddress) {
        return $this->db->fetch(
            'SELECT * FROM ip_tracking WHERE ip_address = ?',
            [$ipAddress]
        );
    }
    
    /**
     * Check if IP is blocked
     */
    public function isIpBlocked($ipAddress) {
        $result = $this->db->fetch(
            'SELECT is_blocked, reputation_score FROM ip_tracking WHERE ip_address = ?',
            [$ipAddress]
        );
        
        if (!$result) {
            return false;
        }
        
        return $result['is_blocked'] || $result['reputation_score'] < 0.3;
    }
    
    /**
     * Block IP address
     */
    public function blockIp($ipAddress, $reason) {
        $this->db->update(
            'ip_tracking',
            [
                'is_blocked' => true,
                'block_reason' => $reason,
                'reputation_score' => 0.0
            ],
            'ip_address = ?',
            [$ipAddress]
        );
        
        $this->logSecurityEvent('ip_blocked', $ipAddress, "IP blocked: {$reason}");
    }
    
    /**
     * Get security events
     */
    public function getSecurityEvents($limit = 100, $severity = null) {
        $sql = 'SELECT * FROM security_events';
        $params = [];
        
        if ($severity) {
            $sql .= ' WHERE severity = ?';
            $params[] = $severity;
        }
        
        $sql .= ' ORDER BY created_at DESC LIMIT ?';
        $params[] = $limit;
        
        return $this->db->fetchAll($sql, $params);
    }
    
    /**
     * Search submissions
     */
    public function searchSubmissions($query, $limit = 50) {
        $sql = 'SELECT * FROM contact_submissions 
                WHERE name LIKE ? OR email LIKE ? OR message LIKE ?
                ORDER BY created_at DESC LIMIT ?';
        
        $searchTerm = "%{$query}%";
        return $this->db->fetchAll($sql, [$searchTerm, $searchTerm, $searchTerm, $limit]);
    }
    
    /**
     * Get submissions by date range
     */
    public function getSubmissionsByDateRange($startDate, $endDate) {
        return $this->db->fetchAll(
            'SELECT * FROM contact_submissions 
             WHERE created_at BETWEEN ? AND ? 
             ORDER BY created_at DESC',
            [$startDate, $endDate]
        );
    }
    
    /**
     * Generate unique submission ID
     */
    private function generateSubmissionId() {
        return sprintf(
            '%04x%04x-%04x-%04x-%04x-%04x%04x%04x',
            mt_rand(0, 0xffff), mt_rand(0, 0xffff),
            mt_rand(0, 0xffff),
            mt_rand(0, 0x0fff) | 0x4000,
            mt_rand(0, 0x3fff) | 0x8000,
            mt_rand(0, 0xffff), mt_rand(0, 0xffff), mt_rand(0, 0xffff)
        );
    }
    
    /**
     * Update IP tracking information
     */
    private function updateIpTracking($ipAddress, $submissionData) {
        // Get geo-location data (you can integrate with a geo IP service)
        $geoData = $this->getGeoLocation($ipAddress);
        
        $this->db->query(
            'CALL update_ip_tracking(?, ?, ?, ?)',
            [
                $ipAddress,
                $geoData['country_code'] ?? null,
                $geoData['city'] ?? null,
                $geoData['organization'] ?? null
            ]
        );
    }
    
    /**
     * Get geo-location data for IP (placeholder - integrate with real service)
     */
    private function getGeoLocation($ipAddress) {
        // Handle local IPs
        if ($ipAddress === '127.0.0.1' || strpos($ipAddress, '192.168.') === 0 || strpos($ipAddress, '10.') === 0) {
            return [
                'country_code' => 'US',
                'city' => 'Local',
                'organization' => 'Local Network'
            ];
        }
        
        // Simple IP geolocation using ip-api.com (free tier)
        try {
            $url = "http://ip-api.com/json/{$ipAddress}?fields=status,message,countryCode,city,org";
            $context = stream_context_create([
                'http' => [
                    'timeout' => 5,
                    'user_agent' => 'MarkTechSolution/1.0'
                ]
            ]);
            
            $response = file_get_contents($url, false, $context);
            $data = json_decode($response, true);
            
            if ($data && $data['status'] === 'success') {
                return [
                    'country_code' => $data['countryCode'] ?? null,
                    'city' => $data['city'] ?? null,
                    'organization' => $data['org'] ?? null
                ];
            }
        } catch (Exception $e) {
            Logger::warning('Geo-location lookup failed', [
                'ip' => $ipAddress,
                'error' => $e->getMessage()
            ]);
        }
        
        // Fallback values
        return [
            'country_code' => 'US',
            'city' => 'Unknown',
            'organization' => 'Unknown'
        ];
    }
    
    /**
     * Check for suspicious activity and log if needed
     */
    private function checkForSuspiciousActivity($data) {
        $ipInfo = $this->getIpInfo($data['ip_address']);
        
        // Check for rapid submissions from same IP
        if ($ipInfo && $ipInfo['total_submissions'] > 10) {
            $timeThreshold = date('Y-m-d H:i:s', strtotime('-1 hour'));
            
            $recentCount = $this->db->fetch(
                'SELECT COUNT(*) as count FROM contact_submissions 
                 WHERE ip_address = ? AND created_at >= ?',
                [$data['ip_address'], $timeThreshold]
            )['count'];
            
            if ($recentCount > 5) {
                $this->logSecurityEvent(
                    'suspicious_activity',
                    $data['ip_address'],
                    "Rapid submissions detected: {$recentCount} in last hour"
                );
            }
        }
        
        // Check for suspicious patterns in message
        $message = strtolower($data['message']);
        $suspiciousPatterns = [
            'test', 'spam', 'xxx', 'casino', 'lottery', 'winner', 'congratulations',
            'click here', 'free money', 'urgent', 'act now'
        ];
        
        $patternCount = 0;
        foreach ($suspiciousPatterns as $pattern) {
            if (strpos($message, $pattern) !== false) {
                $patternCount++;
            }
        }
        
        if ($patternCount > 3) {
            $this->logSecurityEvent(
                'suspicious_activity',
                $data['ip_address'],
                "Suspicious message patterns detected: {$patternCount} matches"
            );
        }
    }
    
    /**
     * Log security event
     */
    private function logSecurityEvent($eventType, $ipAddress, $details) {
        $eventData = [
            'event_type' => $eventType,
            'ip_address' => $ipAddress,
            'event_details' => $details,
            'severity' => $this->getEventSeverity($eventType)
        ];
        
        $this->db->insert('security_events', $eventData);
        
        Logger::warning('Security event logged', $eventData);
    }
    
    /**
     * Get severity level for event type
     */
    private function getEventSeverity($eventType) {
        $severityMap = [
            'csrf_failure' => 'high',
            'rate_limit_exceeded' => 'medium',
            'recaptcha_failed' => 'medium',
            'invalid_input' => 'low',
            'suspicious_activity' => 'high',
            'ip_blocked' => 'critical'
        ];
        
        return $severityMap[$eventType] ?? 'medium';
    }
    
    /**
     * Get submission email by ID
     */
    private function getSubmissionEmail($submissionId) {
        $result = $this->db->fetch(
            'SELECT email FROM contact_submissions WHERE submission_id = ?',
            [$submissionId]
        );
        
        return $result ? $result['email'] : null;
    }
}
