<?php
/**
 * VTemplateBuilder - Drag and Drop Template Builder System
 *
 * This class handles the creation, management, and rendering of user-created templates
 * Integrates with EasyStream's existing Smarty template system
 *
 * @package    EasyStream
 * @subpackage TemplateBuilder
 * @author     EasyStream
 * @version    1.0
 */

class VTemplateBuilder
{
    private $db;
    private $smarty;
    private $user_id;

    /**
     * Constructor
     */
    public function __construct()
    {
        global $db, $smarty, $class_database;

        $this->db = $db ?? $class_database;
        $this->smarty = $smarty;
        $this->user_id = isset($_SESSION['USER_ID']) ? (int)$_SESSION['USER_ID'] : 0;
    }

    /**
     * Create a new template
     *
     * @param array $data Template data
     * @return array Result with success status and template_id
     */
    public function createTemplate($data)
    {
        // Validate input
        if (empty($data['template_name'])) {
            return ['success' => false, 'error' => 'Template name is required'];
        }

        if ($this->user_id === 0) {
            return ['success' => false, 'error' => 'User not authenticated'];
        }

        // Generate slug
        $slug = $this->generateSlug($data['template_name'], $this->user_id);

        // Default structure if not provided
        $default_structure = json_encode([
            'sections' => [],
            'layout_type' => 'flex',
            'max_width' => 1200
        ]);

        // Prepare data
        $insert_data = [
            'user_id' => $this->user_id,
            'template_name' => VDatabase::sanitizeInput($data['template_name']),
            'template_slug' => $slug,
            'template_type' => $data['template_type'] ?? 'custom_page',
            'template_structure' => $data['template_structure'] ?? $default_structure,
            'template_settings' => $data['template_settings'] ?? json_encode([]),
            'custom_css' => $data['custom_css'] ?? '',
            'custom_js' => $data['custom_js'] ?? '',
            'is_active' => isset($data['is_active']) ? (int)$data['is_active'] : 0
        ];

        // Insert into database
        $sql = "INSERT INTO `db_templatebuilder_templates`
                SET " . VDatabase::build_insert_update($insert_data);

        $result = $this->db->execute($sql);

        if ($result) {
            $template_id = $this->db->insert_id();

            // Create initial version
            $this->createVersion($template_id, $insert_data, 'Initial version');

            VLogger::log('INFO', "Template created: ID {$template_id}, Name: {$data['template_name']}",
                        ['user_id' => $this->user_id]);

            return [
                'success' => true,
                'template_id' => $template_id,
                'slug' => $slug
            ];
        }

        return ['success' => false, 'error' => 'Failed to create template'];
    }

    /**
     * Update an existing template
     *
     * @param int $template_id Template ID
     * @param array $data Update data
     * @param string $change_note Optional change note for version history
     * @return array Result with success status
     */
    public function updateTemplate($template_id, $data, $change_note = null)
    {
        $template_id = (int)$template_id;

        // Verify ownership
        if (!$this->verifyOwnership($template_id)) {
            return ['success' => false, 'error' => 'Unauthorized'];
        }

        // Prepare update data
        $update_data = [];

        $allowed_fields = [
            'template_name', 'template_type', 'template_structure',
            'template_settings', 'custom_css', 'custom_js', 'is_active', 'is_default'
        ];

        foreach ($allowed_fields as $field) {
            if (isset($data[$field])) {
                if ($field === 'template_name') {
                    $update_data[$field] = VDatabase::sanitizeInput($data[$field]);
                } else {
                    $update_data[$field] = $data[$field];
                }
            }
        }

        if (empty($update_data)) {
            return ['success' => false, 'error' => 'No valid fields to update'];
        }

        // Update database
        $sql = "UPDATE `db_templatebuilder_templates`
                SET " . VDatabase::build_insert_update($update_data) . "
                WHERE `template_id` = '{$template_id}'";

        $result = $this->db->execute($sql);

        if ($result) {
            // Create version history entry
            $this->createVersion($template_id, $update_data, $change_note);

            VLogger::log('INFO', "Template updated: ID {$template_id}",
                        ['user_id' => $this->user_id, 'changes' => array_keys($update_data)]);

            return ['success' => true];
        }

        return ['success' => false, 'error' => 'Failed to update template'];
    }

    /**
     * Delete a template
     *
     * @param int $template_id Template ID
     * @return array Result with success status
     */
    public function deleteTemplate($template_id)
    {
        $template_id = (int)$template_id;

        // Verify ownership
        if (!$this->verifyOwnership($template_id)) {
            return ['success' => false, 'error' => 'Unauthorized'];
        }

        $sql = "DELETE FROM `db_templatebuilder_templates`
                WHERE `template_id` = '{$template_id}'";

        $result = $this->db->execute($sql);

        if ($result) {
            VLogger::log('INFO', "Template deleted: ID {$template_id}",
                        ['user_id' => $this->user_id]);

            return ['success' => true];
        }

        return ['success' => false, 'error' => 'Failed to delete template'];
    }

    /**
     * Get template by ID
     *
     * @param int $template_id Template ID
     * @param bool $check_ownership Whether to verify ownership
     * @return array|null Template data or null if not found
     */
    public function getTemplate($template_id, $check_ownership = true)
    {
        $template_id = (int)$template_id;

        $sql = "SELECT * FROM `db_templatebuilder_templates`
                WHERE `template_id` = '{$template_id}'";

        if ($check_ownership && $this->user_id > 0) {
            $sql .= " AND `user_id` = '{$this->user_id}'";
        }

        $result = $this->db->execute($sql);

        if ($result && $result->recordcount() > 0) {
            $template = $result->fields;

            // Decode JSON fields
            $template['template_structure'] = json_decode($template['template_structure'], true);
            $template['template_settings'] = json_decode($template['template_settings'], true);

            return $template;
        }

        return null;
    }

    /**
     * Get template by slug
     *
     * @param string $slug Template slug
     * @return array|null Template data or null if not found
     */
    public function getTemplateBySlug($slug)
    {
        $slug = VDatabase::sanitizeInput($slug);

        $sql = "SELECT * FROM `db_templatebuilder_templates`
                WHERE `template_slug` = '{$slug}'
                AND `is_active` = 1
                LIMIT 1";

        $result = $this->db->execute($sql);

        if ($result && $result->recordcount() > 0) {
            $template = $result->fields;

            // Decode JSON fields
            $template['template_structure'] = json_decode($template['template_structure'], true);
            $template['template_settings'] = json_decode($template['template_settings'], true);

            return $template;
        }

        return null;
    }

    /**
     * Get all templates for current user
     *
     * @param array $filters Optional filters
     * @return array Array of templates
     */
    public function getUserTemplates($filters = [])
    {
        if ($this->user_id === 0) {
            return [];
        }

        $sql = "SELECT * FROM `db_templatebuilder_templates`
                WHERE `user_id` = '{$this->user_id}'";

        // Apply filters
        if (!empty($filters['template_type'])) {
            $type = VDatabase::sanitizeInput($filters['template_type']);
            $sql .= " AND `template_type` = '{$type}'";
        }

        if (isset($filters['is_active'])) {
            $active = (int)$filters['is_active'];
            $sql .= " AND `is_active` = '{$active}'";
        }

        $sql .= " ORDER BY `updated_at` DESC";

        if (!empty($filters['limit'])) {
            $limit = (int)$filters['limit'];
            $sql .= " LIMIT {$limit}";
        }

        $result = $this->db->execute($sql);
        $templates = [];

        if ($result) {
            foreach ($result->getRows() as $row) {
                // Don't decode JSON for listing (performance)
                $templates[] = $row;
            }
        }

        return $templates;
    }

    /**
     * Render a template
     *
     * @param int|string $template_identifier Template ID or slug
     * @param array $data Data to pass to template
     * @return string Rendered HTML
     */
    public function renderTemplate($template_identifier, $data = [])
    {
        // Get template
        if (is_numeric($template_identifier)) {
            $template = $this->getTemplate($template_identifier, false);
        } else {
            $template = $this->getTemplateBySlug($template_identifier);
        }

        if (!$template) {
            return '<!-- Template not found -->';
        }

        // Increment views
        $this->incrementViews($template['template_id']);

        // Build HTML from structure
        $html = $this->buildHtmlFromStructure($template['template_structure'], $data);

        // Wrap with custom CSS if present
        if (!empty($template['custom_css'])) {
            $html = "<style>\n{$template['custom_css']}\n</style>\n" . $html;
        }

        // Add custom JS if present (sanitized)
        if (!empty($template['custom_js'])) {
            $html .= "\n<script>\n{$template['custom_js']}\n</script>";
        }

        return $html;
    }

    /**
     * Build HTML from template structure
     *
     * @param array $structure Template structure
     * @param array $data Data to pass to components
     * @return string Generated HTML
     */
    private function buildHtmlFromStructure($structure, $data = [])
    {
        if (empty($structure['sections'])) {
            return '';
        }

        $html = '';
        $max_width = $structure['max_width'] ?? 1200;
        $layout_type = $structure['layout_type'] ?? 'flex';

        // Container wrapper
        $html .= "<div class=\"template-builder-container\" data-layout=\"{$layout_type}\" style=\"max-width: {$max_width}px; margin: 0 auto;\">\n";

        foreach ($structure['sections'] as $section) {
            $html .= $this->buildSection($section, $data);
        }

        $html .= "</div>\n";

        return $html;
    }

    /**
     * Build a section
     *
     * @param array $section Section data
     * @param array $data Global data
     * @return string Section HTML
     */
    private function buildSection($section, $data)
    {
        $section_id = $section['id'] ?? 'section-' . uniqid();
        $section_class = $section['class'] ?? '';
        $columns = $section['columns'] ?? 1;

        $html = "<div class=\"tb-section {$section_class}\" id=\"{$section_id}\" data-columns=\"{$columns}\">\n";

        // Apply section styles if present
        if (!empty($section['styles'])) {
            $style_str = $this->buildStyleString($section['styles']);
            $html = str_replace('<div class="tb-section', "<div style=\"{$style_str}\" class=\"tb-section", $html);
        }

        // Build columns
        if (!empty($section['blocks'])) {
            $html .= "<div class=\"tb-columns\" style=\"display: grid; grid-template-columns: repeat({$columns}, 1fr); gap: " . ($section['gap'] ?? 20) . "px;\">\n";

            foreach ($section['blocks'] as $block) {
                $html .= $this->buildBlock($block, $data);
            }

            $html .= "</div>\n";
        }

        $html .= "</div>\n";

        return $html;
    }

    /**
     * Build a block (component)
     *
     * @param array $block Block data
     * @param array $data Global data
     * @return string Block HTML
     */
    private function buildBlock($block, $data)
    {
        $block_id = $block['id'] ?? 'block-' . uniqid();
        $component_slug = $block['component'] ?? null;

        if (!$component_slug) {
            return '';
        }

        // Get component definition
        $component = $this->getComponent($component_slug);

        if (!$component) {
            return "<!-- Component '{$component_slug}' not found -->";
        }

        // Merge block settings with component defaults
        $settings = array_merge(
            json_decode($component['component_settings_schema'], true) ?? [],
            $block['settings'] ?? []
        );

        // Build HTML from component template
        $html = $component['component_html'];

        // Replace placeholders with settings values
        $html = $this->replacePlaceholders($html, $settings, $data);

        // Apply component CSS if present
        if (!empty($component['component_css'])) {
            $css = $this->replacePlaceholders($component['component_css'], $settings, $data);
            $html = "<style>\n{$css}\n</style>\n" . $html;
        }

        // Wrap in block container
        $block_html = "<div class=\"tb-block\" id=\"{$block_id}\" data-component=\"{$component_slug}\">\n";
        $block_html .= $html;
        $block_html .= "</div>\n";

        return $block_html;
    }

    /**
     * Replace placeholders in template string
     *
     * @param string $template Template string
     * @param array $settings Settings values
     * @param array $data Global data
     * @return string Processed string
     */
    private function replacePlaceholders($template, $settings, $data)
    {
        // Replace {{variable}} with actual values
        $template = preg_replace_callback('/\{\{(\w+)\}\}/', function($matches) use ($settings, $data) {
            $key = $matches[1];

            // Check settings first
            if (isset($settings[$key])) {
                $value = $settings[$key];
                // Get default value if it's an array
                if (is_array($value) && isset($value['default'])) {
                    return $value['default'];
                }
                return $value;
            }

            // Check global data
            if (isset($data[$key])) {
                return $data[$key];
            }

            return $matches[0]; // Return original if not found
        }, $template);

        return $template;
    }

    /**
     * Get component by slug
     *
     * @param string $slug Component slug
     * @return array|null Component data
     */
    private function getComponent($slug)
    {
        $slug = VDatabase::sanitizeInput($slug);

        $sql = "SELECT * FROM `db_templatebuilder_components`
                WHERE `component_slug` = '{$slug}'
                LIMIT 1";

        $result = $this->db->execute($sql);

        if ($result && $result->recordcount() > 0) {
            return $result->fields;
        }

        return null;
    }

    /**
     * Get all available components
     *
     * @param string $category Optional category filter
     * @return array Array of components
     */
    public function getComponents($category = null)
    {
        $sql = "SELECT * FROM `db_templatebuilder_components`";

        if ($category) {
            $category = VDatabase::sanitizeInput($category);
            $sql .= " WHERE `component_category` = '{$category}'";
        }

        $sql .= " ORDER BY `component_category`, `component_name`";

        $result = $this->db->execute($sql);
        $components = [];

        if ($result) {
            foreach ($result->getRows() as $row) {
                $row['component_settings_schema'] = json_decode($row['component_settings_schema'], true);
                $components[] = $row;
            }
        }

        return $components;
    }

    /**
     * Create a version history entry
     *
     * @param int $template_id Template ID
     * @param array $data Template data
     * @param string $change_note Optional change note
     * @return bool Success status
     */
    private function createVersion($template_id, $data, $change_note = null)
    {
        // Get current version number
        $sql = "SELECT MAX(`version_number`) as max_version
                FROM `db_templatebuilder_versions`
                WHERE `template_id` = '{$template_id}'";

        $result = $this->db->execute($sql);
        $max_version = 0;

        if ($result && $result->recordcount() > 0) {
            $row = $result->fields;
            $max_version = (int)$row['max_version'];
        }

        $new_version = $max_version + 1;

        $version_data = [
            'template_id' => $template_id,
            'version_number' => $new_version,
            'template_structure' => $data['template_structure'] ?? '{}',
            'template_settings' => $data['template_settings'] ?? '{}',
            'custom_css' => $data['custom_css'] ?? '',
            'custom_js' => $data['custom_js'] ?? '',
            'change_note' => $change_note ? VDatabase::sanitizeInput($change_note) : null
        ];

        $sql = "INSERT INTO `db_templatebuilder_versions`
                SET " . VDatabase::build_insert_update($version_data);

        return $this->db->execute($sql);
    }

    /**
     * Get user preferences
     *
     * @param int $user_id Optional user ID (defaults to current user)
     * @return array User preferences
     */
    public function getUserPreferences($user_id = null)
    {
        $user_id = $user_id ?? $this->user_id;

        if ($user_id === 0) {
            return $this->getDefaultPreferences();
        }

        $sql = "SELECT * FROM `db_templatebuilder_user_prefs`
                WHERE `user_id` = '{$user_id}'
                LIMIT 1";

        $result = $this->db->execute($sql);

        if ($result && $result->recordcount() > 0) {
            $prefs = $result->fields;
            $prefs['preferences'] = json_decode($prefs['preferences'], true);
            return $prefs;
        }

        return $this->getDefaultPreferences();
    }

    /**
     * Update user preferences
     *
     * @param array $preferences Preferences to update
     * @return bool Success status
     */
    public function updateUserPreferences($preferences)
    {
        if ($this->user_id === 0) {
            return false;
        }

        // Check if preferences exist
        $existing = $this->getUserPreferences();

        $allowed_fields = [
            'active_template_homepage', 'active_template_channel',
            'active_template_browse', 'builder_mode', 'auto_save',
            'show_grid', 'preferences'
        ];

        $update_data = [];
        foreach ($allowed_fields as $field) {
            if (isset($preferences[$field])) {
                if ($field === 'preferences') {
                    $update_data[$field] = json_encode($preferences[$field]);
                } else {
                    $update_data[$field] = $preferences[$field];
                }
            }
        }

        if (empty($update_data)) {
            return false;
        }

        if (!empty($existing['pref_id'])) {
            // Update existing
            $sql = "UPDATE `db_templatebuilder_user_prefs`
                    SET " . VDatabase::build_insert_update($update_data) . "
                    WHERE `user_id` = '{$this->user_id}'";
        } else {
            // Insert new
            $update_data['user_id'] = $this->user_id;
            $sql = "INSERT INTO `db_templatebuilder_user_prefs`
                    SET " . VDatabase::build_insert_update($update_data);
        }

        return $this->db->execute($sql);
    }

    /**
     * Get default preferences
     *
     * @return array Default preferences
     */
    private function getDefaultPreferences()
    {
        return [
            'builder_mode' => 'simple',
            'auto_save' => 1,
            'show_grid' => 1,
            'preferences' => []
        ];
    }

    /**
     * Verify template ownership
     *
     * @param int $template_id Template ID
     * @return bool True if user owns template
     */
    private function verifyOwnership($template_id)
    {
        if ($this->user_id === 0) {
            return false;
        }

        $sql = "SELECT `user_id` FROM `db_templatebuilder_templates`
                WHERE `template_id` = '{$template_id}'
                LIMIT 1";

        $result = $this->db->execute($sql);

        if ($result && $result->recordcount() > 0) {
            $row = $result->fields;
            return ((int)$row['user_id'] === $this->user_id);
        }

        return false;
    }

    /**
     * Generate unique slug
     *
     * @param string $name Template name
     * @param int $user_id User ID
     * @return string Unique slug
     */
    private function generateSlug($name, $user_id)
    {
        // Basic slug generation
        $slug = strtolower(trim(preg_replace('/[^A-Za-z0-9-]+/', '-', $name)));
        $slug = $user_id . '-' . $slug;

        // Check uniqueness
        $original_slug = $slug;
        $counter = 1;

        while ($this->slugExists($slug)) {
            $slug = $original_slug . '-' . $counter;
            $counter++;
        }

        return $slug;
    }

    /**
     * Check if slug exists
     *
     * @param string $slug Slug to check
     * @return bool True if exists
     */
    private function slugExists($slug)
    {
        $slug = VDatabase::sanitizeInput($slug);

        $sql = "SELECT COUNT(*) as count FROM `db_templatebuilder_templates`
                WHERE `template_slug` = '{$slug}'";

        $result = $this->db->execute($sql);

        if ($result) {
            $row = $result->fields;
            return ((int)$row['count'] > 0);
        }

        return false;
    }

    /**
     * Increment template views
     *
     * @param int $template_id Template ID
     * @return bool Success status
     */
    private function incrementViews($template_id)
    {
        $sql = "UPDATE `db_templatebuilder_templates`
                SET `views` = `views` + 1
                WHERE `template_id` = '{$template_id}'";

        return $this->db->execute($sql);
    }

    /**
     * Build CSS style string from array
     *
     * @param array $styles Style array
     * @return string CSS string
     */
    private function buildStyleString($styles)
    {
        $style_parts = [];

        foreach ($styles as $property => $value) {
            $property = str_replace('_', '-', $property);
            $style_parts[] = "{$property}: {$value}";
        }

        return implode('; ', $style_parts);
    }

    /**
     * Duplicate a template
     *
     * @param int $template_id Template ID to duplicate
     * @param string $new_name Optional new name
     * @return array Result with success status and new template_id
     */
    public function duplicateTemplate($template_id, $new_name = null)
    {
        $template = $this->getTemplate($template_id, true);

        if (!$template) {
            return ['success' => false, 'error' => 'Template not found'];
        }

        // Prepare new template data
        $new_template = [
            'template_name' => $new_name ?? ($template['template_name'] . ' (Copy)'),
            'template_type' => $template['template_type'],
            'template_structure' => json_encode($template['template_structure']),
            'template_settings' => json_encode($template['template_settings']),
            'custom_css' => $template['custom_css'],
            'custom_js' => $template['custom_js'],
            'is_active' => 0
        ];

        return $this->createTemplate($new_template);
    }
}
