'use client';

import { Globe2Icon, Settings } from 'lucide-react';
import { useEffect, useState, useRef } from 'react';
import { toast } from 'sonner';
import { cn } from '@/lib/utils';
import SmallNewsCard from '@/components/Discover/SmallNewsCard';
import MajorNewsCard from '@/components/Discover/MajorNewsCard';
import DataFetchError from '@/components/DataFetchError';
import { fetchContextWithClient } from '@/lib/geoDevice';

const COUNTRY_TO_REGION: Record<string, string> = {
  US: 'america', CA: 'america', MX: 'america',
  RU: 'russia', BY: 'russia', KZ: 'russia',
  CN: 'china', HK: 'china', TW: 'china',
  DE: 'eu', FR: 'eu', IT: 'eu', ES: 'eu', GB: 'eu', UK: 'eu',
  NL: 'eu', PL: 'eu', BE: 'eu', AT: 'eu', PT: 'eu', SE: 'eu',
  FI: 'eu', IE: 'eu', GR: 'eu', RO: 'eu', CZ: 'eu', HU: 'eu',
  BG: 'eu', HR: 'eu', SK: 'eu', SI: 'eu', LT: 'eu', LV: 'eu', EE: 'eu', DK: 'eu',
};

const getRegionFromGeo = (countryCode: string | undefined): string | null => {
  if (!countryCode) return null;
  return COUNTRY_TO_REGION[countryCode] ?? null;
};

const fetchRegion = async (): Promise<string | null> => {
  let region: string | null = null;
  try {
    const ctx = await fetchContextWithClient();
    region = getRegionFromGeo(ctx.geo?.countryCode);
  } catch {
    // geo-context недоступен
  }
  if (!region) {
    try {
      const res = await fetch('https://get.geojs.io/v1/ip/geo.json');
      const d = await res.json();
      region = getRegionFromGeo(d?.country_code);
    } catch {
      // GeoJS недоступен
    }
  }
  return region;
};

export interface Discover {
  title: string;
  content: string;
  url: string;
  thumbnail: string;
}

const topics: { key: string; display: string }[] = [
  {
    display: 'GooSeek',
    key: 'gooseek',
  },
  {
    display: 'Tech & Science',
    key: 'tech',
  },
  {
    display: 'Finance',
    key: 'finance',
  },
  {
    display: 'Art & Culture',
    key: 'art',
  },
  {
    display: 'Sports',
    key: 'sports',
  },
  {
    display: 'Entertainment',
    key: 'entertainment',
  },
];

const FETCH_TIMEOUT_MS = 15000;

const Page = () => {
  const [discover, setDiscover] = useState<Discover[] | null>(null);
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState<string | null>(null);
  const [activeTopic, setActiveTopic] = useState<string>(topics[0].key);
  const [setupRequired, setSetupRequired] = useState(false);
  const regionPromiseRef = useRef<Promise<string | null> | null>(null);

  const getRegionPromise = (): Promise<string | null> => {
    if (!regionPromiseRef.current) {
      regionPromiseRef.current = fetchRegion();
    }
    return regionPromiseRef.current;
  };

  const fetchArticles = async (topic: string) => {
    setLoading(true);
    setError(null);
    setSetupRequired(false);
    try {
      const region = await getRegionPromise();
      const url = new URL('/api/v1/discover', window.location.origin);
      url.searchParams.set('topic', topic);
      if (region) url.searchParams.set('region', region);
      const res = await fetch(url.toString(), {
        method: 'GET',
        headers: { 'Content-Type': 'application/json' },
        signal: AbortSignal.timeout(FETCH_TIMEOUT_MS),
      });

      const data = await res.json();

      if (!res.ok) {
        throw new Error(data.message || 'Failed to load articles');
      }

      if (topic !== 'gooseek') {
        data.blogs = data.blogs.filter((blog: Discover) => blog.thumbnail);
      }

      setDiscover(data.blogs);
    } catch (err: unknown) {
      const message = err instanceof Error ? err.message : 'Error fetching data';
      if (message.includes('SearxNG is not configured')) {
        setSetupRequired(true);
        setDiscover(null);
      } else {
        setError(message.includes('timeout') || (err as Error)?.name === 'AbortError'
          ? 'Request timed out. Try again.'
          : message);
        toast.error(message);
      }
    } finally {
      setLoading(false);
    }
  };

  useEffect(() => {
    if (activeTopic === 'gooseek') {
      fetchArticles('gooseek');
      return;
    }
    fetchArticles(activeTopic);
  }, [activeTopic]);

  return (
    <>
      <div>
        <div className="flex flex-col pt-10 border-b border-light-200/20 dark:border-dark-200/20 pb-6 px-2">
          <div className="flex flex-col lg:flex-row lg:items-center lg:justify-between gap-4">
            <div className="flex items-center justify-center">
              <Globe2Icon size={45} className="mb-2.5" />
              <h1 className="text-5xl font-normal p-2">
                Discover
              </h1>
            </div>
            <div className="flex flex-row items-center space-x-2 overflow-x-auto">
              {topics.map((t, i) => (
                <div
                  key={i}
                  className={cn(
                    'border-[0.1px] rounded-full text-sm px-3 py-1 text-nowrap transition duration-200 cursor-pointer',
                    activeTopic === t.key
                      ? 'text-[#EA580C] bg-[#EA580C]/20 border-[#EA580C]/60 dark:bg-[#EA580C]/30 dark:border-[#EA580C]/40'
                      : 'border-black/30 dark:border-white/30 text-black/70 dark:text-white/70 hover:text-black dark:hover:text-white hover:border-black/40 dark:hover:border-white/40 hover:bg-black/5 dark:hover:bg-white/5',
                  )}
                  onClick={() => setActiveTopic(t.key)}
                >
                  <span>{t.display}</span>
                </div>
              ))}
            </div>
          </div>
        </div>

        {loading ? (
          <div className="flex flex-col gap-4 pb-28 pt-5 lg:pb-8 w-full">
            {/* Mobile: SmallNewsCard — rounded-3xl, aspect-video, p-4, h3 mb-2 + p */}
            <div className="block lg:hidden">
              <div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
                {[1, 2, 3, 4].map((i) => (
                  <div
                    key={i}
                    className="rounded-3xl overflow-hidden bg-light-secondary dark:bg-dark-secondary shadow-sm shadow-light-200/10 dark:shadow-black/25 flex flex-col"
                  >
                    <div className="relative aspect-video overflow-hidden bg-light-200 dark:bg-dark-200 animate-pulse" />
                    <div className="p-4">
                      <div className="h-4 w-full rounded bg-light-200 dark:bg-dark-200 animate-pulse mb-2" />
                      <div className="h-4 w-3/4 rounded bg-light-200 dark:bg-dark-200 animate-pulse mb-2" />
                      <div className="h-3 w-2/3 rounded bg-light-200 dark:bg-dark-200 animate-pulse" />
                      <div className="h-3 w-1/2 rounded bg-light-200 dark:bg-dark-200 animate-pulse mt-1" />
                    </div>
                  </div>
                ))}
              </div>
            </div>
            {/* Desktop: точно как реальный layout — 1st Major isLeft=false (текст слева, картинка справа) */}
            <div className="hidden lg:block space-y-0">
              {/* 1st MajorNewsCard isLeft=FALSE: content LEFT, image RIGHT */}
              <div className="w-full flex flex-row items-stretch gap-6 h-60 py-3">
                <div className="flex flex-col justify-center flex-1 py-4 space-y-3">
                  <div className="h-8 w-3/4 rounded bg-light-200 dark:bg-dark-200 animate-pulse" />
                  <div className="h-4 w-full rounded bg-light-200 dark:bg-dark-200 animate-pulse" />
                  <div className="h-4 w-3/4 rounded bg-light-200 dark:bg-dark-200 animate-pulse" />
                  <div className="h-4 w-1/2 rounded bg-light-200 dark:bg-dark-200 animate-pulse" />
                </div>
                <div className="relative w-80 h-full overflow-hidden rounded-2xl flex-shrink-0 bg-light-200 dark:bg-dark-200 animate-pulse" />
              </div>
              <hr className="border-t border-light-200/20 dark:border-dark-200/20 my-3 w-full" />
              {/* 3× SmallNewsCard */}
              <div className="grid lg:grid-cols-3 sm:grid-cols-2 grid-cols-1 gap-4">
                {[1, 2, 3].map((i) => (
                  <div
                    key={i}
                    className="rounded-3xl overflow-hidden bg-light-secondary dark:bg-dark-secondary shadow-sm shadow-light-200/10 dark:shadow-black/25 flex flex-col"
                  >
                    <div className="relative aspect-video overflow-hidden bg-light-200 dark:bg-dark-200 animate-pulse" />
                    <div className="p-4">
                      <div className="h-4 w-full rounded bg-light-200 dark:bg-dark-200 animate-pulse mb-2" />
                      <div className="h-4 w-3/4 rounded bg-light-200 dark:bg-dark-200 animate-pulse mb-2" />
                      <div className="h-3 w-2/3 rounded bg-light-200 dark:bg-dark-200 animate-pulse" />
                      <div className="h-3 w-1/2 rounded bg-light-200 dark:bg-dark-200 animate-pulse mt-1" />
                    </div>
                  </div>
                ))}
              </div>
              <hr className="border-t border-light-200/20 dark:border-dark-200/20 my-3 w-full" />
              {/* 2nd MajorNewsCard isLeft=TRUE: image LEFT, content RIGHT */}
              <div className="w-full flex flex-row items-stretch gap-6 h-60 py-3">
                <div className="relative w-80 h-full overflow-hidden rounded-2xl flex-shrink-0 bg-light-200 dark:bg-dark-200 animate-pulse" />
                <div className="flex flex-col justify-center flex-1 py-4 space-y-3">
                  <div className="h-8 w-2/3 rounded bg-light-200 dark:bg-dark-200 animate-pulse" />
                  <div className="h-4 w-full rounded bg-light-200 dark:bg-dark-200 animate-pulse" />
                  <div className="h-4 w-3/4 rounded bg-light-200 dark:bg-dark-200 animate-pulse" />
                </div>
              </div>
              <hr className="border-t border-light-200/20 dark:border-dark-200/20 my-3 w-full" />
              {/* 3rd MajorNewsCard isLeft=FALSE: content LEFT, image RIGHT */}
              <div className="w-full flex flex-row items-stretch gap-6 h-60 py-3">
                <div className="flex flex-col justify-center flex-1 py-4 space-y-3">
                  <div className="h-8 w-2/3 rounded bg-light-200 dark:bg-dark-200 animate-pulse" />
                  <div className="h-4 w-full rounded bg-light-200 dark:bg-dark-200 animate-pulse" />
                </div>
                <div className="relative w-80 h-full overflow-hidden rounded-2xl flex-shrink-0 bg-light-200 dark:bg-dark-200 animate-pulse" />
              </div>
              <hr className="border-t border-light-200/20 dark:border-dark-200/20 my-3 w-full" />
              {/* 3× SmallNewsCard */}
              <div className="grid lg:grid-cols-3 sm:grid-cols-2 grid-cols-1 gap-4">
                {[1, 2, 3].map((i) => (
                  <div
                    key={i}
                    className="rounded-3xl overflow-hidden bg-light-secondary dark:bg-dark-secondary shadow-sm shadow-light-200/10 dark:shadow-black/25 flex flex-col"
                  >
                    <div className="relative aspect-video overflow-hidden bg-light-200 dark:bg-dark-200 animate-pulse" />
                    <div className="p-4">
                      <div className="h-4 w-full rounded bg-light-200 dark:bg-dark-200 animate-pulse mb-2" />
                      <div className="h-4 w-3/4 rounded bg-light-200 dark:bg-dark-200 animate-pulse mb-2" />
                      <div className="h-3 w-2/3 rounded bg-light-200 dark:bg-dark-200 animate-pulse" />
                      <div className="h-3 w-1/2 rounded bg-light-200 dark:bg-dark-200 animate-pulse mt-1" />
                    </div>
                  </div>
                ))}
              </div>
            </div>
          </div>
        ) : error ? (
          <div className="pb-28 pt-5 lg:pb-8 px-4">
            <DataFetchError message={error} onRetry={() => fetchArticles(activeTopic)} />
          </div>
        ) : setupRequired ? (
          <div className="flex flex-col items-center justify-center min-h-[50vh] gap-4 px-4 text-center">
            <div className="rounded-full p-4 bg-[#EA580C]/10 dark:bg-[#EA580C]/5">
              <Settings size={48} className="text-[#EA580C]" />
            </div>
            <div>
              <p className="text-lg font-medium text-black dark:text-white">
                Configure SearxNG to discover articles
              </p>
              <p className="mt-2 text-sm text-black/60 dark:text-white/60 max-w-md">
                Open Settings (gear icon in the navbar), go to Search, and enter
                your SearxNG URL (e.g. http://localhost:8080)
              </p>
            </div>
          </div>
        ) : discover && discover.length > 0 ? (
          <div className="flex flex-col gap-4 pb-28 pt-5 lg:pb-8 w-full">
            <div className="block lg:hidden">
              <div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
                {discover?.map((item, i) => (
                  <SmallNewsCard key={`mobile-${i}`} item={item} />
                ))}
              </div>
            </div>

            <div className="hidden lg:block">
              {discover &&
                discover.length > 0 &&
                (() => {
                  const sections = [];
                  let index = 0;

                  while (index < discover.length) {
                    if (sections.length > 0) {
                      sections.push(
                        <hr
                          key={`sep-${index}`}
                          className="border-t border-light-200/20 dark:border-dark-200/20 my-3 w-full"
                        />,
                      );
                    }

                    if (index < discover.length) {
                      sections.push(
                        <MajorNewsCard
                          key={`major-${index}`}
                          item={discover[index]}
                          isLeft={false}
                        />,
                      );
                      index++;
                    }

                    if (index < discover.length) {
                      sections.push(
                        <hr
                          key={`sep-${index}-after`}
                          className="border-t border-light-200/20 dark:border-dark-200/20 my-3 w-full"
                        />,
                      );
                    }

                    if (index < discover.length) {
                      const smallCards = discover.slice(index, index + 3);
                      sections.push(
                        <div
                          key={`small-group-${index}`}
                          className="grid lg:grid-cols-3 sm:grid-cols-2 grid-cols-1 gap-4"
                        >
                          {smallCards.map((item, i) => (
                            <SmallNewsCard
                              key={`small-${index + i}`}
                              item={item}
                            />
                          ))}
                        </div>,
                      );
                      index += 3;
                    }

                    if (index < discover.length) {
                      sections.push(
                        <hr
                          key={`sep-${index}-after-small`}
                          className="border-t border-light-200/20 dark:border-dark-200/20 my-3 w-full"
                        />,
                      );
                    }

                    if (index < discover.length - 1) {
                      const twoMajorCards = discover.slice(index, index + 2);
                      twoMajorCards.forEach((item, i) => {
                        sections.push(
                          <MajorNewsCard
                            key={`double-${index + i}`}
                            item={item}
                            isLeft={i === 0}
                          />,
                        );
                        if (i === 0) {
                          sections.push(
                            <hr
                              key={`sep-double-${index + i}`}
                              className="border-t border-light-200/20 dark:border-dark-200/20 my-3 w-full"
                            />,
                          );
                        }
                      });
                      index += 2;
                    } else if (index < discover.length) {
                      sections.push(
                        <MajorNewsCard
                          key={`final-major-${index}`}
                          item={discover[index]}
                          isLeft={true}
                        />,
                      );
                      index++;
                    }

                    if (index < discover.length) {
                      sections.push(
                        <hr
                          key={`sep-${index}-after-major`}
                          className="border-t border-light-200/20 dark:border-dark-200/20 my-3 w-full"
                        />,
                      );
                    }

                    if (index < discover.length) {
                      const smallCards = discover.slice(index, index + 3);
                      sections.push(
                        <div
                          key={`small-group-2-${index}`}
                          className="grid lg:grid-cols-3 sm:grid-cols-2 grid-cols-1 gap-4"
                        >
                          {smallCards.map((item, i) => (
                            <SmallNewsCard
                              key={`small-2-${index + i}`}
                              item={item}
                            />
                          ))}
                        </div>,
                      );
                      index += 3;
                    }
                  }

                  return sections;
                })()}
            </div>
          </div>
        ) : discover && discover.length === 0 ? (
          <div className="flex flex-col items-center justify-center min-h-[40vh] px-4 text-center">
            <p className="text-black/60 dark:text-white/60 text-sm">
              No articles found for this topic.
            </p>
          </div>
        ) : null}
      </div>
    </>
  );
};

export default Page;
