//! Filter presets component
//!
//! Allows users to save and load filter configurations as named presets.
//! Presets are stored on the server and associated with the current user.

use crate::types::FilterPresetDto;

/// Generate HTML for the filter presets sidebar
///
/// # Arguments
///
/// * `presets` - List of available filter presets
/// * `auth_token` - Authentication token for API calls (optional)
///
/// # Returns
///
/// HTML string for the filter presets component
pub fn filter_presets_html(presets: &[FilterPresetDto], auth_token: Option<&str>) -> String {
    let presets_html = if presets.is_empty() {
        r#"<p class="text-sm text-gray-500 dark:text-gray-400 italic">No saved filters yet</p>"#
            .to_string()
    } else {
        presets
            .iter()
            .map(|preset| {
                format!(
                    r#"<button
    class="w-full text-left px-3 py-2 rounded-md hover:bg-blue-50 dark:hover:bg-blue-900 transition-colors filter-preset-btn"
    data-preset-id="{}"
    data-preset-filters='{}'>
    <div class="flex items-center justify-between">
        <span class="font-medium text-sm text-gray-900 dark:text-white">{}</span>
        <button
            class="text-red-600 hover:text-red-800 dark:text-red-400 dark:hover:text-red-300 delete-preset-btn"
            data-preset-id="{}"
            title="Delete preset"
            onclick="event.stopPropagation();">
            ✕
        </button>
    </div>
    <span class="text-xs text-gray-500 dark:text-gray-400">{}</span>
</button>"#,
                    preset.id,
                    html_escape(&preset.filters_json),
                    html_escape(&preset.name),
                    preset.id,
                    format_datetime(&preset.created_at)
                )
            })
            .collect::<Vec<_>>()
            .join("\n")
    };

    let auth_header = auth_token
        .map(|token| format!(r#"headers.set('Authorization', 'Bearer {}');"#, token))
        .unwrap_or_default();

    format!(
        r#"<div class="bg-white dark:bg-gray-800 rounded-lg shadow-md p-4 mb-6">
    <div class="flex items-center justify-between mb-4">
        <h3 class="text-lg font-bold text-gray-900 dark:text-white">Saved Filters</h3>
        <button
            id="save-preset-btn"
            class="px-3 py-1 bg-blue-600 hover:bg-blue-700 text-white text-sm rounded-md transition-colors"
            title="Save current filters">
            Save Current
        </button>
    </div>

    <div class="space-y-2" id="presets-container">
        {}
    </div>
</div>

<!-- Save Preset Modal -->
<div id="save-preset-modal" class="hidden fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50">
    <div class="bg-white dark:bg-gray-800 rounded-lg shadow-xl p-6 max-w-md w-full mx-4">
        <h3 class="text-xl font-bold text-gray-900 dark:text-white mb-4">Save Filter Preset</h3>

        <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">
            Preset Name
        </label>
        <input
            type="text"
            id="preset-name-input"
            class="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md shadow-sm dark:bg-gray-700 dark:text-white focus:outline-none focus:ring-blue-500 focus:border-blue-500"
            placeholder="e.g., High Priority Tasks"
        />

        <div class="mt-6 flex justify-end space-x-3">
            <button
                id="cancel-save-preset"
                class="px-4 py-2 border border-gray-300 dark:border-gray-600 rounded-md text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-700 transition-colors">
                Cancel
            </button>
            <button
                id="confirm-save-preset"
                class="px-4 py-2 bg-blue-600 hover:bg-blue-700 text-white rounded-md transition-colors">
                Save
            </button>
        </div>
    </div>
</div>

<script>
    (function() {{
        const modal = document.getElementById('save-preset-modal');
        const nameInput = document.getElementById('preset-name-input');

        // Show save modal
        document.getElementById('save-preset-btn')?.addEventListener('click', function() {{
            modal?.classList.remove('hidden');
            nameInput?.focus();
        }});

        // Cancel save
        document.getElementById('cancel-save-preset')?.addEventListener('click', function() {{
            modal?.classList.add('hidden');
            nameInput.value = '';
        }});

        // Confirm save
        document.getElementById('confirm-save-preset')?.addEventListener('click', async function() {{
            const name = nameInput?.value?.trim();
            if (!name) {{
                alert('Please enter a preset name');
                return;
            }}

            // Collect current filter state
            const filters = {{
                search: document.getElementById('search-input')?.value || '',
                status: document.querySelector('input[name="status"]:checked')?.value || 'all',
                priority: document.getElementById('priority-filter')?.value || 'all',
                taskType: document.getElementById('task-type-filter')?.value || 'all',
                sortBy: document.getElementById('sort-select')?.value || 'created_newest'
            }};

            try {{
                const headers = new Headers();
                headers.set('Content-Type', 'application/json');
                {}

                const response = await fetch('/api/filter-presets', {{
                    method: 'POST',
                    headers: headers,
                    body: JSON.stringify({{
                        name: name,
                        filters_json: JSON.stringify(filters)
                    }})
                }});

                if (response.ok) {{
                    // Reload page to show new preset
                    window.location.reload();
                }} else {{
                    const error = await response.json();
                    alert('Failed to save preset: ' + (error.error || 'Unknown error'));
                }}
            }} catch (err) {{
                console.error('Save preset error:', err);
                alert('Network error. Please try again.');
            }}
        }});

        // Apply preset
        document.querySelectorAll('.filter-preset-btn').forEach(btn => {{
            btn.addEventListener('click', function() {{
                const filtersJson = this.getAttribute('data-preset-filters');
                if (!filtersJson) return;

                try {{
                    const filters = JSON.parse(filtersJson);

                    // Apply filters to UI
                    if (filters.search !== undefined) {{
                        const searchInput = document.getElementById('search-input');
                        if (searchInput) searchInput.value = filters.search;
                    }}

                    if (filters.status) {{
                        const statusRadio = document.querySelector(`input[name="status"][value="${{filters.status}}"]`);
                        if (statusRadio) statusRadio.checked = true;
                    }}

                    if (filters.priority) {{
                        const prioritySelect = document.getElementById('priority-filter');
                        if (prioritySelect) prioritySelect.value = filters.priority;
                    }}

                    if (filters.taskType) {{
                        const taskTypeSelect = document.getElementById('task-type-filter');
                        if (taskTypeSelect) taskTypeSelect.value = filters.taskType;
                    }}

                    if (filters.sortBy) {{
                        const sortSelect = document.getElementById('sort-select');
                        if (sortSelect) sortSelect.value = filters.sortBy;
                    }}

                    // Trigger filter update event
                    window.dispatchEvent(new Event('filters-changed'));
                }} catch (err) {{
                    console.error('Failed to apply preset:', err);
                }}
            }});
        }});

        // Delete preset
        document.querySelectorAll('.delete-preset-btn').forEach(btn => {{
            btn.addEventListener('click', async function() {{
                if (!confirm('Delete this filter preset?')) {{
                    return;
                }}

                const presetId = this.getAttribute('data-preset-id');

                try {{
                    const headers = new Headers();
                    {}

                    const response = await fetch(`/api/filter-presets/${{presetId}}`, {{
                        method: 'DELETE',
                        headers: headers
                    }});

                    if (response.ok) {{
                        window.location.reload();
                    }} else {{
                        alert('Failed to delete preset');
                    }}
                }} catch (err) {{
                    console.error('Delete preset error:', err);
                    alert('Network error. Please try again.');
                }}
            }});
        }});
    }})();
</script>"#,
        presets_html, auth_header, auth_header
    )
}

/// Escape HTML special characters
fn html_escape(s: &str) -> String {
    s.replace('&', "&amp;")
        .replace('<', "&lt;")
        .replace('>', "&gt;")
        .replace('"', "&quot;")
        .replace('\'', "&#x27;")
}

/// Format datetime string for display
fn format_datetime(dt: &str) -> String {
    // Simple formatting - in production, use chrono for better parsing
    if let Some(date_part) = dt.split('T').next() {
        format!("Created {}", date_part)
    } else {
        dt.to_string()
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_html_escape() {
        assert_eq!(html_escape("Hello World"), "Hello World");
        assert_eq!(html_escape("<script>"), "&lt;script&gt;");
        assert_eq!(html_escape("A & B"), "A &amp; B");
        assert_eq!(html_escape(r#"Say "Hi""#), "Say &quot;Hi&quot;");
    }

    #[test]
    fn test_format_datetime() {
        assert_eq!(
            format_datetime("2023-11-14T10:30:00Z"),
            "Created 2023-11-14"
        );
        assert_eq!(format_datetime("invalid"), "Created invalid");
    }

    #[test]
    fn test_filter_presets_html_empty() {
        let html = filter_presets_html(&[], None);
        assert!(html.contains("No saved filters yet"));
        assert!(html.contains("Saved Filters"));
    }

    #[test]
    fn test_filter_presets_html_with_presets() {
        let presets = vec![FilterPresetDto {
            id: "preset-1".to_string(),
            user_id: "user-1".to_string(),
            name: "High Priority".to_string(),
            filters_json: r#"{"priority":"high"}"#.to_string(),
            created_at: "2023-11-14T10:00:00Z".to_string(),
        }];

        let html = filter_presets_html(&presets, Some("test-token"));
        assert!(html.contains("High Priority"));
        assert!(html.contains("preset-1"));
        // JSON should be HTML-escaped in data attributes
        assert!(html.contains(r#"data-preset-filters='{&quot;priority&quot;:&quot;high&quot;}'"#));
        assert!(html.contains("Authorization"));
    }

    #[test]
    fn test_filter_presets_html_without_auth() {
        let presets = vec![FilterPresetDto {
            id: "preset-1".to_string(),
            user_id: "user-1".to_string(),
            name: "Test".to_string(),
            filters_json: "{}".to_string(),
            created_at: "2023-11-14T10:00:00Z".to_string(),
        }];

        let html = filter_presets_html(&presets, None);
        assert!(!html.contains("Authorization"));
    }
}
