import React, { useCallback, useEffect, useState } from 'react';
import { View, Text, ScrollView, RefreshControl, StyleSheet } from 'react-native';
import { useSafeAreaInsets } from 'react-native-safe-area-context';
import type { PostSummary } from '@ai-radar/shared';
import { useTheme } from '../theme/ThemeProvider';
import { textStyle, space } from '../theme';
import { getDict } from '../lib/dictionary';
import { getHome, ApiError, type HomePayload } from '../lib/api';
import { longDate } from '../lib/format';
import { StoryCard } from '../components/StoryCard';
import { Loading, ErrorState, EmptyState } from '../components/States';
import { SectionHeading } from '../components/SectionHeading';

/**
 * Today.
 *
 * The daily digest, in the same hierarchy the website leads with: one
 * hero, then what else was important, then the rest as a scan list.
 *
 * This screen is the whole promise — "5 minutes to know what changed" —
 * so it deliberately ends. There is no infinite scroll: running out of
 * stories is the product telling you that you are done.
 */
export function TodayScreen({ onOpen }: { onOpen: (post: PostSummary) => void }) {
  const { palette, locale, rtl } = useTheme();
  const dict = getDict(locale);
  const insets = useSafeAreaInsets();

  const [data, setData] = useState<HomePayload | null>(null);
  const [error, setError] = useState<string | null>(null);
  const [loading, setLoading] = useState(true);
  const [refreshing, setRefreshing] = useState(false);

  const load = useCallback(
    async (mode: 'initial' | 'refresh') => {
      if (mode === 'refresh') setRefreshing(true);
      else setLoading(true);
      setError(null);

      try {
        setData(await getHome(locale));
      } catch (err) {
        setError(err instanceof ApiError ? err.message : 'Something went wrong.');
      } finally {
        setLoading(false);
        setRefreshing(false);
      }
    },
    [locale],
  );

  useEffect(() => {
    void load('initial');
  }, [load]);

  if (loading) return <Loading />;
  if (error && !data) return <ErrorState message={error} onRetry={() => void load('initial')} />;
  if (!data) return null;

  const align = rtl ? ('right' as const) : ('left' as const);
  const dir = rtl ? ('rtl' as const) : ('ltr' as const);

  // The API's lists overlap by design — the same story is both the most
  // important thing today and worth trying. Showing it twice makes a
  // short day look padded, which is the opposite of the promise, so each
  // story appears once, in the highest position it earned.
  const shown = new Set<string>();
  const unseen = (posts: PostSummary[]) =>
    posts.filter((p) => {
      if (shown.has(p.slug)) return false;
      shown.add(p.slug);
      return true;
    });

  if (data.hero) shown.add(data.hero.slug);
  const important = unseen(data.important);
  const worthTrying = unseen(data.worthTrying);
  const rest = unseen([...data.models, ...data.tools, ...data.updates, ...data.pricing]);

  const quiet =
    !data.hero && important.length === 0 && worthTrying.length === 0 && rest.length === 0;

  return (
    <ScrollView
      style={{ backgroundColor: palette.bg }}
      contentContainerStyle={[
        styles.content,
        { paddingBottom: insets.bottom + space.s10 },
      ]}
      refreshControl={
        <RefreshControl
          refreshing={refreshing}
          onRefresh={() => void load('refresh')}
          tintColor={palette.accent}
          colors={[palette.accent]}
        />
      }
    >
      <View style={styles.header}>
        <Text
          style={[
            textStyle('meta', locale),
            { color: palette.text3, textAlign: align, writingDirection: dir },
          ]}
        >
          {longDate(data.date, locale).toUpperCase()}
        </Text>
        <Text
          style={[
            textStyle('display', locale),
            { color: palette.text, textAlign: align, writingDirection: dir, marginTop: space.s1 },
          ]}
        >
          {dict.today}
        </Text>
        <Text
          style={[
            textStyle('bodySm', locale),
            { color: palette.text2, textAlign: align, writingDirection: dir, marginTop: space.s1 },
          ]}
        >
          {dict.storiesCount(data.totalPublished)}
        </Text>
      </View>

      {quiet ? (
        <EmptyState title={dict.quietTitle} body={dict.quietBody} />
      ) : (
        <>
          {(data.hero || important.length > 0) && (
            <View style={styles.block}>
              <SectionHeading title={dict.importantToday} />
              {data.hero && <StoryCard post={data.hero} variant="hero" onPress={onOpen} />}
              {important.map((post, i) => (
                <View
                  key={post.slug}
                  // No gap above the first card when there is no hero
                  // above it to separate from.
                  style={{ marginTop: !data.hero && i === 0 ? 0 : space.s3 }}
                >
                  <StoryCard post={post} variant="standard" onPress={onOpen} />
                </View>
              ))}
            </View>
          )}

          {worthTrying.length > 0 && (
            <View style={styles.block}>
              <SectionHeading title={dict.worthTrying} />
              {worthTrying.map((post) => (
                <StoryCard key={post.slug} post={post} variant="row" onPress={onOpen} />
              ))}
            </View>
          )}

          {rest.length > 0 && (
            <View style={styles.block}>
              <SectionHeading title={dict.alsoToday} />
              {rest.map((post) => (
                <StoryCard key={post.slug} post={post} variant="row" onPress={onOpen} />
              ))}
            </View>
          )}

          {/* The end of the day's news, said plainly. */}
          <Text
            style={[
              textStyle('meta', locale),
              { color: palette.text3, textAlign: 'center', marginTop: space.s8 },
            ]}
          >
            {dict.promise}
          </Text>
        </>
      )}
    </ScrollView>
  );
}

const styles = StyleSheet.create({
  content: {
    paddingHorizontal: space.s4,
    paddingTop: space.s4,
  },
  header: {
    marginBottom: space.s6,
  },
  block: {
    marginBottom: space.section,
  },
});
