import { searchSearxng, type SearxngSearchResult } from '@/lib/searxng';
import configManager from '@/lib/config';
import { getSearxngURL } from '@/lib/config/serverRegistry';

type Region = 'america' | 'eu' | 'russia' | 'china';
type Topic = 'tech' | 'finance' | 'art' | 'sports' | 'entertainment';

const SOURCES_BY_REGION: Record<
  Region,
  Record<Topic, { query: string[]; links: string[] }>
> = {
  america: {
    tech: {
      query: ['technology news', 'latest tech', 'AI', 'science and innovation'],
      links: ['techcrunch.com', 'wired.com', 'theverge.com', 'arstechnica.com'],
    },
    finance: {
      query: ['finance news', 'economy', 'stock market', 'investing'],
      links: ['bloomberg.com', 'cnbc.com', 'marketwatch.com', 'reuters.com'],
    },
    art: {
      query: ['art news', 'culture', 'modern art', 'cultural events'],
      links: ['artnews.com', 'hyperallergic.com', 'theartnewspaper.com'],
    },
    sports: {
      query: ['sports news', 'latest sports', 'cricket football tennis'],
      links: ['espn.com', 'cbssports.com', 'nfl.com', 'nba.com'],
    },
    entertainment: {
      query: ['entertainment news', 'movies', 'TV shows', 'celebrities'],
      links: ['hollywoodreporter.com', 'variety.com', 'deadline.com'],
    },
  },
  eu: {
    tech: {
      query: ['technology news', 'tech', 'AI', 'innovation'],
      links: ['techcrunch.com', 'bbc.com', 'theguardian.com', 'reuters.com', 'euronews.com'],
    },
    finance: {
      query: ['finance news', 'economy', 'stock market', 'euro'],
      links: ['reuters.com', 'ft.com', 'bbc.com', 'euronews.com', 'politico.eu'],
    },
    art: {
      query: ['art news', 'culture', 'art', 'exhibition'],
      links: ['theguardian.com', 'bbc.com', 'dw.com', 'france24.com'],
    },
    sports: {
      query: ['sports news', 'football', 'football soccer', 'champions league'],
      links: ['bbc.com/sport', 'skysports.com', 'uefa.com', 'eurosport.com'],
    },
    entertainment: {
      query: ['entertainment news', 'films', 'music', 'culture'],
      links: ['bbc.com', 'theguardian.com', 'euronews.com', 'dw.com'],
    },
  },
  russia: {
    tech: {
      query: ['technology news', 'tech', 'IT', 'innovation'],
      links: ['tass.com', 'ria.ru', 'interfax.com', 'kommersant.ru', 'vedomosti.ru'],
    },
    finance: {
      query: ['finance news', 'economy', 'markets', 'ruble'],
      links: ['tass.com', 'ria.ru', 'interfax.com', 'kommersant.ru', 'vedomosti.ru'],
    },
    art: {
      query: ['art news', 'culture', 'exhibition', 'museum'],
      links: ['tass.com', 'ria.ru', 'kommersant.ru', 'interfax.com'],
    },
    sports: {
      query: ['sports news', 'football', 'hockey', 'olympics'],
      links: ['tass.com', 'ria.ru', 'rsport.ria.ru', 'championat.com', 'sport-express.ru'],
    },
    entertainment: {
      query: ['entertainment news', 'films', 'music', 'culture'],
      links: ['tass.com', 'ria.ru', 'interfax.com', 'kommersant.ru'],
    },
  },
  china: {
    tech: {
      query: ['technology news', 'tech', 'AI', 'innovation'],
      links: ['scmp.com', 'xinhuanet.com', 'chinadaily.com.cn', 'reuters.com'],
    },
    finance: {
      query: ['finance news', 'economy', 'China markets', 'investing'],
      links: ['scmp.com', 'chinadaily.com.cn', 'reuters.com', 'bloomberg.com'],
    },
    art: {
      query: ['art news', 'culture', 'exhibition', 'Chinese art'],
      links: ['scmp.com', 'chinadaily.com.cn', 'xinhuanet.com'],
    },
    sports: {
      query: ['sports news', 'Olympics', 'football', 'basketball'],
      links: ['scmp.com', 'chinadaily.com.cn', 'xinhuanet.com'],
    },
    entertainment: {
      query: ['entertainment news', 'films', 'music', 'culture'],
      links: ['scmp.com', 'chinadaily.com.cn', 'variety.com'],
    },
  },
};

const COUNTRY_TO_REGION: Record<string, Region> = {
  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',
};

export const GET = async (req: Request) => {
  try {
    const searxngURL = getSearxngURL();
    if (!searxngURL?.trim()) {
      return Response.json(
        {
          message:
            'SearxNG is not configured. Please set the SearxNG URL in Settings → Search.',
        },
        { status: 503 },
      );
    }

    const params = new URL(req.url).searchParams;

    const mode: 'normal' | 'preview' =
      (params.get('mode') as 'normal' | 'preview') || 'normal';
    const topic: Topic = (params.get('topic') as Topic) || 'tech';
    const regionParam = params.get('region') as Region | null;

    let region: Region = 'america';
    const configRegion = configManager.getConfig('search.newsRegion', 'auto') as
      | Region
      | 'auto';

    if (configRegion !== 'auto' && ['america', 'eu', 'russia', 'china'].includes(configRegion)) {
      region = configRegion;
    } else if (regionParam && ['america', 'eu', 'russia', 'china'].includes(regionParam)) {
      region = regionParam;
    } else if (configRegion === 'auto') {
      try {
        const geoUrl =
          process.env.GEO_DEVICE_SERVICE_URL ?? 'http://localhost:4002';
        const geoRes = await fetch(`${geoUrl}/api/context`, {
          headers: {
            'x-forwarded-for': req.headers.get('x-forwarded-for') ?? '',
            'x-real-ip': req.headers.get('x-real-ip') ?? '',
            'user-agent': req.headers.get('user-agent') ?? '',
          },
        });
        const geoData = await geoRes.json();
        const cc = geoData?.geo?.countryCode;
        if (cc && COUNTRY_TO_REGION[cc]) {
          region = COUNTRY_TO_REGION[cc];
        }
      } catch {
        // keep default america
      }
    }

    const selectedTopic = SOURCES_BY_REGION[region][topic];

    const searchLang = region === 'russia' ? 'ru' : region === 'china' ? 'zh' : 'en';
    let data = [];

    if (mode === 'normal') {
      const seenUrls = new Set();

      const searchPromises = selectedTopic.links.flatMap((link) =>
        selectedTopic.query.map((query) =>
          searchSearxng(`site:${link} ${query}`, {
            engines: ['bing news'],
            pageno: 1,
            language: searchLang,
          }).then((r) => r.results),
        ),
      );
      const settled = await Promise.allSettled(searchPromises);
      const allResults = settled
        .filter((r): r is PromiseFulfilledResult<SearxngSearchResult[]> => r.status === 'fulfilled')
        .flatMap((r) => r.value);

      data = allResults
        .flat()
        .filter((item) => {
          const url = item.url?.toLowerCase().trim();
          if (seenUrls.has(url)) return false;
          seenUrls.add(url);
          return true;
        })
        .sort(() => Math.random() - 0.5);
    } else {
      data = (
        await searchSearxng(
          `site:${selectedTopic.links[Math.floor(Math.random() * selectedTopic.links.length)]} ${selectedTopic.query[Math.floor(Math.random() * selectedTopic.query.length)]}`,
          {
            engines: ['bing news'],
            pageno: 1,
            language: searchLang,
          },
        )
      ).results;
    }

    return Response.json(
      {
        blogs: data,
      },
      {
        status: 200,
      },
    );
  } catch (err) {
    const message =
      err instanceof Error ? err.message : 'An error has occurred';
    console.error(`Discover route error:`, err);
    return Response.json(
      {
        message:
          message.includes('fetch') || message.includes('ECONNREFUSED')
            ? 'Cannot connect to SearxNG. Check that it is running and the URL is correct in Settings.'
            : message,
      },
      { status: 500 },
    );
  }
};
