<?php
/**
 * Form Model
 *
 * @package Freelance_Studio
 */

class FS_Form {

    /**
     * Form status constants
     */
    const STATUS_DRAFT = 'draft';
    const STATUS_ACTIVE = 'active';
    const STATUS_ARCHIVED = 'archived';

    /**
     * Question type constants
     */
    const TYPE_SHORT_TEXT = 'short_text';
    const TYPE_LONG_TEXT = 'long_text';
    const TYPE_EMAIL = 'email';
    const TYPE_PHONE = 'phone';
    const TYPE_NUMBER = 'number';
    const TYPE_URL = 'url';
    const TYPE_DATE = 'date';
    const TYPE_TIME = 'time';
    const TYPE_SINGLE_CHOICE = 'single_choice';
    const TYPE_MULTIPLE_CHOICE = 'multiple_choice';
    const TYPE_DROPDOWN = 'dropdown';
    const TYPE_FILE_UPLOAD = 'file_upload';
    const TYPE_FILE_DOWNLOAD = 'file_download';
    const TYPE_HEADING = 'heading';
    const TYPE_PARAGRAPH = 'paragraph';
    const TYPE_DIVIDER = 'divider';
    const TYPE_YES_NO = 'yes_no';
    const TYPE_SCALE = 'scale';
    const TYPE_SIGNATURE = 'signature';

    /**
     * Create a new form
     *
     * @param array $data Form data
     * @return int|false Insert ID or false on failure
     */
    public static function create($data) {
        global $wpdb;
        
        $table = $wpdb->prefix . 'fs_forms';
        
        // Generate public token for sharing
        $public_token = wp_generate_password(32, false);
        
        $insert_data = array(
                'name' => sanitize_text_field($data['name']),
                'description' => isset($data['description']) ? sanitize_textarea_field($data['description']) : '',
                'project_id' => !empty($data['project_id']) ? intval($data['project_id']) : null,
                'client_id' => !empty($data['client_id']) ? intval($data['client_id']) : null,
                'status' => self::STATUS_ACTIVE, // Forms are always active
                'fields' => isset($data['fields']) ? wp_json_encode($data['fields']) : '[]',
                'settings' => isset($data['settings']) ? wp_json_encode($data['settings']) : '{}',
                'public_token' => $public_token,
                'created_at' => current_time('mysql'),
                'updated_at' => current_time('mysql'),
        );
        
        $result = $wpdb->insert(
            $table,
            $insert_data,
            array('%s', '%s', '%d', '%d', '%s', '%s', '%s', '%s', '%s', '%s')
        );
        
        if ($result === false) {
            error_log('FS_Form::create failed: ' . $wpdb->last_error);
            return false;
        }
        
        $new_id = $wpdb->insert_id;
        FS_DB_Helper::fix_null_fields($table, $new_id, array(
            'project_id' => $insert_data['project_id'],
            'client_id' => $insert_data['client_id'],
        ));
        
        return $new_id;
    }

    /**
     * Get a form by ID
     *
     * @param int $id Form ID
     * @return object|null
     */
    public static function get($id) {
        global $wpdb;
        
        $table = $wpdb->prefix . 'fs_forms';
        
        $form = $wpdb->get_row($wpdb->prepare(
            "SELECT * FROM {$table} WHERE id = %d",
            $id
        ));
        
        if ($form) {
            $form->fields = json_decode($form->fields ?? '', true) ?: array();
            $form->settings = json_decode($form->settings ?? '', true) ?: array();
        }
        
        return $form;
    }

    /**
     * Get a form by public token
     *
     * @param string $token Public token
     * @return object|null
     */
    public static function get_by_token($token) {
        global $wpdb;
        
        $table = $wpdb->prefix . 'fs_forms';
        
        $form = $wpdb->get_row($wpdb->prepare(
            "SELECT * FROM {$table} WHERE public_token = %s",
            $token
        ));
        
        if ($form) {
            $form->fields = json_decode($form->fields ?? '', true) ?: array();
            $form->settings = json_decode($form->settings ?? '', true) ?: array();
        }
        
        return $form;
    }

    /**
     * Get all forms
     *
     * @param array $args Query arguments
     * @return array
     */
    public static function get_all($args = array()) {
        global $wpdb;
        
        $defaults = array(
            'project_id' => null,
            'client_id' => null,
            'status' => null,
            'orderby' => 'created_at',
            'order' => 'DESC',
            'limit' => 100,
            'offset' => 0,
        );
        
        $args = wp_parse_args($args, $defaults);
        
        $table = $wpdb->prefix . 'fs_forms';
        $clients_table = $wpdb->prefix . 'fs_clients';
        $projects_table = $wpdb->prefix . 'fs_projects';
        
        $where = array('1=1');
        $values = array();
        
        if ($args['project_id'] !== null) {
            if ($args['project_id'] === 0) {
                $where[] = 'f.project_id IS NULL';
            } else {
                $where[] = 'f.project_id = %d';
                $values[] = $args['project_id'];
            }
        }
        
        if ($args['client_id']) {
            $where[] = 'f.client_id = %d';
            $values[] = $args['client_id'];
        }
        
        if ($args['status']) {
            if (is_array($args['status'])) {
                $placeholders = implode(', ', array_fill(0, count($args['status']), '%s'));
                $where[] = "f.status IN ($placeholders)";
                $values = array_merge($values, $args['status']);
            } else {
                $where[] = 'f.status = %s';
                $values[] = $args['status'];
            }
        }
        
        $where_clause = implode(' AND ', $where);
        $orderby = sanitize_sql_orderby($args['orderby'] . ' ' . $args['order']) ?: 'created_at DESC';
        
        $sql = "SELECT f.*, 
                       c.name as client_name,
                       c.company_name as client_company,
                       p.name as project_name,
                       (SELECT COUNT(*) FROM {$wpdb->prefix}fs_form_responses WHERE form_id = f.id) as response_count
                FROM {$table} f
                LEFT JOIN {$clients_table} c ON f.client_id = c.id
                LEFT JOIN {$projects_table} p ON f.project_id = p.id
                WHERE {$where_clause}
                ORDER BY f.{$orderby}
                LIMIT %d OFFSET %d";
        
        $values[] = $args['limit'];
        $values[] = $args['offset'];
        
        if (!empty($values)) {
            $sql = $wpdb->prepare($sql, $values); // phpcs:ignore PluginCheck.Security.DirectDB.UnescapedDBParameter, WordPress.DB.PreparedSQL.NotPrepared
        }
        
        $results = $wpdb->get_results($sql); // phpcs:ignore PluginCheck.Security.DirectDB.UnescapedDBParameter, WordPress.DB.PreparedSQL.NotPrepared
        
        foreach ($results as &$form) {
            $form->fields = json_decode($form->fields ?? '', true) ?: array();
            $form->settings = json_decode($form->settings ?? '', true) ?: array();
        }
        
        return $results;
    }

    /**
     * Get forms by project
     *
     * @param int $project_id Project ID
     * @return array
     */
    public static function get_by_project($project_id) {
        return self::get_all(array('project_id' => $project_id));
    }

    /**
     * Get forms by client
     *
     * @param int $client_id Client ID
     * @return array
     */
    public static function get_by_client($client_id) {
        return self::get_all(array('client_id' => $client_id));
    }

    /**
     * Get generic forms (not tied to a project)
     *
     * @return array
     */
    public static function get_generic() {
        return self::get_all(array('project_id' => 0));
    }

    /**
     * Update a form
     *
     * @param int   $id   Form ID
     * @param array $data Form data
     * @return int|false
     */
    public static function update($id, $data) {
        global $wpdb;
        
        $table = $wpdb->prefix . 'fs_forms';
        
        $update_data = array(
            'updated_at' => current_time('mysql'),
        );
        
        if (isset($data['name'])) {
            $update_data['name'] = sanitize_text_field($data['name']);
        }
        
        if (isset($data['description'])) {
            $update_data['description'] = sanitize_textarea_field($data['description']);
        }
        
        if (array_key_exists('project_id', $data)) {
            $update_data['project_id'] = !empty($data['project_id']) ? intval($data['project_id']) : null;
        }
        
        if (array_key_exists('client_id', $data)) {
            $update_data['client_id'] = !empty($data['client_id']) ? intval($data['client_id']) : null;
        }
        
        if (isset($data['status'])) {
            $update_data['status'] = sanitize_text_field($data['status']);
        }
        
        if (isset($data['fields'])) {
            $update_data['fields'] = wp_json_encode($data['fields']);
        }
        
        if (isset($data['settings'])) {
            $update_data['settings'] = wp_json_encode($data['settings']);
        }
        
        // Track nullable foreign keys
        $nullable_fks = array();
        $nullable_fk_fields = array('project_id', 'client_id');
        foreach ($nullable_fk_fields as $fk_field) {
            if (array_key_exists($fk_field, $update_data) && $update_data[$fk_field] === null) {
                $nullable_fks[$fk_field] = null;
                unset($update_data[$fk_field]);
            }
        }
        
        $result = $wpdb->update(
            $table,
            $update_data,
            array('id' => $id),
            null,
            array('%d')
        );
        
        if (!empty($nullable_fks)) {
            FS_DB_Helper::fix_null_fields($table, $id, $nullable_fks);
        }
        
        return $result;
    }

    /**
     * Update form status
     *
     * @param int    $id     Form ID
     * @param string $status New status
     * @return int|false
     */
    public static function update_status($id, $status) {
        global $wpdb;
        
        $table = $wpdb->prefix . 'fs_forms';
        
        return $wpdb->update(
            $table,
            array(
                'status' => sanitize_text_field($status),
                'updated_at' => current_time('mysql'),
            ),
            array('id' => $id),
            array('%s', '%s'),
            array('%d')
        );
    }

    /**
     * Delete a form
     *
     * @param int $id Form ID
     * @return int|false
     */
    public static function delete($id) {
        global $wpdb;
        
        // Delete all responses first
        $responses_table = $wpdb->prefix . 'fs_form_responses';
        $wpdb->delete($responses_table, array('form_id' => $id), array('%d'));
        
        // Delete the form
        $table = $wpdb->prefix . 'fs_forms';
        return $wpdb->delete($table, array('id' => $id), array('%d'));
    }

    /**
     * Duplicate a form
     *
     * @param int $id Form ID to duplicate
     * @return int|false New form ID or false
     */
    public static function duplicate($id) {
        $original = self::get($id);
        
        if (!$original) {
            return false;
        }
        
        $data = array(
            'name' => $original->name . ' (Copy)',
            'description' => $original->description,
            'project_id' => $original->project_id,
            'client_id' => $original->client_id,
            'status' => self::STATUS_DRAFT,
            'fields' => $original->fields,
            'settings' => $original->settings,
        );
        
        return self::create($data);
    }

    /**
     * Get statuses
     *
     * @return array
     */
    public static function get_statuses() {
        return array(
            self::STATUS_DRAFT => __('Draft', 'freelance-studio'),
            self::STATUS_ACTIVE => __('Active', 'freelance-studio'),
            self::STATUS_ARCHIVED => __('Archived', 'freelance-studio'),
        );
    }

    /**
     * Get question types
     *
     * @return array
     */
    public static function get_question_types() {
        return array(
            'input' => array(
                'label' => __('Input Fields', 'freelance-studio'),
                'types' => array(
                    self::TYPE_SHORT_TEXT => array(
                        'label' => __('Short Text', 'freelance-studio'),
                        'icon' => 'dashicons-editor-textcolor',
                        'description' => __('Single line text input', 'freelance-studio'),
                    ),
                    self::TYPE_LONG_TEXT => array(
                        'label' => __('Long Text', 'freelance-studio'),
                        'icon' => 'dashicons-editor-paragraph',
                        'description' => __('Multi-line text area', 'freelance-studio'),
                    ),
                    self::TYPE_EMAIL => array(
                        'label' => __('Email', 'freelance-studio'),
                        'icon' => 'dashicons-email',
                        'description' => __('Email address with validation', 'freelance-studio'),
                    ),
                    self::TYPE_PHONE => array(
                        'label' => __('Phone', 'freelance-studio'),
                        'icon' => 'dashicons-phone',
                        'description' => __('Phone number input', 'freelance-studio'),
                    ),
                    self::TYPE_NUMBER => array(
                        'label' => __('Number', 'freelance-studio'),
                        'icon' => 'dashicons-editor-ol',
                        'description' => __('Numeric input', 'freelance-studio'),
                    ),
                    self::TYPE_URL => array(
                        'label' => __('Website URL', 'freelance-studio'),
                        'icon' => 'dashicons-admin-links',
                        'description' => __('URL/website address', 'freelance-studio'),
                    ),
                ),
            ),
            'date_time' => array(
                'label' => __('Date & Time', 'freelance-studio'),
                'types' => array(
                    self::TYPE_DATE => array(
                        'label' => __('Date', 'freelance-studio'),
                        'icon' => 'dashicons-calendar-alt',
                        'description' => __('Date picker', 'freelance-studio'),
                    ),
                    self::TYPE_TIME => array(
                        'label' => __('Time', 'freelance-studio'),
                        'icon' => 'dashicons-clock',
                        'description' => __('Time picker', 'freelance-studio'),
                    ),
                ),
            ),
            'choice' => array(
                'label' => __('Choice Fields', 'freelance-studio'),
                'types' => array(
                    self::TYPE_SINGLE_CHOICE => array(
                        'label' => __('Single Choice', 'freelance-studio'),
                        'icon' => 'dashicons-marker',
                        'description' => __('Radio buttons - select one', 'freelance-studio'),
                    ),
                    self::TYPE_MULTIPLE_CHOICE => array(
                        'label' => __('Multiple Choice', 'freelance-studio'),
                        'icon' => 'dashicons-yes-alt',
                        'description' => __('Checkboxes - select multiple', 'freelance-studio'),
                    ),
                    self::TYPE_DROPDOWN => array(
                        'label' => __('Dropdown', 'freelance-studio'),
                        'icon' => 'dashicons-arrow-down-alt2',
                        'description' => __('Dropdown select', 'freelance-studio'),
                    ),
                    self::TYPE_YES_NO => array(
                        'label' => __('Yes/No', 'freelance-studio'),
                        'icon' => 'dashicons-yes',
                        'description' => __('Simple yes or no toggle', 'freelance-studio'),
                    ),
                    self::TYPE_SCALE => array(
                        'label' => __('Scale/Rating', 'freelance-studio'),
                        'icon' => 'dashicons-chart-bar',
                        'description' => __('Numeric scale (e.g., 1-10)', 'freelance-studio'),
                    ),
                ),
            ),
            'files' => array(
                'label' => __('Files', 'freelance-studio'),
                'types' => array(
                    self::TYPE_FILE_UPLOAD => array(
                        'label' => __('File Upload', 'freelance-studio'),
                        'icon' => 'dashicons-upload',
                        'description' => __('Allow file uploads', 'freelance-studio'),
                    ),
                    self::TYPE_FILE_DOWNLOAD => array(
                        'label' => __('File Download', 'freelance-studio'),
                        'icon' => 'dashicons-download',
                        'description' => __('Provide files for download', 'freelance-studio'),
                    ),
                ),
            ),
            'content' => array(
                'label' => __('Content Elements', 'freelance-studio'),
                'types' => array(
                    self::TYPE_HEADING => array(
                        'label' => __('Heading', 'freelance-studio'),
                        'icon' => 'dashicons-heading',
                        'description' => __('Section heading', 'freelance-studio'),
                    ),
                    self::TYPE_PARAGRAPH => array(
                        'label' => __('Paragraph', 'freelance-studio'),
                        'icon' => 'dashicons-text',
                        'description' => __('Instructions or description', 'freelance-studio'),
                    ),
                    self::TYPE_DIVIDER => array(
                        'label' => __('Divider', 'freelance-studio'),
                        'icon' => 'dashicons-minus',
                        'description' => __('Visual separator', 'freelance-studio'),
                    ),
                ),
            ),
            'special' => array(
                'label' => __('Special', 'freelance-studio'),
                'types' => array(
                    self::TYPE_SIGNATURE => array(
                        'label' => __('Signature', 'freelance-studio'),
                        'icon' => 'dashicons-edit',
                        'description' => __('Signature capture pad', 'freelance-studio'),
                    ),
                ),
            ),
        );
    }

    /**
     * Get flat list of question types
     *
     * @return array
     */
    public static function get_question_types_flat() {
        $grouped = self::get_question_types();
        $flat = array();
        
        foreach ($grouped as $group) {
            foreach ($group['types'] as $type => $info) {
                $flat[$type] = $info;
            }
        }
        
        return $flat;
    }

    /**
     * Count forms
     *
     * @param array $args Query arguments
     * @return int
     */
    public static function count($args = array()) {
        global $wpdb;
        
        $table = $wpdb->prefix . 'fs_forms';
        
        $where = array('1=1');
        $values = array();
        
        if (!empty($args['project_id'])) {
            $where[] = 'project_id = %d';
            $values[] = $args['project_id'];
        }
        
        if (!empty($args['client_id'])) {
            $where[] = 'client_id = %d';
            $values[] = $args['client_id'];
        }
        
        if (!empty($args['status'])) {
            $where[] = 'status = %s';
            $values[] = $args['status'];
        }
        
        $where_clause = implode(' AND ', $where);
        
        $sql = "SELECT COUNT(*) FROM {$table} WHERE {$where_clause}";
        
        if (!empty($values)) {
            $sql = $wpdb->prepare($sql, $values); // phpcs:ignore PluginCheck.Security.DirectDB.UnescapedDBParameter, WordPress.DB.PreparedSQL.NotPrepared
        }
        
        return (int) $wpdb->get_var($sql); // phpcs:ignore PluginCheck.Security.DirectDB.UnescapedDBParameter, WordPress.DB.PreparedSQL.NotPrepared
    }

    /**
     * Get public URL for form
     *
     * @param object $form Form object
     * @return string
     */
    public static function get_public_url($form) {
        return add_query_arg('fs_form', $form->public_token, home_url('/'));
    }

    /**
     * Check if form accepts responses
     *
     * @param object $form Form object
     * @return bool
     */
    public static function accepts_responses($form) {
        // Forms are always active and accepting responses
        return true;
    }
}
