'use client';

import { Rss, Search, Star, Settings, Plus, Trash2, X, ExternalLink } from 'lucide-react';
import { useState, useEffect, useCallback, useRef } from 'react';
import { formatDistanceToNow } from 'date-fns';

// --- Types ---

interface FeedItem {
    id: number;
    feed_id: number;
    title: string;
    link: string;
    pub_date: string | null;
    creator: string | null;
    snippet: string | null;
    read: number;
    bookmarked: number;
    feed_name: string;
    feed_url: string | null;
}

interface Feed {
    id: number;
    name: string;
    url: string;
    last_fetched: string | null;
    item_count: number;
}

// --- Helpers ---

function feedColor(name: string): string {
    let hash = 0;
    for (let i = 0; i < name.length; i++) {
        hash = name.charCodeAt(i) + ((hash << 5) - hash);
    }
    const colors = [
        'bg-amber-500/20 text-amber-400',
        'bg-blue-500/20 text-blue-400',
        'bg-emerald-500/20 text-emerald-400',
        'bg-purple-500/20 text-purple-400',
        'bg-rose-500/20 text-rose-400',
        'bg-cyan-500/20 text-cyan-400',
        'bg-orange-500/20 text-orange-400',
        'bg-indigo-500/20 text-indigo-400',
    ];
    return colors[Math.abs(hash) % colors.length];
}

function feedHealthDot(lastFetched: string | null): string {
    if (!lastFetched) return 'bg-neutral-600';
    const diff = Date.now() - new Date(lastFetched).getTime();
    if (diff < 10 * 60 * 1000) return 'bg-emerald-500';
    if (diff < 30 * 60 * 1000) return 'bg-amber-500';
    return 'bg-red-500';
}

function faviconUrl(feedUrl: string): string {
    try {
        const domain = new URL(feedUrl).hostname;
        return `https://www.google.com/s2/favicons?domain=${domain}&sz=32`;
    } catch {
        return '';
    }
}

function FeedFavicon({ url, size = 14 }: { url: string; size?: number }) {
    const src = faviconUrl(url);
    if (!src) return null;
    return (
        // eslint-disable-next-line @next/next/no-img-element
        <img
            src={src}
            alt=""
            width={size}
            height={size}
            className="shrink-0 rounded-sm"
            onError={(e) => { (e.target as HTMLImageElement).style.display = 'none'; }}
        />
    );
}

// --- Sub-components ---

function SearchBar({ value, onChange }: { value: string; onChange: (v: string) => void }) {
    const [local, setLocal] = useState(value);
    const timerRef = useRef<ReturnType<typeof setTimeout>>();

    useEffect(() => { setLocal(value); }, [value]);

    const handleChange = (v: string) => {
        setLocal(v);
        clearTimeout(timerRef.current);
        timerRef.current = setTimeout(() => onChange(v), 300);
    };

    return (
        <div className="relative flex-1 max-w-[200px]">
            <Search size={13} className="absolute left-2 top-1/2 -translate-y-1/2 text-neutral-500" />
            <input
                type="text"
                placeholder="Search..."
                value={local}
                onChange={(e) => handleChange(e.target.value)}
                className="w-full bg-neutral-800 border border-neutral-700 rounded-lg pl-7 pr-2 py-1.5 text-xs text-white placeholder-neutral-500 focus:outline-none focus:border-neutral-500"
            />
        </div>
    );
}

function FeedFilterPills({
    feeds,
    activeFeedId,
    onSelect,
}: {
    feeds: Feed[];
    activeFeedId: number | null;
    onSelect: (id: number | null) => void;
}) {
    const totalItems = feeds.reduce((s, f) => s + f.item_count, 0);

    return (
        <div className="flex gap-1.5 overflow-x-auto pb-1 scrollbar-none">
            <button
                onClick={() => onSelect(null)}
                className={`shrink-0 px-2.5 py-1 rounded-full text-[11px] font-medium transition-colors ${
                    activeFeedId === null
                        ? 'bg-neutral-700 text-white'
                        : 'bg-neutral-800/60 text-neutral-400 hover:text-neutral-200'
                }`}
            >
                All ({totalItems})
            </button>
            {feeds.map((f) => (
                <button
                    key={f.id}
                    onClick={() => onSelect(f.id)}
                    className={`shrink-0 px-2.5 py-1 rounded-full text-[11px] font-medium transition-colors flex items-center gap-1.5 ${
                        activeFeedId === f.id
                            ? 'bg-neutral-700 text-white'
                            : 'bg-neutral-800/60 text-neutral-400 hover:text-neutral-200'
                    }`}
                >
                    <FeedFavicon url={f.url} size={12} />
                    {f.name} ({f.item_count})
                </button>
            ))}
        </div>
    );
}

function AddFeedForm({ onAdded }: { onAdded: () => void }) {
    const [url, setUrl] = useState('');
    const [submitting, setSubmitting] = useState(false);
    const [error, setError] = useState('');

    const handleSubmit = async (e: React.FormEvent) => {
        e.preventDefault();
        setError('');
        setSubmitting(true);
        try {
            const res = await fetch('/api/rss/feeds', {
                method: 'POST',
                headers: { 'Content-Type': 'application/json' },
                body: JSON.stringify({ url: url.trim() }),
            });
            if (!res.ok) {
                const data = await res.json();
                throw new Error(data.error || 'Failed to add feed');
            }
            setUrl('');
            onAdded();
        } catch (err: unknown) {
            setError(err instanceof Error ? err.message : 'Failed to add feed');
        } finally {
            setSubmitting(false);
        }
    };

    return (
        <form onSubmit={handleSubmit} className="flex gap-2 items-start">
            <div className="flex-1 min-w-0">
                <input
                    type="url"
                    placeholder="Paste RSS feed URL..."
                    value={url}
                    onChange={(e) => setUrl(e.target.value)}
                    required
                    className="w-full bg-neutral-800 border border-neutral-700 rounded-lg px-3 py-1.5 text-xs text-white placeholder-neutral-500 focus:outline-none focus:border-neutral-500"
                />
                {error && <p className="text-[10px] text-red-400 mt-1">{error}</p>}
            </div>
            <button
                type="submit"
                disabled={submitting}
                className="shrink-0 flex items-center gap-1 text-xs bg-neutral-700 hover:bg-neutral-600 text-white px-3 py-1.5 rounded-lg transition-colors disabled:opacity-50"
            >
                <Plus size={12} />
                {submitting ? 'Adding...' : 'Add'}
            </button>
        </form>
    );
}

function FeedManager({
    feeds,
    onChanged,
    onClose,
}: {
    feeds: Feed[];
    onChanged: () => void;
    onClose: () => void;
}) {
    const handleDelete = async (id: number) => {
        try {
            await fetch('/api/rss/feeds', {
                method: 'DELETE',
                headers: { 'Content-Type': 'application/json' },
                body: JSON.stringify({ id }),
            });
            onChanged();
        } catch (e) {
            console.error('Failed to delete feed:', e);
        }
    };

    return (
        <div className="border border-neutral-800 rounded-lg p-3 space-y-3 bg-neutral-900/50">
            <div className="flex items-center justify-between">
                <span className="text-xs font-medium text-neutral-400">Manage Feeds</span>
                <button onClick={onClose} className="text-neutral-500 hover:text-neutral-300 transition-colors">
                    <X size={14} />
                </button>
            </div>
            <AddFeedForm onAdded={onChanged} />
            <div className="space-y-1.5 max-h-[150px] overflow-y-auto scrollbar-thin">
                {feeds.map((f) => (
                    <div key={f.id} className="flex items-center justify-between gap-2 px-2 py-1.5 rounded-lg hover:bg-neutral-800/40 group">
                        <div className="flex items-center gap-2 min-w-0">
                            <div className={`w-1.5 h-1.5 rounded-full shrink-0 ${feedHealthDot(f.last_fetched)}`} />
                            <FeedFavicon url={f.url} size={14} />
                            <span className="text-xs text-neutral-300 truncate">{f.name}</span>
                            <span className="text-[10px] text-neutral-600 truncate hidden sm:inline">{f.url}</span>
                        </div>
                        <div className="flex items-center gap-2 shrink-0">
                            {f.last_fetched && (
                                <span className="text-[10px] text-neutral-600 font-mono">
                                    {formatDistanceToNow(new Date(f.last_fetched), { addSuffix: true })}
                                </span>
                            )}
                            <button
                                onClick={() => handleDelete(f.id)}
                                className="opacity-0 group-hover:opacity-100 text-neutral-500 hover:text-red-400 transition-all"
                            >
                                <Trash2 size={12} />
                            </button>
                        </div>
                    </div>
                ))}
            </div>
        </div>
    );
}

function FeedItemRow({
    item,
    onRead,
    onBookmark,
}: {
    item: FeedItem;
    onRead: (id: number) => void;
    onBookmark: (id: number, bookmarked: boolean) => void;
}) {
    const handleClick = () => {
        window.open(item.link, '_blank', 'noopener,noreferrer');
        if (!item.read) onRead(item.id);
    };

    return (
        <div
            className={`flex items-start gap-3 px-2 py-2.5 rounded-lg hover:bg-neutral-800/40 transition-colors group cursor-pointer ${
                item.read ? 'opacity-50' : 'border-l-2 border-l-amber-500/50'
            }`}
            onClick={handleClick}
        >
            <div className="flex-1 min-w-0">
                <div className="flex items-center gap-2 mb-1">
                    <span className={`shrink-0 px-1.5 py-0.5 rounded text-[9px] font-medium flex items-center gap-1 ${feedColor(item.feed_name || '')}`}>
                        {item.feed_url && <FeedFavicon url={item.feed_url} size={10} />}
                        {item.feed_name || 'Unknown'}
                    </span>
                    {item.creator && (
                        <span className="text-[10px] text-neutral-600 truncate">{item.creator}</span>
                    )}
                </div>
                <h3 className="text-sm text-neutral-300 font-medium group-hover:text-amber-400 transition-colors line-clamp-2 leading-snug">
                    {item.title}
                </h3>
                {item.snippet && (
                    <p className="text-[11px] text-neutral-600 line-clamp-1 mt-0.5">{item.snippet}</p>
                )}
                <div className="flex items-center gap-2 mt-1">
                    {item.pub_date && (
                        <span className="text-[10px] text-neutral-600 font-mono">
                            {formatDistanceToNow(new Date(item.pub_date), { addSuffix: true })}
                        </span>
                    )}
                </div>
            </div>
            <button
                onClick={(e) => {
                    e.stopPropagation();
                    onBookmark(item.id, !item.bookmarked);
                }}
                className={`shrink-0 mt-1 transition-colors ${
                    item.bookmarked
                        ? 'text-amber-400'
                        : 'text-neutral-700 opacity-0 group-hover:opacity-100 hover:text-amber-400'
                }`}
            >
                <Star size={14} fill={item.bookmarked ? 'currentColor' : 'none'} />
            </button>
        </div>
    );
}

// --- Main Component ---

export function NewsFeed() {
    const [items, setItems] = useState<FeedItem[]>([]);
    const [feeds, setFeeds] = useState<Feed[]>([]);
    const [searchQuery, setSearchQuery] = useState('');
    const [activeFeedId, setActiveFeedId] = useState<number | null>(null);
    const [showBookmarked, setShowBookmarked] = useState(false);
    const [showFeedManager, setShowFeedManager] = useState(false);
    const [loading, setLoading] = useState(true);
    const [newCount, setNewCount] = useState(0);
    const prevItemIdsRef = useRef<Set<number>>(new Set());

    const fetchFeeds = useCallback(async () => {
        try {
            const res = await fetch('/api/rss/feeds');
            const data = await res.json();
            if (Array.isArray(data)) setFeeds(data);
        } catch (e) {
            console.error('Failed to fetch feeds:', e);
        }
    }, []);

    const fetchItems = useCallback(async (opts?: { silent?: boolean; resetFeedFilter?: boolean }) => {
        try {
            const params = new URLSearchParams();
            if (searchQuery) params.set('q', searchQuery);
            if (!opts?.resetFeedFilter && activeFeedId !== null) params.set('feed_id', String(activeFeedId));
            if (showBookmarked) params.set('bookmarked', '1');
            params.set('limit', '50');

            const res = await fetch(`/api/rss?${params}`);
            const data = await res.json();
            if (Array.isArray(data)) {
                if (opts?.silent && prevItemIdsRef.current.size > 0) {
                    const newIds = data.filter((i: FeedItem) => !prevItemIdsRef.current.has(i.id));
                    if (newIds.length > 0) {
                        setNewCount((c) => c + newIds.length);
                    }
                }
                prevItemIdsRef.current = new Set(data.map((i: FeedItem) => i.id));
                setItems(data);
            }
        } catch (e) {
            console.error('Failed to fetch items:', e);
        } finally {
            setLoading(false);
        }
    }, [searchQuery, activeFeedId, showBookmarked]);

    // Initial load + refresh
    useEffect(() => {
        fetchFeeds();
        fetchItems();
    }, [fetchFeeds, fetchItems]);

    // Auto-refresh every 30s
    useEffect(() => {
        const interval = setInterval(() => {
            fetchItems({ silent: true });
            fetchFeeds();
        }, 30000);
        return () => clearInterval(interval);
    }, [fetchItems, fetchFeeds]);

    const handleRead = async (id: number) => {
        setItems((prev) => prev.map((i) => (i.id === id ? { ...i, read: 1 } : i)));
        try {
            await fetch('/api/rss', {
                method: 'PATCH',
                headers: { 'Content-Type': 'application/json' },
                body: JSON.stringify({ id, read: true }),
            });
        } catch (e) {
            console.error('Failed to mark as read:', e);
        }
    };

    const handleBookmark = async (id: number, bookmarked: boolean) => {
        setItems((prev) =>
            prev.map((i) => (i.id === id ? { ...i, bookmarked: bookmarked ? 1 : 0 } : i))
        );
        try {
            await fetch('/api/rss', {
                method: 'PATCH',
                headers: { 'Content-Type': 'application/json' },
                body: JSON.stringify({ id, bookmarked }),
            });
        } catch (e) {
            console.error('Failed to toggle bookmark:', e);
        }
    };

    const handleFeedChanged = () => {
        setActiveFeedId(null);
        fetchFeeds();
        fetchItems({ resetFeedFilter: true });
    };

    const handleDismissNew = () => {
        setNewCount(0);
        fetchItems();
    };

    const hasFeeds = feeds.length > 0;

    return (
        <div className="col-span-1 md:col-span-4 lg:col-span-4 row-span-3 bg-neutral-900 border border-neutral-800 rounded-xl p-5 flex flex-col hover:border-neutral-700 transition-colors overflow-hidden">
            {/* Header */}
            <div className="flex items-center justify-between gap-3 shrink-0 mb-3">
                <div className="flex items-center gap-2 text-neutral-400">
                    <Rss size={18} />
                    <span className="text-sm font-medium">Feed</span>
                </div>
                <div className="flex items-center gap-2">
                    <SearchBar value={searchQuery} onChange={setSearchQuery} />
                    <button
                        onClick={() => setShowBookmarked(!showBookmarked)}
                        className={`p-1.5 rounded-lg transition-colors ${
                            showBookmarked ? 'bg-amber-500/10 text-amber-400' : 'text-neutral-500 hover:text-neutral-300 hover:bg-neutral-800'
                        }`}
                        title="Bookmarks"
                    >
                        <Star size={15} fill={showBookmarked ? 'currentColor' : 'none'} />
                    </button>
                    <button
                        onClick={() => setShowFeedManager(!showFeedManager)}
                        className={`p-1.5 rounded-lg transition-colors ${
                            showFeedManager ? 'bg-neutral-700 text-white' : 'text-neutral-500 hover:text-neutral-300 hover:bg-neutral-800'
                        }`}
                        title="Manage feeds"
                    >
                        <Settings size={15} />
                    </button>
                </div>
            </div>

            {/* Feed filter pills */}
            {hasFeeds && (
                <div className="shrink-0 mb-2">
                    <FeedFilterPills feeds={feeds} activeFeedId={activeFeedId} onSelect={setActiveFeedId} />
                </div>
            )}

            {/* Feed manager (collapsible) */}
            {showFeedManager && (
                <div className="shrink-0 mb-3">
                    <FeedManager feeds={feeds} onChanged={handleFeedChanged} onClose={() => setShowFeedManager(false)} />
                </div>
            )}

            {/* New items badge */}
            {newCount > 0 && (
                <button
                    onClick={handleDismissNew}
                    className="shrink-0 mb-2 text-xs text-amber-400 bg-amber-500/10 rounded-lg py-1.5 px-3 text-center hover:bg-amber-500/20 transition-colors"
                >
                    {newCount} new item{newCount > 1 ? 's' : ''} — click to refresh
                </button>
            )}

            {/* Item list */}
            <div className="flex-1 overflow-y-auto min-h-0 pr-1 scrollbar-thin scrollbar-thumb-neutral-800">
                {loading ? (
                    <div className="space-y-3">
                        {[1, 2, 3, 4, 5].map((i) => (
                            <div key={i} className="space-y-2 animate-pulse px-2">
                                <div className="h-3 bg-neutral-800 rounded w-16" />
                                <div className="h-4 bg-neutral-800 rounded w-3/4" />
                                <div className="h-3 bg-neutral-800 rounded w-1/2" />
                            </div>
                        ))}
                    </div>
                ) : !hasFeeds ? (
                    <div className="flex flex-col items-center justify-center h-full text-neutral-500 gap-3">
                        <Rss size={32} className="opacity-30" />
                        <span className="text-sm">No feeds yet</span>
                        <button
                            onClick={() => setShowFeedManager(true)}
                            className="flex items-center gap-1.5 text-xs text-amber-400 hover:text-amber-300 transition-colors"
                        >
                            <Plus size={14} />
                            Add your first feed
                        </button>
                    </div>
                ) : items.length === 0 ? (
                    <div className="flex flex-col items-center justify-center h-full text-neutral-500 gap-2">
                        <Search size={24} className="opacity-30" />
                        <span className="text-sm">No items found</span>
                    </div>
                ) : (
                    <div className="space-y-0.5">
                        {items.map((item) => (
                            <FeedItemRow
                                key={item.id}
                                item={item}
                                onRead={handleRead}
                                onBookmark={handleBookmark}
                            />
                        ))}
                    </div>
                )}
            </div>
        </div>
    );
}
