//! Task comments component
//!
//! Provides commenting functionality for tasks with real-time updates.
//! Supports adding, viewing, and deleting comments.

use crate::types::TaskCommentDto;

/// Generate HTML for the task comments component
///
/// # Arguments
///
/// * `task_id` - ID of the task to show comments for
/// * `comments` - Existing comments for the task
/// * `auth_token` - Authentication token for API calls (optional)
/// * `current_user_id` - Current user ID for permission checks (optional)
///
/// # Returns
///
/// HTML string for the task comments component
pub fn task_comments_html(
    task_id: &str,
    comments: &[TaskCommentDto],
    auth_token: Option<&str>,
    current_user_id: Option<&str>,
) -> String {
    let comments_html = if comments.is_empty() {
        r#"<p class="text-sm text-gray-500 dark:text-gray-400 italic text-center py-8">No comments yet. Be the first to comment!</p>"#.to_string()
    } else {
        comments
            .iter()
            .map(|comment| {
                let can_delete = current_user_id
                    .map(|uid| uid == comment.user_id)
                    .unwrap_or(false);

                let delete_button = if can_delete {
                    format!(
                        r#"<button
                            class="text-red-600 hover:text-red-800 dark:text-red-400 dark:hover:text-red-300 text-sm delete-comment-btn"
                            data-comment-id="{}"
                            title="Delete comment">
                            Delete
                        </button>"#,
                        comment.id
                    )
                } else {
                    String::new()
                };

                format!(
                    r#"<div class="border-b border-gray-200 dark:border-gray-700 pb-4 mb-4 last:border-b-0">
    <div class="flex items-start justify-between mb-2">
        <div class="flex items-center space-x-2">
            <div class="w-8 h-8 rounded-full bg-blue-500 flex items-center justify-center text-white font-bold text-sm">
                {}
            </div>
            <div>
                <p class="text-sm font-medium text-gray-900 dark:text-white">{}</p>
                <p class="text-xs text-gray-500 dark:text-gray-400">{}</p>
            </div>
        </div>
        {}
    </div>
    <div class="ml-10">
        <p class="text-sm text-gray-700 dark:text-gray-300 whitespace-pre-wrap">{}</p>
    </div>
</div>"#,
                    get_user_initials(&comment.user_name),
                    html_escape(&comment.user_name),
                    format_datetime(&comment.created_at),
                    delete_button,
                    html_escape(&comment.content)
                )
            })
            .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">
    <h3 class="text-lg font-bold text-gray-900 dark:text-white mb-4">
        Comments ({})
    </h3>

    <!-- Comments List -->
    <div class="mb-6 max-h-96 overflow-y-auto" id="comments-list-{}">
        {}
    </div>

    <!-- Add Comment Form -->
    <form id="add-comment-form-{}" class="border-t border-gray-200 dark:border-gray-700 pt-4">
        <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">
            Add a comment
        </label>
        <textarea
            id="comment-text-{}"
            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 resize-none"
            rows="3"
            placeholder="Share your thoughts..."
            required></textarea>

        <div class="mt-3 flex justify-end space-x-2">
            <button
                type="button"
                id="cancel-comment-{}"
                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
                type="submit"
                class="px-4 py-2 bg-blue-600 hover:bg-blue-700 text-white rounded-md transition-colors">
                Post Comment
            </button>
        </div>
    </form>
</div>

<script>
    (function() {{
        const taskId = '{}';
        const form = document.getElementById('add-comment-form-' + taskId);
        const textarea = document.getElementById('comment-text-' + taskId);
        const cancelBtn = document.getElementById('cancel-comment-' + taskId);

        // Handle form submission
        form?.addEventListener('submit', async function(e) {{
            e.preventDefault();

            const content = textarea?.value?.trim();
            if (!content) {{
                alert('Please enter a comment');
                return;
            }}

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

                const response = await fetch(`/api/tasks/${{taskId}}/comments`, {{
                    method: 'POST',
                    headers: headers,
                    body: JSON.stringify({{ content: content }})
                }});

                if (response.ok) {{
                    // Clear form and reload
                    textarea.value = '';
                    window.location.reload();
                }} else {{
                    const error = await response.json();
                    alert('Failed to post comment: ' + (error.error || 'Unknown error'));
                }}
            }} catch (err) {{
                console.error('Comment error:', err);
                alert('Network error. Please try again.');
            }}
        }});

        // Handle cancel button
        cancelBtn?.addEventListener('click', function() {{
            textarea.value = '';
            textarea.blur();
        }});

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

                const commentId = this.getAttribute('data-comment-id');

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

                    const response = await fetch(`/api/tasks/${{taskId}}/comments/${{commentId}}`, {{
                        method: 'DELETE',
                        headers: headers
                    }});

                    if (response.ok) {{
                        window.location.reload();
                    }} else {{
                        alert('Failed to delete comment');
                    }}
                }} catch (err) {{
                    console.error('Delete error:', err);
                    alert('Network error. Please try again.');
                }}
            }});
        }});

        // Auto-resize textarea
        textarea?.addEventListener('input', function() {{
            this.style.height = 'auto';
            this.style.height = this.scrollHeight + 'px';
        }});
    }})();
</script>"#,
        comments.len(),
        task_id,
        comments_html,
        task_id,
        task_id,
        task_id,
        task_id,
        auth_header,
        auth_header
    )
}

/// Get user initials from name
fn get_user_initials(name: &str) -> String {
    name.split_whitespace()
        .take(2)
        .filter_map(|word| word.chars().next())
        .collect::<String>()
        .to_uppercase()
}

/// 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 {
    // Parse ISO 8601 datetime and format for display
    if let Some(datetime_str) = dt.split('T').next() {
        if let Some(time_str) = dt.split('T').nth(1) {
            if let Some(time_part) = time_str.split('.').next() {
                return format!("{} {}", datetime_str, &time_part[..5]);
            }
        }
        return datetime_str.to_string();
    }
    dt.to_string()
}

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

    #[test]
    fn test_get_user_initials() {
        assert_eq!(get_user_initials("John Doe"), "JD");
        assert_eq!(get_user_initials("Alice"), "A");
        assert_eq!(get_user_initials("Bob Smith Johnson"), "BS");
        assert_eq!(get_user_initials(""), "");
    }

    #[test]
    fn test_html_escape() {
        assert_eq!(html_escape("Hello"), "Hello");
        assert_eq!(
            html_escape("<script>alert('xss')</script>"),
            "&lt;script&gt;alert(&#x27;xss&#x27;)&lt;/script&gt;"
        );
        assert_eq!(html_escape("A & B"), "A &amp; B");
    }

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

    #[test]
    fn test_task_comments_html_empty() {
        let html = task_comments_html("task-123", &[], None, None);
        assert!(html.contains("task-123"));
        assert!(html.contains("No comments yet"));
        assert!(html.contains("Comments (0)"));
    }

    #[test]
    fn test_task_comments_html_with_comments() {
        let comments = vec![TaskCommentDto {
            id: "comment-1".to_string(),
            task_id: "task-123".to_string(),
            user_id: "user-1".to_string(),
            user_name: "John Doe".to_string(),
            content: "Great work!".to_string(),
            created_at: "2023-11-14T10:00:00Z".to_string(),
            updated_at: "2023-11-14T10:00:00Z".to_string(),
        }];

        let html = task_comments_html("task-123", &comments, Some("token"), Some("user-1"));
        assert!(html.contains("John Doe"));
        assert!(html.contains("Great work!"));
        assert!(html.contains("JD")); // Initials
        assert!(html.contains("Comments (1)"));
        assert!(html.contains("Delete")); // User can delete own comment
    }

    #[test]
    fn test_task_comments_html_cannot_delete_others() {
        let comments = vec![TaskCommentDto {
            id: "comment-1".to_string(),
            task_id: "task-123".to_string(),
            user_id: "user-1".to_string(),
            user_name: "John Doe".to_string(),
            content: "Test comment".to_string(),
            created_at: "2023-11-14T10:00:00Z".to_string(),
            updated_at: "2023-11-14T10:00:00Z".to_string(),
        }];

        let html = task_comments_html("task-123", &comments, Some("token"), Some("user-2"));
        // Different user cannot delete - check for "Delete" button text
        assert!(!html.contains(">Delete<"));
    }
}
