<?php
/**
 * HVAC Community Events - Communication Logger
 *
 * Handles logging of communication schedule execution and delivery.
 * Tracks sent emails, failures, and schedule performance.
 *
 * @package HVAC_Community_Events
 * @subpackage Communication
 * @version 1.0.0
 */

// Exit if accessed directly
if ( ! defined( 'ABSPATH' ) ) {
    exit;
}

/**
 * Class HVAC_Communication_Logger
 *
 * Manages logging for communication schedules and delivery.
 */
class HVAC_Communication_Logger {

    /**
     * Database table names
     */
    private $logs_table;

    /**
     * Constructor
     */
    public function __construct() {
        global $wpdb;
        
        $this->logs_table = $wpdb->prefix . 'hvac_communication_logs';
    }

    /**
     * Log a schedule execution
     *
     * @param int $schedule_id Schedule ID
     * @param string $status Execution status ('sent', 'failed', 'skipped')
     * @param array $details Additional execution details
     * @return int|false Log ID on success, false on failure
     */
    public function log_schedule_execution( $schedule_id, $status, $details = array() ) {
        global $wpdb;

        $log_data = array(
            'schedule_id' => intval( $schedule_id ),
            'status' => sanitize_text_field( $status ),
            'sent_date' => current_time( 'mysql' ),
            'recipient_count' => isset( $details['recipient_count'] ) ? intval( $details['recipient_count'] ) : 0,
            'success_count' => isset( $details['success_count'] ) ? intval( $details['success_count'] ) : 0,
            'error_count' => isset( $details['error_count'] ) ? intval( $details['error_count'] ) : 0,
            'execution_time' => isset( $details['execution_time'] ) ? floatval( $details['execution_time'] ) : 0,
            'details' => ! empty( $details ) ? wp_json_encode( $details ) : null
        );

        $formats = array( '%d', '%s', '%s', '%d', '%d', '%d', '%f', '%s' );

        $result = $wpdb->insert( $this->logs_table, $log_data, $formats );

        if ( $result === false ) {
            if ( class_exists( 'HVAC_Logger' ) ) {
                HVAC_Logger::error( 'Failed to log schedule execution: ' . $wpdb->last_error, 'Communication Logger' );
            }
            return false;
        }

        return $wpdb->insert_id;
    }

    /**
     * Log individual email delivery
     *
     * @param int $schedule_id Schedule ID
     * @param string $recipient_email Recipient email address
     * @param string $status Delivery status ('sent', 'failed', 'bounced')
     * @param array $details Additional delivery details
     * @return int|false Log ID on success, false on failure
     */
    public function log_email_delivery( $schedule_id, $recipient_email, $status, $details = array() ) {
        global $wpdb;

        $log_data = array(
            'schedule_id' => intval( $schedule_id ),
            'recipient_email' => sanitize_email( $recipient_email ),
            'status' => sanitize_text_field( $status ),
            'sent_date' => current_time( 'mysql' ),
            'details' => ! empty( $details ) ? wp_json_encode( $details ) : null
        );

        $formats = array( '%d', '%s', '%s', '%s', '%s' );

        $result = $wpdb->insert( $this->logs_table, $log_data, $formats );

        return $result !== false ? $wpdb->insert_id : false;
    }

    /**
     * Get execution logs for a schedule
     *
     * @param int $schedule_id Schedule ID
     * @param array $args Query arguments
     * @return array Array of log entries
     */
    public function get_schedule_logs( $schedule_id, $args = array() ) {
        global $wpdb;

        $defaults = array(
            'limit' => 50,
            'offset' => 0,
            'status' => null,
            'date_from' => null,
            'date_to' => null
        );

        $args = wp_parse_args( $args, $defaults );

        $where_clauses = array( 'schedule_id = %d' );
        $where_values = array( intval( $schedule_id ) );

        // Status filter
        if ( ! empty( $args['status'] ) ) {
            $where_clauses[] = 'status = %s';
            $where_values[] = $args['status'];
        }

        // Date range filters
        if ( ! empty( $args['date_from'] ) ) {
            $where_clauses[] = 'sent_date >= %s';
            $where_values[] = $args['date_from'];
        }

        if ( ! empty( $args['date_to'] ) ) {
            $where_clauses[] = 'sent_date <= %s';
            $where_values[] = $args['date_to'];
        }

        $where_sql = implode( ' AND ', $where_clauses );

        $sql = "SELECT * FROM {$this->logs_table} 
                WHERE {$where_sql} 
                ORDER BY sent_date DESC 
                LIMIT %d OFFSET %d";

        $where_values[] = intval( $args['limit'] );
        $where_values[] = intval( $args['offset'] );

        $logs = $wpdb->get_results( $wpdb->prepare( $sql, $where_values ), ARRAY_A );

        // Decode JSON details
        foreach ( $logs as &$log ) {
            if ( ! empty( $log['details'] ) ) {
                $log['details'] = json_decode( $log['details'], true );
            }
        }

        return $logs;
    }

    /**
     * Get logs for all schedules with filtering
     *
     * @param array $args Query arguments
     * @return array Array of log entries with schedule info
     */
    public function get_all_logs( $args = array() ) {
        global $wpdb;

        $defaults = array(
            'limit' => 50,
            'offset' => 0,
            'trainer_id' => null,
            'status' => null,
            'date_from' => null,
            'date_to' => null
        );

        $args = wp_parse_args( $args, $defaults );

        $schedules_table = $wpdb->prefix . 'hvac_communication_schedules';

        $where_clauses = array();
        $where_values = array();

        // Trainer filter
        if ( ! empty( $args['trainer_id'] ) ) {
            $where_clauses[] = 's.trainer_id = %d';
            $where_values[] = intval( $args['trainer_id'] );
        }

        // Status filter
        if ( ! empty( $args['status'] ) ) {
            $where_clauses[] = 'l.status = %s';
            $where_values[] = $args['status'];
        }

        // Date range filters
        if ( ! empty( $args['date_from'] ) ) {
            $where_clauses[] = 'l.sent_date >= %s';
            $where_values[] = $args['date_from'];
        }

        if ( ! empty( $args['date_to'] ) ) {
            $where_clauses[] = 'l.sent_date <= %s';
            $where_values[] = $args['date_to'];
        }

        $where_sql = ! empty( $where_clauses ) ? 'WHERE ' . implode( ' AND ', $where_clauses ) : '';

        $sql = "SELECT l.*, 
                       s.trainer_id,
                       s.event_id,
                       s.template_id,
                       s.trigger_type,
                       e.post_title as event_name,
                       t.post_title as template_name
                FROM {$this->logs_table} l
                LEFT JOIN {$schedules_table} s ON l.schedule_id = s.schedule_id
                LEFT JOIN {$wpdb->posts} e ON s.event_id = e.ID
                LEFT JOIN {$wpdb->posts} t ON s.template_id = t.ID
                {$where_sql}
                ORDER BY l.sent_date DESC 
                LIMIT %d OFFSET %d";

        $where_values[] = intval( $args['limit'] );
        $where_values[] = intval( $args['offset'] );

        $logs = $wpdb->get_results( $wpdb->prepare( $sql, $where_values ), ARRAY_A );

        // Decode JSON details
        foreach ( $logs as &$log ) {
            if ( ! empty( $log['details'] ) ) {
                $log['details'] = json_decode( $log['details'], true );
            }
        }

        return $logs;
    }

    /**
     * Get summary statistics for communication logs
     *
     * @param int|null $trainer_id Optional trainer ID filter
     * @param string|null $date_from Optional start date filter
     * @param string|null $date_to Optional end date filter
     * @return array Statistics array
     */
    public function get_statistics( $trainer_id = null, $date_from = null, $date_to = null ) {
        global $wpdb;

        $schedules_table = $wpdb->prefix . 'hvac_communication_schedules';

        $where_clauses = array();
        $where_values = array();

        if ( ! empty( $trainer_id ) ) {
            $where_clauses[] = 's.trainer_id = %d';
            $where_values[] = intval( $trainer_id );
        }

        if ( ! empty( $date_from ) ) {
            $where_clauses[] = 'l.sent_date >= %s';
            $where_values[] = $date_from;
        }

        if ( ! empty( $date_to ) ) {
            $where_clauses[] = 'l.sent_date <= %s';
            $where_values[] = $date_to;
        }

        $where_sql = ! empty( $where_clauses ) ? 'WHERE ' . implode( ' AND ', $where_clauses ) : '';

        $sql = "SELECT 
                    COUNT(*) as total_executions,
                    COUNT(CASE WHEN l.status = 'sent' THEN 1 END) as successful_executions,
                    COUNT(CASE WHEN l.status = 'failed' THEN 1 END) as failed_executions,
                    COUNT(CASE WHEN l.status = 'skipped' THEN 1 END) as skipped_executions,
                    SUM(l.recipient_count) as total_recipients,
                    SUM(l.success_count) as total_emails_sent,
                    SUM(l.error_count) as total_email_errors,
                    AVG(l.execution_time) as avg_execution_time
                FROM {$this->logs_table} l
                LEFT JOIN {$schedules_table} s ON l.schedule_id = s.schedule_id
                {$where_sql}";

        $stats = $wpdb->get_row( 
            empty( $where_values ) ? $sql : $wpdb->prepare( $sql, $where_values ), 
            ARRAY_A 
        );

        // Ensure numeric values
        foreach ( $stats as $key => $value ) {
            if ( in_array( $key, array( 'avg_execution_time' ) ) ) {
                $stats[$key] = floatval( $value );
            } else {
                $stats[$key] = intval( $value );
            }
        }

        return $stats;
    }

    /**
     * Get recent execution activity
     *
     * @param int $limit Number of recent activities to retrieve
     * @param int|null $trainer_id Optional trainer ID filter
     * @return array Array of recent activities
     */
    public function get_recent_activity( $limit = 10, $trainer_id = null ) {
        global $wpdb;

        $schedules_table = $wpdb->prefix . 'hvac_communication_schedules';

        $where_clause = '';
        $where_values = array();

        if ( ! empty( $trainer_id ) ) {
            $where_clause = 'WHERE s.trainer_id = %d';
            $where_values[] = intval( $trainer_id );
        }

        $sql = "SELECT l.*, 
                       s.trainer_id,
                       e.post_title as event_name,
                       t.post_title as template_name
                FROM {$this->logs_table} l
                LEFT JOIN {$schedules_table} s ON l.schedule_id = s.schedule_id
                LEFT JOIN {$wpdb->posts} e ON s.event_id = e.ID
                LEFT JOIN {$wpdb->posts} t ON s.template_id = t.ID
                {$where_clause}
                ORDER BY l.sent_date DESC 
                LIMIT %d";

        $where_values[] = intval( $limit );

        $activities = $wpdb->get_results( $wpdb->prepare( $sql, $where_values ), ARRAY_A );

        // Decode JSON details and format for display
        foreach ( $activities as &$activity ) {
            if ( ! empty( $activity['details'] ) ) {
                $activity['details'] = json_decode( $activity['details'], true );
            }

            // Add human-readable time
            $activity['time_ago'] = human_time_diff( strtotime( $activity['sent_date'] ), current_time( 'timestamp' ) ) . ' ago';
        }

        return $activities;
    }

    /**
     * Clean up old log entries
     *
     * @param int $days_to_keep Number of days to keep logs (default 90)
     * @return int Number of entries deleted
     */
    public function cleanup_old_logs( $days_to_keep = 90 ) {
        global $wpdb;

        $cutoff_date = date( 'Y-m-d H:i:s', strtotime( "-{$days_to_keep} days" ) );

        $deleted = $wpdb->query( $wpdb->prepare(
            "DELETE FROM {$this->logs_table} WHERE sent_date < %s",
            $cutoff_date
        ) );

        if ( $deleted !== false && class_exists( 'HVAC_Logger' ) ) {
            HVAC_Logger::info( "Cleaned up {$deleted} old communication log entries", 'Communication Logger' );
        }

        return intval( $deleted );
    }

    /**
     * Export logs to CSV format
     *
     * @param array $args Export arguments
     * @return string CSV content
     */
    public function export_logs_csv( $args = array() ) {
        $logs = $this->get_all_logs( $args );

        $csv_header = array(
            'Date',
            'Schedule ID',
            'Event',
            'Template',
            'Status',
            'Recipients',
            'Successful',
            'Errors',
            'Execution Time (s)'
        );

        $csv_data = array();
        $csv_data[] = $csv_header;

        foreach ( $logs as $log ) {
            $csv_data[] = array(
                $log['sent_date'],
                $log['schedule_id'],
                $log['event_name'] ?: 'N/A',
                $log['template_name'] ?: 'N/A',
                $log['status'],
                $log['recipient_count'],
                $log['success_count'],
                $log['error_count'],
                $log['execution_time']
            );
        }

        // Convert to CSV string
        $csv_content = '';
        foreach ( $csv_data as $row ) {
            $csv_content .= '"' . implode( '","', $row ) . '"' . "\n";
        }

        return $csv_content;
    }

    /**
     * Get performance metrics for schedules
     *
     * @param int|null $trainer_id Optional trainer ID filter
     * @return array Performance metrics
     */
    public function get_performance_metrics( $trainer_id = null ) {
        global $wpdb;

        $schedules_table = $wpdb->prefix . 'hvac_communication_schedules';

        $where_clause = '';
        $where_values = array();

        if ( ! empty( $trainer_id ) ) {
            $where_clause = 'WHERE s.trainer_id = %d';
            $where_values[] = intval( $trainer_id );
        }

        // Get delivery success rate
        $sql = "SELECT 
                    COUNT(*) as total_schedules,
                    AVG(CASE WHEN l.status = 'sent' THEN 100.0 ELSE 0.0 END) as success_rate,
                    AVG(l.execution_time) as avg_execution_time,
                    SUM(l.recipient_count) / COUNT(*) as avg_recipients_per_execution
                FROM {$this->logs_table} l
                LEFT JOIN {$schedules_table} s ON l.schedule_id = s.schedule_id
                {$where_clause}";

        $metrics = $wpdb->get_row( 
            empty( $where_values ) ? $sql : $wpdb->prepare( $sql, $where_values ), 
            ARRAY_A 
        );

        // Format metrics
        $metrics['success_rate'] = round( floatval( $metrics['success_rate'] ), 2 );
        $metrics['avg_execution_time'] = round( floatval( $metrics['avg_execution_time'] ), 3 );
        $metrics['avg_recipients_per_execution'] = round( floatval( $metrics['avg_recipients_per_execution'] ), 1 );

        return $metrics;
    }
}