import { Link } from 'react-router-dom';
import React, { useEffect, useMemo, useState } from 'react';
import {
  FaArrowRight,
  FaRegFileAlt,
  FaRegLightbulb,
  FaRegNewspaper,
  FaSpinner,
} from 'react-icons/fa';
import { HiSparkles } from 'react-icons/hi';

import { formatNumber } from '../agent-analytics/helpers';
import type {
  ArticleListResponse,
  SuggestionEntry,
} from '../../service/visibility/visibility.interface';
import {
  generateArticle,
  listArticles,
  listBrands,
  listSuggestions,
} from '../../service/visibility/visibility.service';

const ARTICLES_TO = '/ai-visibility';
const MAX_IDEAS = 5;

interface ArticlesState {
  data: ArticleListResponse;
  ideas: SuggestionEntry[];
  brandId: string | null;
}

const EMPTY_STATE: ArticlesState = {
  data: { articles: [], counts: { recommended: 0, published: 0 } },
  ideas: [],
  brandId: null,
};

/**
 * Dashboard "Article ideas" widget - top ungenerated ideas with one-click
 * generate. Generated articles live behind "View all"; only ideas show here.
 *
 * @param {object} props - Recomaze auth.
 * @return {React.ReactElement} The articles section.
 */
export function LatestArticles({
  clientId,
  token,
}: {
  clientId: string;
  token: string;
}) {
  const [state, setState] = useState<ArticlesState>(EMPTY_STATE);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    if (!clientId || !token) return;
    let cancelled = false;
    setLoading(true);

    /**
     * Fetch the five most recently created articles (any status); the backend
     * returns them sorted by created_at desc. Benign empty fallback on error.
     */
    const loadArticles = async (): Promise<ArticleListResponse> => {
      try {
        return await listArticles(clientId, token, { limit: 5 });
      } catch {
        return EMPTY_STATE.data;
      }
    };

    /** Fetch the first brand's top ideas; benign empty fallback on error. */
    const loadIdeas = async (): Promise<{
      brandId: string | null;
      ideas: SuggestionEntry[];
    }> => {
      try {
        const brandsRes = await listBrands(clientId, token);
        const brandId = brandsRes.brands?.[0]?.brand_id ?? null;
        if (!brandId) return { brandId: null, ideas: [] };
        const suggestionsRes = await listSuggestions(clientId, token, brandId);
        const ideas = (suggestionsRes.suggestions ?? [])
          .filter(
            suggestion =>
              suggestion.lifecycle_state === 'suggested' ||
              suggestion.lifecycle_state === 'accepted'
          )
          .slice(0, MAX_IDEAS);

        return { brandId, ideas };
      } catch {
        return { brandId: null, ideas: [] };
      }
    };

    void (async () => {
      try {
        const [data, ideaResult] = await Promise.all([
          loadArticles(),
          loadIdeas(),
        ]);
        if (!cancelled) {
          setState({
            data,
            ideas: ideaResult.ideas,
            brandId: ideaResult.brandId,
          });
        }
      } catch {
        // Benign: the store may have no visibility data yet.
      } finally {
        if (!cancelled) setLoading(false);
      }
    })();

    return () => {
      cancelled = true;
    };
  }, [clientId, token]);

  const { data, ideas, brandId } = state;
  const { articles, counts } = data;

  const inProgressSuggestionIds = useMemo(
    () =>
      new Set(
        articles
          .filter(
            article =>
              article.status === 'pending' || article.status === 'generating'
          )
          .map(article => article.triggered_by_suggestion_id)
          .filter(Boolean)
      ),
    [articles]
  );
  const visibleIdeas = brandId
    ? ideas.filter(idea => !inProgressSuggestionIds.has(idea.suggestion_id))
    : [];

  return (
    <section className="rounded-2xl border border-gray-200 bg-white p-6">
      <div className="mb-4 flex flex-wrap items-end justify-between gap-3">
        <div className="flex items-center gap-2.5">
          <span className="flex h-9 w-9 shrink-0 items-center justify-center rounded-xl bg-indigo-50 ring-1 ring-indigo-100">
            <FaRegNewspaper className="h-4 w-4 text-indigo-500" />
          </span>
          <div>
            <h2 className="text-base font-semibold text-gray-900">
              Content ideas
            </h2>
            <p className="mt-0.5 text-xs text-gray-500">
              Generate AEO content for your tracked prompts in one click
            </p>
          </div>
        </div>
        <div className="flex items-center gap-2">
          <CountBadge
            label="Recommended"
            value={counts?.recommended ?? 0}
            dot="bg-amber-400"
          />
          <CountBadge
            label="Published"
            value={counts?.published ?? 0}
            dot="bg-emerald-400"
          />
          <Link
            to={ARTICLES_TO}
            className="group inline-flex items-center gap-1 rounded-full border border-gray-200 bg-white px-3 py-1.5 text-xs font-medium text-gray-600 transition-colors hover:border-[#B7007C]/30 hover:text-[#B7007C]"
          >
            View all
            <FaArrowRight className="h-3 w-3 transition-transform group-hover:translate-x-0.5" />
          </Link>
        </div>
      </div>

      {loading ? (
        <SkeletonRows />
      ) : visibleIdeas.length === 0 ? (
        <EmptyState />
      ) : (
        <div className="space-y-2.5">
          {visibleIdeas.map(idea => (
            <IdeaRow
              key={idea.suggestion_id}
              idea={idea}
              brandId={brandId as string}
              clientId={clientId}
              token={token}
            />
          ))}
        </div>
      )}
    </section>
  );
}

function CountBadge({
  label,
  value,
  dot,
}: {
  label: string;
  value: number;
  dot: string;
}) {
  return (
    <span className="hidden items-center gap-1.5 rounded-full border border-gray-200 bg-white px-2.5 py-1 text-xs text-gray-500 sm:inline-flex">
      <span className={`h-1.5 w-1.5 rounded-full ${dot}`} />
      {label}
      <span className="font-semibold text-gray-900">{value}</span>
    </span>
  );
}

function IdeaRow({
  idea,
  brandId,
  clientId,
  token,
}: {
  idea: SuggestionEntry;
  brandId: string;
  clientId: string;
  token: string;
}) {
  const [dispatching, setDispatching] = useState(false);
  const [dispatched, setDispatched] = useState(false);
  const [error, setError] = useState<string | null>(null);

  const handleGenerate = async () => {
    if (dispatching || dispatched) return;
    setDispatching(true);
    setError(null);
    try {
      await generateArticle(clientId, token, {
        brand_id: brandId,
        topic: idea.topic || idea.title,
        target_prompts: idea.target_prompts ?? [],
        keywords: idea.keywords ?? [],
        language: idea.language || undefined,
        suggestion_id: idea.suggestion_id,
        triggered_by: 'suggestion',
      });
      setDispatched(true);
    } catch (generateError) {
      setError(
        generateError instanceof Error
          ? generateError.message
          : 'Failed to start generation. Please try again.'
      );
    } finally {
      setDispatching(false);
    }
  };

  return (
    <div className="flex items-start gap-3 rounded-xl border border-dashed border-amber-200 bg-amber-50/40 p-3.5">
      <span className="flex h-9 w-9 shrink-0 items-center justify-center rounded-xl bg-amber-100">
        <FaRegLightbulb className="h-4 w-4 text-amber-500" />
      </span>
      <div className="min-w-0 flex-1">
        <div className="flex items-center gap-2">
          <p className="truncate text-sm font-medium text-gray-900">
            {idea.title}
          </p>
          {idea.language && (
            <span className="shrink-0 rounded-md bg-gray-100 px-1.5 py-0.5 text-[10px] font-semibold uppercase tracking-wide text-gray-500">
              {idea.language}
            </span>
          )}
        </div>
        <div className="mt-1.5 flex flex-wrap items-center gap-x-2 gap-y-1 text-xs text-gray-500">
          <span className="shrink-0 rounded-full bg-amber-100 px-2 py-0.5 text-[10px] font-semibold uppercase tracking-wide text-amber-600">
            Idea
          </span>
          {idea.priority_score > 0 && (
            <span className="shrink-0 rounded-full bg-gray-100 px-2 py-0.5 text-[10px] font-semibold uppercase tracking-wide text-gray-500">
              Score {Math.round(idea.priority_score)}
            </span>
          )}
          {idea.estimated_word_count > 0 && (
            <span className="shrink-0">
              ~{formatNumber(idea.estimated_word_count)} words
            </span>
          )}
        </div>
        {(dispatching || dispatched) && !error && (
          <p className="mt-1.5 text-xs text-gray-500">
            Keep this page open. We&apos;re pulling matching products from your
            catalog and drafting the content. This usually takes a minute or
            two.
          </p>
        )}
        {error && <p className="mt-1 text-xs text-red-600">{error}</p>}
      </div>
      <button
        type="button"
        onClick={handleGenerate}
        disabled={dispatching || dispatched}
        className="inline-flex shrink-0 items-center gap-1.5 rounded-full border border-amber-300 bg-amber-100 px-3 py-1.5 text-xs font-medium text-amber-700 transition-colors hover:bg-amber-200 disabled:cursor-not-allowed disabled:opacity-60"
      >
        {dispatching || dispatched ? (
          <FaSpinner className="h-3.5 w-3.5 animate-spin" />
        ) : (
          <HiSparkles className="h-3.5 w-3.5" />
        )}
        {dispatching || dispatched ? 'Starting...' : 'Generate'}
      </button>
    </div>
  );
}

function SkeletonRows() {
  return (
    <div className="space-y-2.5">
      {Array.from({ length: 3 }).map((_, index) => (
        <div
          key={index}
          className="h-16 animate-pulse rounded-xl border border-gray-100 bg-gray-50"
        />
      ))}
    </div>
  );
}

function EmptyState() {
  return (
    <div className="flex flex-col items-center justify-center gap-2 rounded-xl border border-dashed border-gray-200 px-6 py-10 text-center">
      <span className="flex h-10 w-10 items-center justify-center rounded-xl bg-gray-100">
        <FaRegFileAlt className="h-5 w-5 text-gray-400" />
      </span>
      <p className="text-sm font-medium text-gray-900">
        No content ideas right now
      </p>
      <p className="max-w-xs text-xs text-gray-500">
        New ideas appear here after each visibility scan; your generated content
        is under View all.
      </p>
    </div>
  );
}
