<?php
/**
 * Monday.com Integration
 *
 * @package SPAI_Contact_Form
 */

class SPAI_Monday_Integration extends SPAI_Integration_Base {
    
    /**
     * API Key
     */
    private $api_key;
    
    /**
     * API URL
     */
    private $api_url = 'https://api.monday.com/v2';
    
    /**
     * Constructor
     */
    public function __construct($api_key = '') {
        $this->api_key = $api_key;
    }
    
    /**
     * Log messages
     */
    protected function log($message, $level = 'info', $data = null) {
            strtoupper($level), 
            $message, 
            $data ? json_encode($data) : ''
        ));
    }
    
    /**
     * Get integration name
     */
    public function get_name() {
        return 'Monday.com';
    }
    
    /**
     * Get integration description
     */
    public function get_description() {
        return __('Create items in Monday.com boards from form submissions', 'spai-contact-form');
    }
    
    /**
     * Get settings fields
     */
    public function get_settings_fields() {
        return array(
            'api_key' => array(
                'type' => 'password',
                'label' => __('API Key', 'spai-contact-form'),
                'required' => true,
                'description' => __('Your Monday.com API v2 key', 'spai-contact-form')
            ),
            'board_id' => array(
                'type' => 'select',
                'label' => __('Board', 'spai-contact-form'),
                'required' => true,
                'options' => array(),
                'description' => __('Select the board to create items in', 'spai-contact-form')
            )
        );
    }
    
    /**
     * Get field configuration
     */
    public function get_fields_config() {
        return array(
            'name' => array(
                'type' => 'text',
                'label' => __('Item Name', 'spai-contact-form'),
                'required' => true
            ),
            'status' => array(
                'type' => 'status',
                'label' => __('Status', 'spai-contact-form'),
                'default' => 'New Lead'
            ),
            'email' => array(
                'type' => 'email',
                'label' => __('Email', 'spai-contact-form')
            ),
            'phone' => array(
                'type' => 'phone',
                'label' => __('Phone', 'spai-contact-form')
            ),
            'text' => array(
                'type' => 'text',
                'label' => __('Text Column', 'spai-contact-form')
            )
        );
    }
    
    /**
     * Process submission
     */
    public function process_submission($data, $mapping) {
        if (empty($this->api_key)) {
            return array(
                'success' => false,
                'message' => __('Monday.com API key not configured', 'spai-contact-form')
            );
        }
        
        // Map fields
        $mapped_data = $this->map_fields($data, $mapping);
        
        // Create item
        return $this->create_item($mapped_data, array(), $mapping);
    }
    
    /**
     * Create item in Monday.com
     */
    public function create_item($form_data, $file_data, $settings) {
        // Get field mapping
        $field_mapping = get_option('spai_contact_form_monday_mapping', array());
        
        // Build column values based on mapping
        $column_values = array();
        
        // Build address components for item name
        $address_parts = array();
        if (!empty($form_data['street'])) $address_parts[] = $form_data['street'];
        if (!empty($form_data['city'])) $address_parts[] = $form_data['city'];
        if (!empty($form_data['state'])) $address_parts[] = $form_data['state'];
        if (!empty($form_data['zip'])) $address_parts[] = $form_data['zip'];
        
        // Use address as name if components exist, otherwise fall back to person's name
        if (!empty($address_parts)) {
            $column_values['name'] = implode(', ', $address_parts);
        } else if (isset($form_data['first_name']) && isset($form_data['last_name'])) {
            $column_values['name'] = $form_data['first_name'] . ' ' . $form_data['last_name'];
        }
        
        // Apply field mapping
        foreach ($field_mapping as $form_field => $monday_column) {
            if (!empty($form_data[$form_field]) && !empty($monday_column)) {
                // Handle different column types
                if ($form_field === 'email') {
                    $column_values[$monday_column] = array(
                        'email' => $form_data[$form_field],
                        'text' => $form_data[$form_field]
                    );
                } else if ($form_field === 'phone') {
                    // Just send the E164 format directly to Monday
                    $column_values[$monday_column] = $form_data['phone'] ?? '';
                } else if (strpos($form_field, 'consent_') === 0 || strpos($form_field, '_consent') !== false) {
                    // Handle consent checkbox fields
                    $column_values[$monday_column] = array(
                        'checked' => $form_data[$form_field] ? 'true' : 'false'
                    );
                } else if (is_array($form_data[$form_field])) {
                    // Handle dropdown/multi-select fields - Monday expects {labels: [...]}
                    $column_values[$monday_column] = array(
                        'labels' => $form_data[$form_field]
                    );
                } else {
                    $column_values[$monday_column] = $form_data[$form_field];
                }
            }
        }
        
        // Fallback for unmapped fields
        if (empty($field_mapping)) {
            if (isset($form_data['email'])) {
                $column_values['email'] = array(
                    'email' => $form_data['email'],
                    'text' => $form_data['email']
                );
            }
            
            if (isset($form_data['phone'])) {
                $column_values['phone'] = $form_data['phone'];
            }
            
            if (isset($form_data['message'])) {
                $column_values['text'] = $form_data['message'];
            }
        }
        
        
        // Create mutation
        $item_name = isset($column_values['name']) ? $column_values['name'] : 'New Lead';
        
        // Remove 'name' from column_values as it's used in item_name
        $mutation_column_values = $column_values;
        unset($mutation_column_values['name']);
        
        // Properly escape item name for GraphQL
        $escaped_item_name = str_replace('\\', '\\\\', $item_name);
        $escaped_item_name = str_replace('"', '\\"', $escaped_item_name);
        $escaped_item_name = str_replace("\n", '\\n', $escaped_item_name);
        $escaped_item_name = str_replace("\r", '\\r', $escaped_item_name);
        
        // Properly escape JSON for GraphQL
        $json_column_values = json_encode($mutation_column_values);
        $escaped_column_values = str_replace('\\', '\\\\', $json_column_values);
        $escaped_column_values = str_replace('"', '\\"', $escaped_column_values);
        $escaped_column_values = str_replace("\n", '\\n', $escaped_column_values);
        $escaped_column_values = str_replace("\r", '\\r', $escaped_column_values);
        
        $mutation = 'mutation {
            create_item (
                board_id: ' . $settings['board_id'] . ',
                item_name: "' . $escaped_item_name . '",
                column_values: "' . $escaped_column_values . '"
            ) {
                id
            }
        }';
        
        // Log the mutation for debugging
        $this->log('Creating Monday.com item', 'info', array(
            'board_id' => $settings['board_id'],
            'item_name' => $item_name,
            'column_values' => $mutation_column_values
        ));
        
        $response = $this->make_request($mutation);
        
        if (isset($response['data']['create_item']['id'])) {
            $item_id = $response['data']['create_item']['id'];
            
            // Handle file uploads sequentially with response validation
            if (!empty($file_data) && !empty($settings['file_column_id'])) {
                $this->log('Starting parallel file uploads for ' . count($file_data) . ' files', 'info', array('item_id' => $item_id));
                
                $parallel_results = $this->upload_files_parallel(
                    $item_id,
                    $settings['file_column_id'],
                    $file_data
                );
                
                $successful_uploads = 0;
                foreach ($parallel_results as $result) {
                    if ($result['success']) {
                        $successful_uploads++;
                    }
                }
                
                $this->log('Parallel file upload batch completed', 'info', array(
                    'item_id' => $item_id,
                    'successful_uploads' => $successful_uploads,
                    'total_files' => count($file_data),
                    'failed_uploads' => count($file_data) - $successful_uploads
                ));
            }
            
            return array(
                'success' => true,
                'item_id' => $item_id,
                'message' => __('Item created successfully in Monday.com', 'spai-contact-form')
            );
        }
        
        // Log the error response
        $this->log('Failed to create Monday.com item', 'error', array(
            'response' => $response,
            'mutation' => $mutation
        ));
        
        return array(
            'success' => false,
            'message' => __('Failed to create item in Monday.com', 'spai-contact-form'),
            'error' => isset($response['errors']) ? $response['errors'] : 'Unknown error'
        );
    }
    
    /**
     * Test connection
     */
    public function test_connection() {
        if (empty($this->api_key)) {
            return array(
                'success' => false,
                'message' => __('API key is required', 'spai-contact-form')
            );
        }
        
        $query = '{ me { name email } }';
        $response = $this->make_request($query);
        
        if (isset($response['data']['me'])) {
            return array(
                'success' => true,
                'message' => sprintf(__('Connected as %s', 'spai-contact-form'), $response['data']['me']['name'])
            );
        }
        
        return array(
            'success' => false,
            'message' => __('Failed to connect to Monday.com', 'spai-contact-form')
        );
    }
    
    /**
     * Get boards
     */
    public function get_boards() {
        $query = '{ boards(limit: 100) { id name } }';
        $response = $this->make_request($query);
        
        if (isset($response['data']['boards'])) {
            return array(
                'success' => true,
                'boards' => $response['data']['boards']
            );
        }
        
        return array(
            'success' => false,
            'message' => __('Failed to fetch boards', 'spai-contact-form')
        );
    }
    
    /**
     * Get board columns
     */
    public function get_board_columns($board_id) {
        $query = '{ boards(ids: [' . $board_id . ']) { columns { id title type } } }';
        $response = $this->make_request($query);
        
        if (isset($response['data']['boards'][0]['columns'])) {
            return array(
                'success' => true,
                'columns' => $response['data']['boards'][0]['columns']
            );
        }
        
        return array(
            'success' => false,
            'message' => __('Failed to fetch board columns', 'spai-contact-form')
        );
    }
    
    /**
     * Get board columns with detailed settings
     */
    public function get_board_columns_detailed($board_id) {
        $query = '{ boards(ids: [' . $board_id . ']) { columns { id title type settings_str } } }';
        $response = $this->make_request($query);
        
        if (isset($response['data']['boards'][0]['columns'])) {
            $columns = $response['data']['boards'][0]['columns'];
            
            // Parse settings for each column
            foreach ($columns as &$column) {
                if (!empty($column['settings_str'])) {
                    $column['settings'] = json_decode($column['settings_str'], true);
                }
                unset($column['settings_str']);
            }
            
            return array(
                'success' => true,
                'columns' => $columns
            );
        }
        
        return array(
            'success' => false,
            'message' => __('Failed to fetch board columns', 'spai-contact-form')
        );
    }
    
    /**
     * Make API request
     */
    private function make_request($query) {
        $args = array(
            'headers' => array(
                'Authorization' => $this->api_key,
                'Content-Type' => 'application/json'
            ),
            'body' => json_encode(array('query' => $query)),
            'timeout' => 30
        );
        
        $response = wp_remote_post($this->api_url, $args);
        
        if (is_wp_error($response)) {
            $this->log('API request failed', 'error', $response->get_error_message());
            return array('errors' => $response->get_error_message());
        }
        
        $body = wp_remote_retrieve_body($response);
        $data = json_decode($body, true);
        
        if (json_last_error() !== JSON_ERROR_NONE) {
            $this->log('Invalid JSON response', 'error', $body);
            return array('errors' => 'Invalid JSON response');
        }
        
        return $data;
    }
    
    /**
     * Upload file to Monday.com item
     */
    public function upload_file_to_item($item_id, $column_id, $file_path, $file_name, $file_index = 0) {
        if (empty($this->api_key) || empty($item_id) || empty($column_id) || !file_exists($file_path)) {
            return array(
                'success' => false,
                'message' => __('Missing required parameters or file not found', 'spai-contact-form')
            );
        }
        
        // Use Monday's file upload endpoint
        $upload_url = 'https://api.monday.com/v2/file';
        
        // Prepare the file for upload
        $file_data = file_get_contents($file_path);
        $file_type = mime_content_type($file_path);
        
        // Build multipart body manually
        $boundary = wp_generate_password(24, false);
        $eol = "\r\n";
        
        $body = '';
        
        // Add query field with unique variable name
        $file_var = 'file' . $file_index;
        $query = 'mutation ($' . $file_var . ': File!) { add_file_to_column(file: $' . $file_var . ', item_id: ' . $item_id . ', column_id: "' . $column_id . '") { id } }';
        $body .= '--' . $boundary . $eol;
        $body .= 'Content-Disposition: form-data; name="query"' . $eol . $eol;
        $body .= $query . $eol;
        
        // Add map field with unique field name
        $field_name = 'image' . $file_index;
        $map = '{"' . $field_name . '":"variables.' . $file_var . '"}';
        $body .= '--' . $boundary . $eol;
        $body .= 'Content-Disposition: form-data; name="map"' . $eol . $eol;
        $body .= $map . $eol;
        
        // Add file field with unique name
        $body .= '--' . $boundary . $eol;
        $body .= 'Content-Disposition: form-data; name="' . $field_name . '"; filename="' . $file_name . '"' . $eol;
        $body .= 'Content-Type: ' . $file_type . $eol . $eol;
        $body .= $file_data . $eol;
        
        // End boundary
        $body .= '--' . $boundary . '--' . $eol;
        
        // Make the request
        $args = array(
            'headers' => array(
                'Authorization' => $this->api_key,
                'Content-Type' => 'multipart/form-data; boundary=' . $boundary
            ),
            'body' => $body,
            'timeout' => 60,
            'data_format' => 'body'
        );
        
        $response = wp_remote_post($upload_url, $args);
        
        if (is_wp_error($response)) {
            $this->log('File upload failed', 'error', $response->get_error_message());
            return array(
                'success' => false,
                'message' => $response->get_error_message()
            );
        }
        
        $body = wp_remote_retrieve_body($response);
        $data = json_decode($body, true);
        
        if (isset($data['data']['add_file_to_column']['id'])) {
            return array(
                'success' => true,
                'asset_id' => $data['data']['add_file_to_column']['id']
            );
        }
        
        return array(
            'success' => false,
            'message' => isset($data['errors']) ? json_encode($data['errors']) : 'Unknown error',
            'response' => $data
        );
    }
    
    /**
     * Upload multiple files in parallel for speed
     */
    private function upload_files_parallel($item_id, $column_id, $file_data) {
        $curl_handles = array();
        $multi_handle = curl_multi_init();
        $results = array();
        
        // Create individual cURL handles for each file
        foreach ($file_data as $index => $file) {
            $ch = $this->create_file_upload_curl($item_id, $column_id, $file['path'], $file['name'], $index);
            $curl_handles[$index] = $ch;
            curl_multi_add_handle($multi_handle, $ch);
        }
        
        // Execute all uploads in parallel
        $running = null;
        do {
            curl_multi_exec($multi_handle, $running);
            curl_multi_select($multi_handle);
        } while ($running > 0);
        
        // Collect results
        foreach ($curl_handles as $index => $ch) {
            $response = curl_multi_getcontent($ch);
            $data = json_decode($response, true);
            
            if (isset($data['data']['add_file_to_column']['id'])) {
                $results[$index] = array(
                    'success' => true,
                    'asset_id' => $data['data']['add_file_to_column']['id'],
                    'file_name' => $file_data[$index]['name']
                );
                $this->log('Parallel file upload successful', 'info', array(
                    'file_name' => $file_data[$index]['name'],
                    'asset_id' => $data['data']['add_file_to_column']['id']
                ));
            } else {
                $results[$index] = array(
                    'success' => false,
                    'file_name' => $file_data[$index]['name'],
                    'error' => isset($data['errors']) ? json_encode($data['errors']) : 'Unknown error'
                );
                $this->log('Parallel file upload failed', 'error', array(
                    'file_name' => $file_data[$index]['name'],
                    'error' => isset($data['errors']) ? json_encode($data['errors']) : 'Unknown error'
                ));
            }
            
            curl_multi_remove_handle($multi_handle, $ch);
            curl_close($ch);
        }
        
        curl_multi_close($multi_handle);
        
        return $results;
    }
    
    /**
     * Create cURL handle for file upload
     */
    private function create_file_upload_curl($item_id, $column_id, $file_path, $file_name, $file_index) {
        $file_var = 'file' . $file_index;
        $query = 'mutation ($' . $file_var . ': File!) { add_file_to_column(file: $' . $file_var . ', item_id: ' . $item_id . ', column_id: "' . $column_id . '") { id } }';
        
        $field_name = 'image' . $file_index;
        $map = '{"' . $field_name . '":"variables.' . $file_var . '"}';
        
        $boundary = 'spai-boundary-' . uniqid();
        $eol = "\r\n";
        
        // Build multipart body
        $body = '';
        
        // Add query field
        $body .= '--' . $boundary . $eol;
        $body .= 'Content-Disposition: form-data; name="query"' . $eol . $eol;
        $body .= $query . $eol;
        
        // Add map field
        $body .= '--' . $boundary . $eol;
        $body .= 'Content-Disposition: form-data; name="map"' . $eol . $eol;
        $body .= $map . $eol;
        
        // Add file field
        $body .= '--' . $boundary . $eol;
        $body .= 'Content-Disposition: form-data; name="' . $field_name . '"; filename="' . $file_name . '"' . $eol;
        $body .= 'Content-Type: ' . mime_content_type($file_path) . $eol . $eol;
        $body .= file_get_contents($file_path) . $eol;
        
        // End boundary
        $body .= '--' . $boundary . '--' . $eol;
        
        $ch = curl_init();
        curl_setopt_array($ch, array(
            CURLOPT_URL => 'https://api.monday.com/v2/file',
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_POST => true,
            CURLOPT_POSTFIELDS => $body,
            CURLOPT_HTTPHEADER => array(
                'Authorization: ' . $this->api_key,
                'Content-Type: multipart/form-data; boundary=' . $boundary
            ),
            CURLOPT_TIMEOUT => 30
        ));
        
        return $ch;
    }
}
