<?php
/**
 * HVAC Community Events - Communication Schedule Manager
 *
 * Handles CRUD operations for communication schedules.
 * Manages database interactions and schedule validation.
 *
 * @package HVAC_Community_Events
 * @subpackage Communication
 * @version 1.0.0
 */

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

/**
 * Class HVAC_Communication_Schedule_Manager
 *
 * Manages communication schedule database operations.
 */
class HVAC_Communication_Schedule_Manager {

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

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

    /**
     * Save a communication schedule
     *
     * @param array $schedule_data Schedule configuration
     * @return int|false Schedule ID on success, false on failure
     */
    public function save_schedule( $schedule_data ) {
        global $wpdb;

        $data = array(
            'trainer_id' => intval( $schedule_data['trainer_id'] ),
            'event_id' => ! empty( $schedule_data['event_id'] ) ? intval( $schedule_data['event_id'] ) : null,
            'template_id' => intval( $schedule_data['template_id'] ),
            'schedule_type' => isset( $schedule_data['schedule_type'] ) ? $schedule_data['schedule_type'] : 'time_based',
            'trigger_type' => sanitize_text_field( $schedule_data['trigger_type'] ),
            'trigger_value' => intval( $schedule_data['trigger_value'] ),
            'trigger_unit' => sanitize_text_field( $schedule_data['trigger_unit'] ),
            'status' => isset( $schedule_data['status'] ) ? sanitize_text_field( $schedule_data['status'] ) : 'active',
            'target_audience' => sanitize_text_field( $schedule_data['target_audience'] ),
            'custom_recipient_list' => ! empty( $schedule_data['custom_recipient_list'] ) ? 
                sanitize_textarea_field( $schedule_data['custom_recipient_list'] ) : null,
            'conditions' => ! empty( $schedule_data['conditions'] ) ? 
                wp_json_encode( $schedule_data['conditions'] ) : null,
            'next_run' => ! empty( $schedule_data['next_run'] ) ? 
                sanitize_text_field( $schedule_data['next_run'] ) : null,
            'is_recurring' => isset( $schedule_data['is_recurring'] ) ? 
                (int) $schedule_data['is_recurring'] : 0,
            'recurring_interval' => ! empty( $schedule_data['recurring_interval'] ) ? 
                intval( $schedule_data['recurring_interval'] ) : null,
            'recurring_unit' => ! empty( $schedule_data['recurring_unit'] ) ? 
                sanitize_text_field( $schedule_data['recurring_unit'] ) : null,
            'max_runs' => ! empty( $schedule_data['max_runs'] ) ? 
                intval( $schedule_data['max_runs'] ) : null
        );

        $formats = array(
            '%d', // trainer_id
            '%d', // event_id
            '%d', // template_id
            '%s', // schedule_type
            '%s', // trigger_type
            '%d', // trigger_value
            '%s', // trigger_unit
            '%s', // status
            '%s', // target_audience
            '%s', // custom_recipient_list
            '%s', // conditions
            '%s', // next_run
            '%d', // is_recurring
            '%d', // recurring_interval
            '%s', // recurring_unit
            '%d'  // max_runs
        );

        $result = $wpdb->insert( $this->schedules_table, $data, $formats );

        if ( $result === false ) {
            if ( class_exists( 'HVAC_Logger' ) ) {
                HVAC_Logger::error( 'Failed to save communication schedule: ' . $wpdb->last_error, 'Schedule Manager' );
            }
            return false;
        }

        return $wpdb->insert_id;
    }

    /**
     * Update a communication schedule
     *
     * @param int $schedule_id Schedule ID
     * @param array $schedule_data Updated schedule data
     * @return bool Success status
     */
    public function update_schedule( $schedule_id, $schedule_data ) {
        global $wpdb;

        $data = array();
        $formats = array();

        // Only update provided fields
        $allowed_fields = array(
            'event_id' => '%d',
            'template_id' => '%d',
            'schedule_type' => '%s',
            'trigger_type' => '%s',
            'trigger_value' => '%d',
            'trigger_unit' => '%s',
            'status' => '%s',
            'target_audience' => '%s',
            'custom_recipient_list' => '%s',
            'conditions' => '%s',
            'next_run' => '%s',
            'is_recurring' => '%d',
            'recurring_interval' => '%d',
            'recurring_unit' => '%s',
            'max_runs' => '%d'
        );

        foreach ( $allowed_fields as $field => $format ) {
            if ( array_key_exists( $field, $schedule_data ) ) {
                if ( $field === 'conditions' && ! empty( $schedule_data[$field] ) ) {
                    $data[$field] = wp_json_encode( $schedule_data[$field] );
                } elseif ( in_array( $format, array( '%d' ) ) ) {
                    $data[$field] = intval( $schedule_data[$field] );
                } else {
                    $data[$field] = sanitize_text_field( $schedule_data[$field] );
                }
                $formats[] = $format;
            }
        }

        // Add modified timestamp
        $data['modified_date'] = current_time( 'mysql' );
        $formats[] = '%s';

        $result = $wpdb->update(
            $this->schedules_table,
            $data,
            array( 'schedule_id' => intval( $schedule_id ) ),
            $formats,
            array( '%d' )
        );

        return $result !== false;
    }

    /**
     * Get a communication schedule by ID
     *
     * @param int $schedule_id Schedule ID
     * @return array|null Schedule data or null if not found
     */
    public function get_schedule( $schedule_id ) {
        global $wpdb;

        $schedule = $wpdb->get_row( $wpdb->prepare(
            "SELECT * FROM {$this->schedules_table} WHERE schedule_id = %d",
            intval( $schedule_id )
        ), ARRAY_A );

        if ( $schedule && ! empty( $schedule['conditions'] ) ) {
            $schedule['conditions'] = json_decode( $schedule['conditions'], true );
        }

        return $schedule;
    }

    /**
     * Get schedules by trainer
     *
     * @param int $trainer_id Trainer user ID
     * @param int $event_id Optional specific event ID
     * @return array Array of schedules
     */
    public function get_schedules_by_trainer( $trainer_id, $event_id = null ) {
        global $wpdb;

        $where_clause = "WHERE trainer_id = %d";
        $params = array( intval( $trainer_id ) );

        if ( $event_id ) {
            $where_clause .= " AND event_id = %d";
            $params[] = intval( $event_id );
        }

        $schedules = $wpdb->get_results( $wpdb->prepare(
            "SELECT s.*, 
                    t.post_title as template_name,
                    e.post_title as event_name,
                    e.post_status as event_status
             FROM {$this->schedules_table} s
             LEFT JOIN {$wpdb->posts} t ON s.template_id = t.ID
             LEFT JOIN {$wpdb->posts} e ON s.event_id = e.ID
             {$where_clause}
             ORDER BY s.created_date DESC",
            $params
        ), ARRAY_A );

        // Process conditions field
        foreach ( $schedules as &$schedule ) {
            if ( ! empty( $schedule['conditions'] ) ) {
                $schedule['conditions'] = json_decode( $schedule['conditions'], true );
            }
        }

        return $schedules;
    }

    /**
     * Get schedules by event
     *
     * @param int $event_id Event ID
     * @return array Array of schedules
     */
    public function get_schedules_by_event( $event_id ) {
        global $wpdb;

        $schedules = $wpdb->get_results( $wpdb->prepare(
            "SELECT s.*, 
                    t.post_title as template_name
             FROM {$this->schedules_table} s
             LEFT JOIN {$wpdb->posts} t ON s.template_id = t.ID
             WHERE s.event_id = %d
             ORDER BY s.trigger_type, s.trigger_value",
            intval( $event_id )
        ), ARRAY_A );

        // Process conditions field
        foreach ( $schedules as &$schedule ) {
            if ( ! empty( $schedule['conditions'] ) ) {
                $schedule['conditions'] = json_decode( $schedule['conditions'], true );
            }
        }

        return $schedules;
    }

    /**
     * Get active schedules
     *
     * @return array Array of active schedules
     */
    public function get_active_schedules() {
        global $wpdb;

        return $wpdb->get_results(
            "SELECT * FROM {$this->schedules_table} 
             WHERE status = 'active'
             ORDER BY next_run ASC",
            ARRAY_A
        );
    }

    /**
     * Get due schedules
     *
     * @return array Array of schedules that are due for execution
     */
    public function get_due_schedules() {
        global $wpdb;

        $current_time = current_time( 'mysql' );

        $schedules = $wpdb->get_results( $wpdb->prepare(
            "SELECT * FROM {$this->schedules_table} 
             WHERE status = 'active' 
             AND next_run IS NOT NULL 
             AND next_run <= %s
             AND (max_runs IS NULL OR run_count < max_runs)
             ORDER BY next_run ASC",
            $current_time
        ), ARRAY_A );

        return $schedules;
    }

    /**
     * Delete a communication schedule
     *
     * @param int $schedule_id Schedule ID
     * @return bool Success status
     */
    public function delete_schedule( $schedule_id ) {
        global $wpdb;

        // Delete associated logs first (foreign key constraint)
        $wpdb->delete(
            $this->logs_table,
            array( 'schedule_id' => intval( $schedule_id ) ),
            array( '%d' )
        );

        // Delete the schedule
        $result = $wpdb->delete(
            $this->schedules_table,
            array( 'schedule_id' => intval( $schedule_id ) ),
            array( '%d' )
        );

        return $result !== false;
    }

    /**
     * Update schedule run tracking
     *
     * @param int $schedule_id Schedule ID
     * @return bool Success status
     */
    public function update_schedule_run_tracking( $schedule_id ) {
        global $wpdb;

        $schedule = $this->get_schedule( $schedule_id );
        if ( ! $schedule ) {
            return false;
        }

        $data = array(
            'last_run' => current_time( 'mysql' ),
            'run_count' => intval( $schedule['run_count'] ) + 1
        );

        // Calculate next run if recurring
        if ( $schedule['is_recurring'] ) {
            $next_run = $this->calculate_next_recurring_run( $schedule );
            if ( $next_run ) {
                $data['next_run'] = $next_run;
            }
        } else {
            // Mark as completed if not recurring
            $data['status'] = 'completed';
            $data['next_run'] = null;
        }

        return $this->update_schedule( $schedule_id, $data );
    }

    /**
     * Calculate next recurring run time
     *
     * @param array $schedule Schedule data
     * @return string|null Next run time or null
     */
    private function calculate_next_recurring_run( $schedule ) {
        if ( ! $schedule['is_recurring'] || ! $schedule['recurring_interval'] ) {
            return null;
        }

        $interval = $schedule['recurring_interval'];
        $unit = $schedule['recurring_unit'];

        $current_time = current_time( 'timestamp' );

        switch ( $unit ) {
            case 'days':
                $next_time = $current_time + ( $interval * DAY_IN_SECONDS );
                break;
            case 'weeks':
                $next_time = $current_time + ( $interval * WEEK_IN_SECONDS );
                break;
            case 'months':
                $next_time = strtotime( "+{$interval} months", $current_time );
                break;
            default:
                return null;
        }

        return date( 'Y-m-d H:i:s', $next_time );
    }

    /**
     * Validate schedule data
     *
     * @param array $schedule_data Schedule data to validate
     * @return bool|WP_Error True if valid, WP_Error if invalid
     */
    public function validate_schedule_data( $schedule_data ) {
        // Required fields
        $required_fields = array( 'trainer_id', 'template_id', 'trigger_type', 'target_audience' );
        
        foreach ( $required_fields as $field ) {
            if ( empty( $schedule_data[$field] ) ) {
                return new WP_Error( 'missing_field', sprintf( __( 'Required field missing: %s', 'hvac-community-events' ), $field ) );
            }
        }

        // Validate trainer exists and has permission
        $trainer = get_user_by( 'id', $schedule_data['trainer_id'] );
        if ( ! $trainer || ! in_array( 'hvac_trainer', $trainer->roles ) ) {
            return new WP_Error( 'invalid_trainer', __( 'Invalid trainer specified.', 'hvac-community-events' ) );
        }

        // Validate template exists and belongs to trainer
        $template = get_post( $schedule_data['template_id'] );
        if ( ! $template || $template->post_type !== 'hvac_email_template' ) {
            return new WP_Error( 'invalid_template', __( 'Invalid template specified.', 'hvac-community-events' ) );
        }

        if ( $template->post_author != $schedule_data['trainer_id'] && ! current_user_can( 'edit_others_posts' ) ) {
            return new WP_Error( 'template_permission', __( 'You do not have permission to use this template.', 'hvac-community-events' ) );
        }

        // Validate event if specified
        if ( ! empty( $schedule_data['event_id'] ) ) {
            $event = get_post( $schedule_data['event_id'] );
            if ( ! $event || $event->post_type !== 'tribe_events' ) {
                return new WP_Error( 'invalid_event', __( 'Invalid event specified.', 'hvac-community-events' ) );
            }

            // Check if trainer owns the event
            if ( $event->post_author != $schedule_data['trainer_id'] && ! current_user_can( 'edit_others_posts' ) ) {
                return new WP_Error( 'event_permission', __( 'You do not have permission to schedule communications for this event.', 'hvac-community-events' ) );
            }
        }

        // Validate trigger settings
        $valid_trigger_types = array( 'before_event', 'after_event', 'on_registration', 'custom_date' );
        if ( ! in_array( $schedule_data['trigger_type'], $valid_trigger_types ) ) {
            return new WP_Error( 'invalid_trigger_type', __( 'Invalid trigger type specified.', 'hvac-community-events' ) );
        }

        $valid_trigger_units = array( 'minutes', 'hours', 'days', 'weeks' );
        if ( ! in_array( $schedule_data['trigger_unit'], $valid_trigger_units ) ) {
            return new WP_Error( 'invalid_trigger_unit', __( 'Invalid trigger unit specified.', 'hvac-community-events' ) );
        }

        // Validate audience settings
        $valid_audiences = array( 'all_attendees', 'confirmed_attendees', 'pending_attendees', 'custom_list' );
        if ( ! in_array( $schedule_data['target_audience'], $valid_audiences ) ) {
            return new WP_Error( 'invalid_audience', __( 'Invalid target audience specified.', 'hvac-community-events' ) );
        }

        // Validate custom recipient list if specified
        if ( $schedule_data['target_audience'] === 'custom_list' && empty( $schedule_data['custom_recipient_list'] ) ) {
            return new WP_Error( 'missing_recipients', __( 'Custom recipient list is required when target audience is set to custom list.', 'hvac-community-events' ) );
        }

        // Validate recurring settings
        if ( ! empty( $schedule_data['is_recurring'] ) ) {
            if ( empty( $schedule_data['recurring_interval'] ) || empty( $schedule_data['recurring_unit'] ) ) {
                return new WP_Error( 'invalid_recurring', __( 'Recurring interval and unit are required for recurring schedules.', 'hvac-community-events' ) );
            }

            $valid_recurring_units = array( 'days', 'weeks', 'months' );
            if ( ! in_array( $schedule_data['recurring_unit'], $valid_recurring_units ) ) {
                return new WP_Error( 'invalid_recurring_unit', __( 'Invalid recurring unit specified.', 'hvac-community-events' ) );
            }
        }

        return true;
    }

    /**
     * Check for schedule conflicts
     *
     * @param array $schedule_data Schedule data to check
     * @return bool|WP_Error True if no conflicts, WP_Error if conflicts found
     */
    public function check_schedule_conflicts( $schedule_data ) {
        global $wpdb;

        // Check for duplicate schedules with same trigger settings
        $existing = $wpdb->get_var( $wpdb->prepare(
            "SELECT COUNT(*) FROM {$this->schedules_table} 
             WHERE trainer_id = %d 
             AND event_id = %d 
             AND template_id = %d 
             AND trigger_type = %s 
             AND trigger_value = %d 
             AND trigger_unit = %s 
             AND status = 'active'",
            $schedule_data['trainer_id'],
            $schedule_data['event_id'] ?? 0,
            $schedule_data['template_id'],
            $schedule_data['trigger_type'],
            $schedule_data['trigger_value'],
            $schedule_data['trigger_unit']
        ) );

        if ( $existing > 0 ) {
            return new WP_Error( 'duplicate_schedule', __( 'A schedule with identical settings already exists.', 'hvac-community-events' ) );
        }

        return true;
    }

    /**
     * Check if user can edit schedule
     *
     * @param int $schedule_id Schedule ID
     * @return bool Whether user can edit the schedule
     */
    public function user_can_edit_schedule( $schedule_id ) {
        $schedule = $this->get_schedule( $schedule_id );
        
        if ( ! $schedule ) {
            return false;
        }

        $current_user_id = get_current_user_id();
        
        // Owner can edit
        if ( $schedule['trainer_id'] == $current_user_id ) {
            return true;
        }

        // Admins can edit others' schedules
        if ( current_user_can( 'edit_others_posts' ) ) {
            return true;
        }

        return false;
    }

    /**
     * Get available templates for scheduling
     *
     * @param int $trainer_id Trainer user ID
     * @return array Array of available templates
     */
    public function get_available_templates( $trainer_id ) {
        $templates_manager = new HVAC_Communication_Templates();
        return $templates_manager->get_user_templates( $trainer_id );
    }

    /**
     * Validate template compatibility with schedule type
     *
     * @param int $template_id Template ID
     * @param string $schedule_type Schedule type
     * @return bool|WP_Error True if compatible, WP_Error if not
     */
    public function validate_template_compatibility( $template_id, $schedule_type ) {
        $template = get_post( $template_id );
        
        if ( ! $template || $template->post_type !== 'hvac_email_template' ) {
            return new WP_Error( 'invalid_template', __( 'Invalid template specified.', 'hvac-community-events' ) );
        }

        // Check for required placeholders based on schedule type
        $required_placeholders = array( '{attendee_name}', '{event_title}' );
        
        if ( $schedule_type === 'event_based' ) {
            $required_placeholders[] = '{event_date}';
            $required_placeholders[] = '{event_time}';
        }

        foreach ( $required_placeholders as $placeholder ) {
            if ( strpos( $template->post_content, $placeholder ) === false ) {
                return new WP_Error( 'missing_placeholder', 
                    sprintf( __( 'Template missing required placeholder: %s', 'hvac-community-events' ), $placeholder ) 
                );
            }
        }

        return true;
    }

    /**
     * Get schedule statistics for a trainer
     *
     * @param int $trainer_id Trainer user ID
     * @return array Statistics array
     */
    public function get_trainer_schedule_stats( $trainer_id ) {
        global $wpdb;

        $stats = $wpdb->get_row( $wpdb->prepare(
            "SELECT 
                COUNT(*) as total_schedules,
                COUNT(CASE WHEN status = 'active' THEN 1 END) as active_schedules,
                COUNT(CASE WHEN status = 'paused' THEN 1 END) as paused_schedules,
                COUNT(CASE WHEN status = 'completed' THEN 1 END) as completed_schedules,
                SUM(run_count) as total_executions
             FROM {$this->schedules_table} 
             WHERE trainer_id = %d",
            $trainer_id
        ), ARRAY_A );

        return $stats;
    }
}