import { Feather } from "@expo/vector-icons";
import DateTimePicker from "@react-native-community/datetimepicker";
import { useQuery, useQueryClient } from "@tanstack/react-query";
import AsyncStorage from "@react-native-async-storage/async-storage";
import * as Clipboard from "expo-clipboard";
import * as Haptics from "expo-haptics";
import { useRouter } from "expo-router";
import React, { useEffect, useMemo, useState } from "react";
import {
  ActivityIndicator,
  Alert,
  FlatList,
  Platform,
  RefreshControl,
  StyleSheet,
  Text,
  TouchableOpacity,
  View,
} from "react-native";
import { useSafeAreaInsets } from "react-native-safe-area-context";
import { PostCard } from "@/components/PostCard";
import { PostizPost, usePostiz } from "@/context/PostizContext";
import { useColors } from "@/hooks/useColors";
import { extractError } from "@/lib/extractError";

const SORT_STORAGE_KEY = "postiz_posts_sort";

type FilterType = "all" | "QUEUE" | "PUBLISHED" | "ERROR" | "DRAFT";

const FILTERS: { key: FilterType; label: string }[] = [
  { key: "all", label: "All" },
  { key: "QUEUE", label: "Queue" },
  { key: "PUBLISHED", label: "Published" },
  { key: "DRAFT", label: "Draft" },
  { key: "ERROR", label: "Error" },
];

export default function PostsScreen() {
  const colors = useColors();
  const insets = useSafeAreaInsets();
  const { client, isConfigured } = usePostiz();
  const queryClient = useQueryClient();
  const router = useRouter();
  const [filter, setFilter] = useState<FilterType>("all");
  const [sortOrder, setSortOrder] = useState<"desc" | "asc">("desc");
  const [refreshing, setRefreshing] = useState(false);
  const [copyToast, setCopyToast] = useState(false);

  useEffect(() => {
    AsyncStorage.getItem(SORT_STORAGE_KEY).then((v) => {
      if (v === "asc" || v === "desc") setSortOrder(v);
    });
  }, []);

  const toggleSort = () => {
    const next = sortOrder === "desc" ? "asc" : "desc";
    setSortOrder(next);
    AsyncStorage.setItem(SORT_STORAGE_KEY, next);
  };

  // reschedule state
  const [reschedulePost, setReschedulePost] = useState<PostizPost | null>(null);
  const [rescheduleDate, setRescheduleDate] = useState(new Date());
  const [rescheduleStep, setRescheduleStep] = useState<"date" | "time" | null>(null);

  const { startDate, endDate } = useMemo(() => {
    const s = new Date();
    s.setMonth(s.getMonth() - 3);
    const e = new Date();
    e.setMonth(e.getMonth() + 6);
    return { startDate: s.toISOString(), endDate: e.toISOString() };
  }, []);

  const { data: posts, isLoading, error, refetch } = useQuery<PostizPost[]>({
    queryKey: ["posts-list", !!client, startDate, endDate],
    queryFn: async () => {
      if (!client) return [];
      const res = await client.get("posts", {
        params: { startDate, endDate },
      });
      return Array.isArray(res.data) ? res.data : res.data?.posts ?? [];
    },
    enabled: !!client,
    retry: 1,
    staleTime: 0,
  });

  const filteredPosts = useMemo(() => {
    const list =
      filter === "all"
        ? posts ?? []
        : (posts ?? []).filter((p) => p.state === filter);
    return [...list].sort((a, b) => {
      const diff = new Date(a.publishDate).getTime() - new Date(b.publishDate).getTime();
      return sortOrder === "desc" ? -diff : diff;
    });
  }, [posts, filter, sortOrder]);

  const filterCounts = useMemo(() => {
    const all = posts ?? [];
    return {
      all: all.length,
      QUEUE: all.filter((p) => p.state === "QUEUE").length,
      PUBLISHED: all.filter((p) => p.state === "PUBLISHED").length,
      DRAFT: all.filter((p) => p.state === "DRAFT").length,
      ERROR: all.filter((p) => p.state === "ERROR").length,
    };
  }, [posts]);

  const handleRefresh = async () => {
    setRefreshing(true);
    await refetch();
    setRefreshing(false);
  };

  const handleDelete = async (id: string) => {
    if (!client) return;
    try {
      await client.delete(`posts/${id}`);
      queryClient.invalidateQueries({ queryKey: ["posts-list"] });
      queryClient.invalidateQueries({ queryKey: ["posts"] });
    } catch (e: unknown) {
      const msg = extractError(e);
      Alert.alert("Delete failed", msg);
    }
  };

  const handleRetry = async (post: PostizPost) => {
    if (!client) return;
    const integrations = post.integrations ?? (post.integration ? [post.integration] : []);
    try {
      const payload = {
        type: "now",
        date: new Date().toISOString(),
        shortLink: false,
        tags: [] as string[],
        posts: integrations.map((intg) => ({
          integration: { id: intg.id },
          value: [{ content: post.content, id: "", image: post.image ?? [] }],
        })),
      };
      await client.post("posts", payload);
      Haptics.notificationAsync(Haptics.NotificationFeedbackType.Success);
      queryClient.invalidateQueries({ queryKey: ["posts-list"] });
      Alert.alert("Retried", "Post submitted again.");
    } catch (e: unknown) {
      const msg = extractError(e);
      Alert.alert("Retry failed", msg);
    }
  };

  const handlePrefillCompose = (post: PostizPost) => {
    const integrations = post.integrations ?? (post.integration ? [post.integration] : []);
    router.push({
      pathname: "/(tabs)/compose",
      params: {
        prefillContent: post.content,
        prefillIntegrationIds: integrations.map((i) => i.id).join(","),
      },
    });
  };

  const startReschedule = (post: PostizPost) => {
    setReschedulePost(post);
    setRescheduleDate(new Date(post.publishDate));
    setRescheduleStep("date");
  };

  const submitReschedule = async (post: PostizPost, date: Date) => {
    if (!client) return;
    const integrations = post.integrations ?? (post.integration ? [post.integration] : []);
    try {
      await client.delete(`posts/${post.id}`);
      await client.post("posts", {
        type: "schedule",
        date: date.toISOString(),
        shortLink: false,
        tags: [] as string[],
        posts: integrations.map((intg) => ({
          integration: { id: intg.id },
          value: [{ content: post.content, image: post.image ?? [] }],
        })),
      });
      queryClient.invalidateQueries({ queryKey: ["posts-list"] });
      Haptics.notificationAsync(Haptics.NotificationFeedbackType.Success);
      Alert.alert("Rescheduled", `Post moved to ${date.toLocaleDateString("en-US", { month: "short", day: "numeric", hour: "2-digit", minute: "2-digit" })}`);
    } catch (e: unknown) {
      const msg = extractError(e);
      Alert.alert("Reschedule failed", msg);
    }
  };

  const showContextMenu = (post: PostizPost) => {
    Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Medium);

    const preview = post.content.slice(0, 60) + (post.content.length > 60 ? "…" : "");

    const buttons: Array<{ text: string; style?: "cancel" | "destructive" | "default"; onPress?: () => void }> = [];

    buttons.push({
      text: "Copy text",
      onPress: async () => {
        await Clipboard.setStringAsync(post.content);
        Haptics.notificationAsync(Haptics.NotificationFeedbackType.Success);
        setCopyToast(true);
        setTimeout(() => setCopyToast(false), 2000);
      },
    });

    if (post.state === "ERROR") {
      if (post.errorMessage) {
        buttons.push({
          text: "View error",
          onPress: () => Alert.alert("Error details", post.errorMessage),
        });
      }
      buttons.push({ text: "Retry now", onPress: () => handleRetry(post) });
      buttons.push({ text: "Edit & retry", onPress: () => handlePrefillCompose(post) });
    } else if (post.state === "QUEUE") {
      buttons.push({ text: "Edit", onPress: () => handlePrefillCompose(post) });
      buttons.push({ text: "Reschedule", onPress: () => startReschedule(post) });
    } else if (post.state === "PUBLISHED") {
      buttons.push({ text: "Repost", onPress: () => handlePrefillCompose(post) });
    } else if (post.state === "DRAFT") {
      buttons.push({ text: "Edit & schedule", onPress: () => handlePrefillCompose(post) });
    }

    buttons.push({ text: "Cancel", style: "cancel" });

    Alert.alert(
      post.state === "ERROR" ? "Failed post" :
      post.state === "QUEUE" ? "Scheduled post" :
      post.state === "PUBLISHED" ? "Published post" : "Draft",
      preview,
      buttons
    );
  };

  if (!isConfigured) {
    return (
      <View
        style={[
          styles.centered,
          { backgroundColor: colors.background, paddingTop: Platform.OS === "web" ? 67 : 0 },
        ]}
      >
        <Feather name="lock" size={32} color={colors.mutedForeground} />
        <Text style={[styles.emptyTitle, { color: colors.foreground }]}>
          Not Configured
        </Text>
        <Text style={[styles.emptyText, { color: colors.mutedForeground }]}>
          Add your API key in Settings
        </Text>
      </View>
    );
  }

  return (
    <View
      style={[
        styles.container,
        {
          backgroundColor: colors.background,
          paddingTop: Platform.OS === "web" ? 67 : 0,
        },
      ]}
    >
      <View style={[styles.filterRow, { borderBottomColor: colors.border }]}>
        <FlatList
          horizontal
          data={FILTERS}
          keyExtractor={(item) => item.key}
          showsHorizontalScrollIndicator={false}
          contentContainerStyle={styles.filterList}
          renderItem={({ item }) => {
            const count = posts ? filterCounts[item.key] : undefined;
            const active = filter === item.key;
            return (
              <TouchableOpacity
                onPress={() => setFilter(item.key)}
                activeOpacity={0.7}
                style={[
                  styles.filterChip,
                  {
                    backgroundColor: active ? colors.primary : colors.secondary,
                    borderColor: active ? colors.primary : colors.border,
                  },
                ]}
              >
                <Text
                  style={[
                    styles.filterText,
                    { color: active ? colors.primaryForeground : colors.mutedForeground },
                  ]}
                >
                  {item.label}
                  {count !== undefined && count > 0 ? ` ${count}` : ""}
                </Text>
              </TouchableOpacity>
            );
          }}
          style={styles.filterBar}
        />
        <TouchableOpacity
          onPress={toggleSort}
          activeOpacity={0.7}
          style={[styles.sortBtn, { borderColor: colors.border, backgroundColor: colors.secondary }]}
        >
          <Feather
            name={sortOrder === "desc" ? "arrow-down" : "arrow-up"}
            size={14}
            color={colors.mutedForeground}
          />
        </TouchableOpacity>
      </View>

      {copyToast && (
        <View style={[styles.toast, { backgroundColor: colors.success }]}>
          <Feather name="check" size={13} color="#fff" />
          <Text style={styles.toastText}>Copied</Text>
        </View>
      )}

      {isLoading ? (
        <View style={styles.centered}>
          <ActivityIndicator color={colors.primary} size="large" />
        </View>
      ) : error ? (
        <View style={styles.centered}>
          <Feather name="alert-circle" size={28} color={colors.error} />
          <Text style={[styles.emptyTitle, { color: colors.foreground }]}>
            Failed to load
          </Text>
          <Text style={[styles.emptyText, { color: colors.mutedForeground }]} selectable>
            {extractError(error)}
          </Text>
          <TouchableOpacity
            onPress={() => refetch()}
            style={[styles.retryBtn, { backgroundColor: colors.primary }]}
          >
            <Text style={[styles.retryText, { color: colors.primaryForeground }]}>
              Try Again
            </Text>
          </TouchableOpacity>
        </View>
      ) : (
        <FlatList
          data={filteredPosts}
          keyExtractor={(item) => item.id}
          renderItem={({ item }) => (
            <PostCard
              post={item}
              onDelete={handleDelete}
              onLongPress={showContextMenu}
              onReschedule={startReschedule}
            />
          )}
          refreshControl={
            <RefreshControl
              refreshing={refreshing}
              onRefresh={handleRefresh}
              tintColor={colors.primary}
            />
          }
          contentInsetAdjustmentBehavior="automatic"
          showsVerticalScrollIndicator={false}
          ListEmptyComponent={
            <View style={styles.emptyState}>
              <Feather name="inbox" size={36} color={colors.mutedForeground} />
              <Text style={[styles.emptyTitle, { color: colors.foreground }]}>
                No posts
              </Text>
              <Text style={[styles.emptyText, { color: colors.mutedForeground }]}>
                {filter === "all"
                  ? "No posts found in the last 3 months"
                  : `No ${filter.toLowerCase()} posts`}
              </Text>
            </View>
          }
          scrollEnabled={filteredPosts.length > 0}
        />
      )}

      {rescheduleStep !== null && reschedulePost !== null && (
        <DateTimePicker
          value={rescheduleDate}
          mode={rescheduleStep}
          display="default"
          minimumDate={rescheduleStep === "date" ? new Date() : undefined}
          textColor={colors.foreground}
          accentColor={colors.primary}
          onChange={(_: unknown, date?: Date) => {
            if (!date) {
              setRescheduleStep(null);
              setReschedulePost(null);
              return;
            }
            if (rescheduleStep === "date") {
              const merged = new Date(rescheduleDate);
              merged.setFullYear(date.getFullYear(), date.getMonth(), date.getDate());
              setRescheduleDate(merged);
              setRescheduleStep("time");
            } else {
              const merged = new Date(rescheduleDate);
              merged.setHours(date.getHours(), date.getMinutes());
              const post = reschedulePost;
              setRescheduleStep(null);
              setReschedulePost(null);
              submitReschedule(post, merged);
            }
          }}
        />
      )}
    </View>
  );
}

const styles = StyleSheet.create({
  container: { flex: 1 },
  centered: {
    flex: 1,
    alignItems: "center",
    justifyContent: "center",
    gap: 10,
    paddingHorizontal: 32,
  },
  filterRow: { flexDirection: "row", alignItems: "center", borderBottomWidth: StyleSheet.hairlineWidth },
  filterBar: { flex: 1 },
  filterList: { paddingHorizontal: 16, paddingVertical: 10, gap: 8 },
  filterChip: { paddingHorizontal: 14, paddingVertical: 6, borderRadius: 20, borderWidth: 1 },
  sortBtn: { marginRight: 12, padding: 7, borderRadius: 8, borderWidth: 1 },
  filterText: { fontSize: 13, fontFamily: "Inter_500Medium" },
  emptyState: { alignItems: "center", paddingTop: 64, gap: 10 },
  emptyTitle: { fontSize: 18, fontFamily: "Inter_600SemiBold" },
  emptyText: { fontSize: 14, fontFamily: "Inter_400Regular", textAlign: "center" },
  retryBtn: { marginTop: 4, paddingHorizontal: 20, paddingVertical: 10, borderRadius: 10 },
  retryText: { fontSize: 14, fontFamily: "Inter_600SemiBold" },
  toast: {
    position: "absolute",
    bottom: 100,
    alignSelf: "center",
    flexDirection: "row",
    alignItems: "center",
    gap: 6,
    paddingHorizontal: 14,
    paddingVertical: 8,
    borderRadius: 20,
    zIndex: 999,
  },
  toastText: { fontSize: 13, fontFamily: "Inter_600SemiBold", color: "#fff" },
});
