use pulldown_cmark::{html as md_html, Options, Parser};
use serde::{Deserialize, Serialize};
use wasm_bindgen::prelude::*;
use wasm_bindgen_futures::spawn_local;
use web_sys::{HtmlInputElement, MouseEvent};
use yew::prelude::*;

#[wasm_bindgen]
extern "C" {
    #[wasm_bindgen(js_namespace = ["window", "__TAURI__", "core"], catch)]
    async fn invoke(cmd: &str, args: JsValue) -> Result<JsValue, JsValue>;
}

#[derive(PartialEq, Clone, Copy)]
pub enum NewsMode {
    Ai,
    Rss,
}

#[derive(Serialize, Deserialize, Clone, PartialEq, Debug)]
#[serde(rename_all = "camelCase")]
pub struct NewsArticle {
    pub content: String,
    pub author: String,
    pub created_at: String,
    pub category: String,
}

#[derive(Serialize, Deserialize, Clone, PartialEq, Debug)]
pub struct RssFeed {
    pub url: String,
    pub category: String,
}

#[derive(Serialize)]
struct StringArgs {
    key: String,
}
#[derive(Serialize)]
struct FeedsArgs {
    feeds: Vec<RssFeed>,
}
#[derive(Serialize)]
struct AiArgs {
    provider: String,
}

const CATEGORIES: &[&str] = &[
    "Alle",
    "Technik",
    "Nachrichten",
    "Wissenschaft",
    "KI",
    "Open Source",
];

#[function_component(News)]
pub fn news() -> Html {
    let articles = use_state(|| None::<Vec<NewsArticle>>);
    let error_msg = use_state(|| None::<String>);
    let show_config = use_state(|| false);
    let current_mode = use_state(|| NewsMode::Ai);
    let ai_provider = use_state(|| "openrouter".to_string());
    let rss_feeds = use_state(Vec::<RssFeed>::new);
    let selected_category = use_state(|| "Alle".to_string());

    let or_key_ref = use_node_ref();
    let groq_key_ref = use_node_ref();
    let new_url_ref = use_node_ref();
    let new_cat_ref = use_node_ref();

    // Init: RSS Feeds laden
    {
        let rss_feeds = rss_feeds.clone();
        use_effect_with((), move |_| {
            spawn_local(async move {
                if let Ok(res) = invoke("load_rss_config", JsValue::NULL).await {
                    if let Ok(feeds) = serde_wasm_bindgen::from_value::<Vec<RssFeed>>(res) {
                        rss_feeds.set(feeds);
                    }
                }
            });
            || ()
        });
    }

    let load_news = {
        let articles = articles.clone();
        let error_msg = error_msg.clone();
        let mode = *current_mode;
        let provider = (*ai_provider).clone();
        Callback::from(move |_| {
            let articles = articles.clone();
            let error_msg = error_msg.clone();
            let provider = provider.clone();
            articles.set(None);
            error_msg.set(None);
            spawn_local(async move {
                let (cmd, args) = if mode == NewsMode::Ai {
                    (
                        "fetch_ai_news",
                        serde_wasm_bindgen::to_value(&AiArgs { provider }).unwrap(),
                    )
                } else {
                    ("fetch_rss_news", JsValue::NULL)
                };
                match invoke(cmd, args).await {
                    Ok(res) => {
                        let data = serde_wasm_bindgen::from_value::<Vec<NewsArticle>>(res)
                            .unwrap_or_default();
                        articles.set(Some(data));
                    }
                    Err(e) => error_msg.set(Some(e.as_string().unwrap_or_default())),
                }
            });
        })
    };

    // Auto-Reload bei Mode/Provider-Switch
    {
        let load_news = load_news.clone();
        use_effect_with(
            ((*current_mode).clone(), (*ai_provider).clone()),
            move |_| {
                load_news.emit(MouseEvent::new("click").unwrap());
                || ()
            },
        );
    }

    let save_settings = {
        let rss_feeds = rss_feeds.clone();
        let or_ref = or_key_ref.clone();
        let groq_ref = groq_key_ref.clone();
        let show_config = show_config.clone();
        let load_news = load_news.clone();
        Callback::from(move |_| {
            let or_key = or_ref
                .cast::<HtmlInputElement>()
                .map(|i| i.value())
                .unwrap_or_default();
            let groq_key = groq_ref
                .cast::<HtmlInputElement>()
                .map(|i| i.value())
                .unwrap_or_default();
            let feeds = (*rss_feeds).clone();
            let show_config = show_config.clone();
            let load_news = load_news.clone();
            spawn_local(async move {
                let _ = invoke(
                    "save_openrouter_key",
                    serde_wasm_bindgen::to_value(&StringArgs { key: or_key }).unwrap(),
                )
                .await;
                let _ = invoke(
                    "save_groq_key",
                    serde_wasm_bindgen::to_value(&StringArgs { key: groq_key }).unwrap(),
                )
                .await;
                let _ = invoke(
                    "save_rss_urls",
                    serde_wasm_bindgen::to_value(&FeedsArgs { feeds }).unwrap(),
                )
                .await;
                show_config.set(false);
                load_news.emit(MouseEvent::new("click").unwrap());
            });
        })
    };

    // Gefilterte Artikel für die Anzeige
    let filtered_articles: Vec<NewsArticle> = (*articles)
        .clone()
        .unwrap_or_default()
        .into_iter()
        .filter(|a| *selected_category == "Alle" || a.category == *selected_category)
        .collect();

    html! {
        <div class="feed-container">
            <div class="feed-header">
                <div class="header-main">
                    <h1>{ if *current_mode == NewsMode::Ai { "📰 KI News" } else { "📻 RSS" } }</h1>
                    <div class="mode-toggle">
                        <button class={if *current_mode == NewsMode::Ai { "toggle-btn active" } else { "toggle-btn" }}
                                onclick={let m = current_mode.clone(); move |_| m.set(NewsMode::Ai)}>{"KI"}</button>
                        <button class={if *current_mode == NewsMode::Rss { "toggle-btn active" } else { "toggle-btn" }}
                                onclick={let m = current_mode.clone(); move |_| m.set(NewsMode::Rss)}>{"RSS"}</button>
                    </div>
                </div>

                if *current_mode == NewsMode::Ai {
                    <div class="provider-switch">
                        <button class={if *ai_provider == "openrouter" { "prov-btn active" } else { "prov-btn" }}
                                onclick={let p = ai_provider.clone(); move |_| p.set("openrouter".into())}>{"OR"}</button>
                        <button class={if *ai_provider == "groq" { "prov-btn active" } else { "prov-btn" }}
                                onclick={let p = ai_provider.clone(); move |_| p.set("groq".into())}>{"Groq"}</button>
                    </div>
                }

                <div class="header-actions">
                    <button class="action-btn" onclick={let sc = show_config.clone(); move |_| sc.set(!*sc)}>{"⚙️"}</button>
                    <button class="action-btn" onclick={load_news.clone()}>{"🔄"}</button>
                </div>
            </div>

            // ── Kategorie-Filterleiste ──────────────────────────────────────
            if *current_mode == NewsMode::Rss {
                <div class="category-bar">
                    { for CATEGORIES.iter().map(|&cat| {
                        let selected_category = selected_category.clone();
                        let is_active = *selected_category == cat;
                        html! {
                            <button
                                class={if is_active { "cat-btn active" } else { "cat-btn" }}
                                onclick={Callback::from(move |_| selected_category.set(cat.to_string()))}>
                                { cat }
                            </button>
                        }
                    }) }
                </div>
            }

            // ── Einstellungen ───────────────────────────────────────────────
            if *show_config {
                <div class="config-panel">
                    <div class="config-section">
                        <label>{"OpenRouter Key"}</label>
                        <input ref={or_key_ref} type="password" class="config-input" placeholder="sk-or-..." />
                    </div>
                    <div class="config-section">
                        <label>{"Groq Key"}</label>
                        <input ref={groq_key_ref} type="password" class="config-input" placeholder="gsk-..." />
                    </div>
                    <div class="config-section">
                        <label>{"RSS FEEDS"}</label>

                        // Bestehende Feeds auflisten
                        <div class="rss-list-scroll">
                            { for (*rss_feeds).iter().enumerate().map(|(i, feed)| {
                                let rss_feeds = rss_feeds.clone();
                                let url_display = feed.url.clone();
                                let cat_display = feed.category.clone();
                                let on_delete = Callback::from(move |_| {
                                    let mut list = (*rss_feeds).clone();
                                    list.remove(i);
                                    rss_feeds.set(list);
                                });
                                html! {
                                    <div class="rss-url-entry" key={url_display.clone()}>
                                        <span class="url-text">{ &url_display }</span>
                                        <span class="cat-badge">{ &cat_display }</span>
                                        <button class="delete-btn" onclick={on_delete}>{"🗑️"}</button>
                                    </div>
                                }
                            }) }
                        </div>

                        // Neue URL + Kategorie hinzufügen
                        <div class="rss-add-row">
                            <input ref={new_url_ref.clone()} type="text" class="config-input" placeholder="https://..." />
                            <select ref={new_cat_ref.clone()} class="cat-select">
                                { for CATEGORIES.iter().skip(1).map(|&cat| html! {
                                    <option value={cat}>{ cat }</option>
                                }) }
                            </select>
                            <button class="add-btn" onclick={
                                let rss_feeds = rss_feeds.clone();
                                let url_ref = new_url_ref.clone();
                                let cat_ref = new_cat_ref.clone();
                                move |_| {
                                    let url_input = url_ref.cast::<HtmlInputElement>();
                                    let cat_input = cat_ref.cast::<HtmlInputElement>();
                                    if let (Some(u), Some(c)) = (url_input, cat_input) {
                                        let url = u.value();
                                        let category = c.value();
                                        if !url.trim().is_empty() {
                                            let mut list = (*rss_feeds).clone();
                                            list.push(RssFeed { url, category });
                                            rss_feeds.set(list);
                                            u.set_value("");
                                        }
                                    }
                                }
                            }>{"+"}</button>
                        </div>
                    </div>
                    <button class="save-master-btn" onclick={save_settings}>{"Alles Speichern"}</button>
                </div>
            }

            // ── Artikel-Liste ───────────────────────────────────────────────
            <div class="posts-list">
                { if let Some(msg) = (*error_msg).clone() {
                    html! { <div class="error-box">{ format!("⚠️ Error: {}", msg) }</div> }
                } else if (*articles).is_none() {
                    html! { <div class="loading-spinner">{"Lade Nachrichten..."}</div> }
                } else if filtered_articles.is_empty() {
                    html! { <div class="empty-msg">{"Keine Artikel in dieser Kategorie."}</div> }
                } else {
                    html! { for filtered_articles.iter().map(|a| html! { <NewsCard article={a.clone()} /> }) }
                } }
            </div>
        </div>
    }
}

#[derive(Properties, PartialEq)]
pub struct NewsCardProps {
    pub article: NewsArticle,
}

#[function_component(NewsCard)]
pub fn news_card(props: &NewsCardProps) -> Html {
    let a = &props.article;
    let markdown_html = {
        let mut options = Options::empty();
        options.insert(Options::ENABLE_STRIKETHROUGH);
        let parser = Parser::new_ext(&a.content, options);
        let mut out = String::new();
        md_html::push_html(&mut out, parser);
        out
    };
    html! {
        <div class="post-card">
            <div class="post-header">
                <span class="post-author">{ &a.author }</span>
                <div class="post-meta">
                    <span class="post-category-badge">{ &a.category }</span>
                    <span class="post-date">{ &a.created_at }</span>
                </div>
            </div>
            <div class="post-content markdown-body">
                { Html::from_html_unchecked(AttrValue::from(markdown_html)) }
            </div>
        </div>
    }
}
