import React, { useEffect, useState } from 'react';
import { openUrl } from '@tauri-apps/plugin-opener';
import { newsBridge } from '../../lib/newsBridge';
import {
  buildNewsTickerCommand,
  formatNewsRelativeTime,
  highlightReasonLabel,
  newsSentimentTone,
  partitionNewsSummaryArticles,
  sortNewsArticlesChronologically,
} from '../../news';
import type { NewsArticle } from '../../types/news';
import { SentimentBadge } from '../ui/SentimentBadge';

interface NewsPanelProps {
  news: NewsArticle[];
  ticker?: string;
  onRunCommand?: (command: string) => void;
}

interface NewsPanelHeaderProps {
  title: string;
  count: number;
  ticker?: string;
}

interface NewsSectionProps {
  title: string;
  children: React.ReactNode;
}

interface NewsArticleCardProps {
  article: NewsArticle;
  isTickerMode: boolean;
  isPending: boolean;
  activeTicker?: string;
  onOpenArticle: (article: NewsArticle) => Promise<void>;
  onMarkRead: (articleId: string) => Promise<void>;
  onToggleSaved: (articleId: string, isSaved: boolean) => Promise<void>;
  onRunCommand?: (command: string) => void;
}

const NewsPanelHeader: React.FC<NewsPanelHeaderProps> = ({ title, count, ticker }) => (
  <header className="mb-5 flex items-center gap-3">
    <h2 className="text-heading-lg text-term-text">{title}</h2>
    {ticker ? (
      <span className="rounded border border-[var(--term-status-info-border)] bg-[var(--term-status-info)] px-2 py-1 font-mono text-[11px] uppercase tracking-[0.2em] text-[var(--term-status-info-strong)]">
        {ticker}
      </span>
    ) : null}
    <span className="rounded border border-info/40 bg-info/10 px-2 py-1 font-mono text-[10px] text-info">
      {count}
    </span>
  </header>
);

const NewsSection: React.FC<NewsSectionProps> = ({ title, children }) => (
  <section className="space-y-3">
    <div className="flex items-center gap-3">
      <h3 className="font-mono text-[11px] uppercase tracking-[0.22em] text-term-text-muted">
        {title}
      </h3>
      <div className="h-px flex-1 bg-term-border-subtle" />
    </div>
    {children}
  </section>
);

const NewsArticleCard: React.FC<NewsArticleCardProps> = ({
  article,
  isTickerMode,
  isPending,
  activeTicker,
  onOpenArticle,
  onMarkRead,
  onToggleSaved,
  onRunCommand,
}) => {
  const summaryClassName = isTickerMode ? 'line-clamp-3' : 'line-clamp-2';
  const visibleTickers = article.tickers.slice(0, isTickerMode ? article.tickers.length : 3);

  const runTickerCommand = (articleTicker: string) => {
    if (!onRunCommand) {
      return;
    }

    if (activeTicker && articleTicker.toUpperCase() === activeTicker.toUpperCase()) {
      return;
    }

    onRunCommand(buildNewsTickerCommand(articleTicker));
  };

  return (
    <article
      className={`rounded-2xl border px-4 py-4 transition-colors ${
        article.isRead
          ? 'border-term-border-subtle bg-term-elevated'
          : 'border-[var(--term-status-info-border)] bg-term-surface'
      }`}
    >
      <div className="mb-3 flex flex-wrap items-center gap-2">
        <span className="rounded bg-info/10 px-2 py-1 font-mono text-[10px] uppercase tracking-[0.2em] text-info">
          {article.source}
        </span>
        <span className="font-mono text-[10px] text-term-text-muted">
          {formatNewsRelativeTime(article.publishedAt)}
        </span>
        <SentimentBadge sentiment={newsSentimentTone(article.sentiment)} size="sm" />
        {article.highlightReason ? (
          <span className="rounded border border-[var(--term-status-warning-border)] bg-[var(--term-status-warning)] px-2 py-1 font-mono text-[10px] uppercase tracking-[0.16em] text-warning">
            {highlightReasonLabel(article.highlightReason)}
          </span>
        ) : null}
      </div>

      {article.url ? (
        <button
          type="button"
          className={`mb-2 block line-clamp-2 text-left text-body-sm font-semibold leading-snug transition-colors ${
            article.isRead
              ? 'text-term-text-muted hover:text-term-text'
              : 'text-term-text hover:text-info'
          }`}
          onClick={() => void onOpenArticle(article)}
        >
          {article.headline}
        </button>
      ) : (
        <h4
          className={`mb-2 line-clamp-2 text-body-sm font-semibold leading-snug ${
            article.isRead ? 'text-term-text-muted' : 'text-term-text'
          }`}
        >
          {article.headline}
        </h4>
      )}

      {article.summary ? (
        <p className={`mb-3 text-body-xs leading-relaxed text-term-text-muted ${summaryClassName}`}>
          {article.summary}
        </p>
      ) : null}

      <div className="flex flex-wrap items-center gap-2">
        {visibleTickers.map((articleTicker) => {
          const isActiveTicker =
            activeTicker &&
            articleTicker.toUpperCase() === activeTicker.toUpperCase();

          return onRunCommand ? (
            <button
              key={articleTicker}
              type="button"
              disabled={Boolean(isActiveTicker)}
              className={`rounded px-2 py-1 font-mono text-[10px] uppercase tracking-[0.16em] ${
                isActiveTicker
                  ? 'bg-[var(--term-status-info)] text-[var(--term-status-info-strong)]'
                  : 'bg-term-highlight text-info transition-colors hover:bg-term-surface hover:text-term-text'
              } disabled:cursor-default`}
              onClick={() => runTickerCommand(articleTicker)}
            >
              {articleTicker}
            </button>
          ) : (
            <span
              key={articleTicker}
              className="rounded bg-term-highlight px-2 py-1 font-mono text-[10px] uppercase tracking-[0.16em] text-info"
            >
              {articleTicker}
            </span>
          );
        })}

        <div className="ml-auto flex items-center gap-2">
          <button
            type="button"
            className="rounded border border-term-border px-2 py-1 font-mono text-[10px] uppercase tracking-[0.16em] text-term-text-muted transition-colors hover:border-info hover:text-term-text disabled:opacity-50"
            disabled={isPending}
            onClick={() => void onMarkRead(article.id)}
          >
            {article.isRead ? 'Read' : 'Mark Read'}
          </button>
          <button
            type="button"
            className={`rounded border px-2 py-1 font-mono text-[10px] uppercase tracking-[0.16em] transition-colors disabled:opacity-50 ${
              article.isSaved
                ? 'border-[var(--term-status-success-border)] bg-[var(--term-status-success)] text-positive'
                : 'border-term-border text-term-text-muted hover:border-info hover:text-term-text'
            }`}
            disabled={isPending}
            onClick={() => void onToggleSaved(article.id, !article.isSaved)}
          >
            {article.isSaved ? 'Saved' : 'Save'}
          </button>
          {article.url ? (
            <button
              type="button"
              className="rounded border border-term-border px-2 py-1 font-mono text-[10px] uppercase tracking-[0.16em] text-info transition-colors hover:border-info/40 hover:text-term-text"
              onClick={() => void onOpenArticle(article)}
            >
              Open
            </button>
          ) : null}
        </div>
      </div>
    </article>
  );
};

export const NewsPanel: React.FC<NewsPanelProps> = ({ news, ticker, onRunCommand }) => {
  const [articles, setArticles] = useState(news);
  const [pendingArticleIds, setPendingArticleIds] = useState<Record<string, boolean>>({});
  const normalizedTicker = ticker?.trim().toUpperCase();
  const isTickerMode = Boolean(normalizedTicker);

  useEffect(() => {
    setArticles(news);
  }, [news]);

  const sortedArticles = sortNewsArticlesChronologically(articles);
  const { highlights, recent } = partitionNewsSummaryArticles(sortedArticles);

  const setPending = (articleId: string, pending: boolean) => {
    setPendingArticleIds((current) => ({
      ...current,
      [articleId]: pending,
    }));
  };

  const replaceArticle = (articleId: string, updater: (article: NewsArticle) => NewsArticle) => {
    setArticles((current) =>
      current.map((article) => (article.id === articleId ? updater(article) : article)),
    );
  };

  const toggleSaved = async (articleId: string, isSaved: boolean) => {
    const previousArticle = articles.find((article) => article.id === articleId);
    if (!previousArticle) {
      return;
    }

    setPending(articleId, true);
    replaceArticle(articleId, (article) => ({ ...article, isSaved }));
    try {
      await newsBridge.updateNewsArticleState({ articleId, isSaved });
    } catch {
      replaceArticle(articleId, () => previousArticle);
    } finally {
      setPending(articleId, false);
    }
  };

  const markRead = async (articleId: string) => {
    const previousArticle = articles.find((article) => article.id === articleId);
    if (!previousArticle || previousArticle.isRead) {
      return;
    }

    setPending(articleId, true);
    replaceArticle(articleId, (article) => ({ ...article, isRead: true }));
    try {
      await newsBridge.updateNewsArticleState({ articleId, isRead: true });
    } catch {
      replaceArticle(articleId, () => previousArticle);
    } finally {
      setPending(articleId, false);
    }
  };

  const openArticle = async (article: NewsArticle) => {
    if (!article.url) {
      return;
    }

    await markRead(article.id);
    await openUrl(article.url);
  };

  const renderArticleCard = (article: NewsArticle) => (
    <NewsArticleCard
      key={article.id}
      article={article}
      isTickerMode={isTickerMode}
      isPending={pendingArticleIds[article.id] === true}
      activeTicker={normalizedTicker}
      onOpenArticle={openArticle}
      onMarkRead={markRead}
      onToggleSaved={toggleSaved}
      onRunCommand={onRunCommand}
    />
  );

  if (sortedArticles.length === 0) {
    return (
      <div className="py-4">
        <NewsPanelHeader
          title={isTickerMode ? `News: ${normalizedTicker}` : 'Market News'}
          count={0}
          ticker={normalizedTicker}
        />
        <div className="rounded-2xl border border-dashed border-term-border bg-term-elevated px-6 py-10 text-center">
          <p className="font-mono text-sm text-term-text-muted">
            {isTickerMode
              ? `No news articles found for ${normalizedTicker}.`
              : 'No news articles found.'}
          </p>
          {!isTickerMode ? (
            <p className="mt-2 font-mono text-[11px] uppercase tracking-[0.16em] text-term-text-tertiary">
              Try again after the next background refresh.
            </p>
          ) : null}
        </div>
      </div>
    );
  }

  if (isTickerMode) {
    return (
      <div className="py-4">
        <NewsPanelHeader
          title={`News: ${normalizedTicker}`}
          count={sortedArticles.length}
          ticker={normalizedTicker}
        />
        <div className="space-y-4">{sortedArticles.map(renderArticleCard)}</div>
      </div>
    );
  }

  return (
    <div className="py-4">
      <NewsPanelHeader title="Market News" count={sortedArticles.length} />
      <div className="space-y-6">
        {highlights.length > 0 ? (
          <NewsSection title="Highlights">
            <div className="space-y-4">{highlights.map(renderArticleCard)}</div>
          </NewsSection>
        ) : null}
        {recent.length > 0 ? (
          <NewsSection title="Recent">
            <div className="space-y-3">{recent.map(renderArticleCard)}</div>
          </NewsSection>
        ) : null}
      </div>
    </div>
  );
};
