import React, { useState, useRef, useEffect } from "react";
import { View, ScrollView, TouchableOpacity, Platform } from "react-native";
import { Text } from "~/components/ui/text";
import ScreenWrapper from "~/components/ui/ScreenWrapper";
import BackButton from "~/components/ui/backButton";
import BottomSheet from "~/components/ui/bottomSheet";
import { Button } from "~/components/ui/button";
import { router } from "expo-router";
import { ROUTES } from "~/lib/routes";
import * as Calendar from "expo-calendar";
import ModalToast from "~/components/ui/toast";
import Skeleton from "~/components/ui/skeleton";
import { collection, doc, FieldValue } from "~/lib/firebase";
import { useAuthWithProfile } from "~/lib/hooks/useAuthWithProfile";

type ScheduleStatus = "active" | "paused" | "stopped";

type Schedule = {
  id: string;
  recipientName: string;
  label: string;
  amount: string;
  currency: string;
  nextRunDate: string;
  nextRunLabel: string;
  frequency: string;
  status: ScheduleStatus;
};

const toISODate = (date: Date) => date.toISOString().split("T")[0];

const TODAY = new Date();

const addDays = (date: Date, days: number) => {
  const d = new Date(date);
  d.setDate(date.getDate() + days);
  return d;
};

const START_OF_WEEK = new Date(TODAY);
START_OF_WEEK.setDate(TODAY.getDate() - TODAY.getDay());

const WEEK_DAYS = Array.from({ length: 7 }).map((_, index) => {
  const day = new Date(START_OF_WEEK);
  day.setDate(START_OF_WEEK.getDate() + index);
  const labels = ["S", "M", "T", "W", "T", "F", "S"];
  return {
    key: toISODate(day),
    label: labels[day.getDay()],
    dateNumber: day.getDate(),
    isToday: day.toDateString() === TODAY.toDateString(),
  };
});

const MOCK_SCHEDULES: Schedule[] = [
  {
    id: "sch-1",
    recipientName: "Abebe Kebede",
    label: "Monthly support",
    amount: "4,500",
    currency: "ETB",
    nextRunDate: toISODate(TODAY),
    nextRunLabel: "Today · 4:00 PM",
    frequency: "Every month",
    status: "active",
  },
  {
    id: "sch-2",
    recipientName: "Sara Alemu",
    label: "Weekly allowance",
    amount: "1,000",
    currency: "ETB",
    nextRunDate: toISODate(addDays(TODAY, 1)),
    nextRunLabel: "Tomorrow · 9:00 AM",
    frequency: "Every week",
    status: "paused",
  },
  {
    id: "sch-3",
    recipientName: "Hope Community Fund",
    label: "Quarterly disbursement",
    amount: "32,000",
    currency: "ETB",
    nextRunDate: toISODate(addDays(TODAY, 2)),
    nextRunLabel: "In 2 days · 2:15 PM",
    frequency: "Every 3 months",
    status: "stopped",
  },
];

const getStatusPillClasses = (status: ScheduleStatus) => {
  switch (status) {
    case "active":
      return "bg-emerald-100 text-emerald-700";
    case "paused":
      return "bg-yellow-100 text-yellow-700";
    case "stopped":
    default:
      return "bg-gray-100 text-gray-600";
  }
};

const isSameDay = (a: Date, b: Date) =>
  a.getFullYear() === b.getFullYear() &&
  a.getMonth() === b.getMonth() &&
  a.getDate() === b.getDate();

const buildFrequencyLabel = (
  repeatType?: string,
  interval?: number
): string => {
  if (!repeatType || repeatType === "none") return "One-time";
  if (repeatType === "every_x_days" && interval) {
    return `Every ${interval} days`;
  }
  return repeatType;
};

const buildNextRunLabel = (dateValue?: any, time?: string): string => {
  if (!dateValue && !time) return "";

  const today = TODAY;
  const tomorrow = addDays(TODAY, 1);

  let dateObj: Date | null = null;

  if (dateValue instanceof Date) {
    dateObj = dateValue;
  } else if (typeof dateValue === "string") {
    const parsed = new Date(dateValue);
    if (!isNaN(parsed.getTime())) {
      dateObj = parsed;
    }
  }

  let dayLabel = "";
  if (dateObj) {
    if (isSameDay(dateObj, today)) dayLabel = "Today";
    else if (isSameDay(dateObj, tomorrow)) dayLabel = "Tomorrow";
    else {
      dayLabel = dateObj.toLocaleDateString(undefined, {
        year: "numeric",
        month: "short",
        day: "numeric",
      });
    }
  }

  if (dayLabel && time) return `${dayLabel} · ${time}`;
  return dayLabel || time || "";
};

const parseTimeFromLabel = (label: string) => {
  const parts = label.split("·");
  const rawTime = parts[1]?.trim();
  if (!rawTime) {
    return { hours: 9, minutes: 0 };
  }

  const match = rawTime.match(/(\d{1,2}):(\d{2})\s*(AM|PM)/i);
  if (!match) {
    return { hours: 9, minutes: 0 };
  }

  let hours = parseInt(match[1], 10);
  const minutes = parseInt(match[2], 10);
  const period = match[3].toUpperCase();

  if (period === "PM" && hours < 12) hours += 12;
  if (period === "AM" && hours === 12) hours = 0;

  return { hours, minutes };
};

const getDateTimesForSchedule = (schedule: Schedule) => {
  const [year, month, day] = schedule.nextRunDate
    .split("-")
    .map((v) => parseInt(v, 10));
  const { hours, minutes } = parseTimeFromLabel(schedule.nextRunLabel);

  const startDate = new Date(year, month - 1, day, hours, minutes);
  const endDate = new Date(startDate.getTime() + 60 * 60 * 1000);

  return { startDate, endDate };
};

const syncScheduleToCalendar = async (
  schedule: Schedule,
  showToast: (
    title: string,
    description?: string,
    variant?: "success" | "error" | "warning" | "info"
  ) => void
) => {
  try {
    const { status } = await Calendar.requestCalendarPermissionsAsync();
    if (status !== "granted") {
      showToast(
        "Calendar permission needed",
        "Allow calendar access to sync schedules.",
        "warning"
      );
      return;
    }

    let calendarId: string | null = null;

    if (Platform.OS === "ios") {
      const defaultCal = await Calendar.getDefaultCalendarAsync();
      calendarId = defaultCal?.id ?? null;
    } else {
      const calendars = await Calendar.getCalendarsAsync(
        Calendar.EntityTypes.EVENT
      );
      const editable = calendars.find(
        (c: Calendar.Calendar) => c.allowsModifications
      );
      calendarId = editable?.id ?? calendars[0]?.id ?? null;
    }

    if (!calendarId) {
      showToast(
        "No calendar found",
        "We couldn't find an editable calendar on this device.",
        "error"
      );
      return;
    }

    const { startDate, endDate } = getDateTimesForSchedule(schedule);

    await Calendar.createEventAsync(calendarId, {
      title: schedule.label || "Scheduled payment",
      notes: `${schedule.recipientName} • ${schedule.currency} ${schedule.amount}`,
      startDate,
      endDate,
      timeZone: undefined,
    });
    showToast(
      "Added to calendar",
      "This schedule was added as an event.",
      "success"
    );
  } catch (error) {
    console.warn("[Schedules] Failed to sync schedule to calendar", error);
    showToast(
      "Calendar error",
      "We couldn't add this schedule to your calendar.",
      "error"
    );
  }
};

export default function SchedulesScreen() {
  const [schedules, setSchedules] = useState<Schedule[]>([]);
  const [selected, setSelected] = useState<Schedule | null>(null);
  const [statusFilter, setStatusFilter] = useState<"all" | ScheduleStatus>(
    "all"
  );
  const [selectedDateKey, setSelectedDateKey] = useState<string>(
    WEEK_DAYS.find((d) => d.isToday)?.key || WEEK_DAYS[0].key
  );
  const [loading, setLoading] = useState(true);
  const [toastVisible, setToastVisible] = useState(false);
  const [toastTitle, setToastTitle] = useState("");
  const [toastDescription, setToastDescription] = useState<string | undefined>(
    undefined
  );
  const [toastVariant, setToastVariant] = useState<
    "success" | "error" | "warning" | "info"
  >("info");
  const toastTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);
  const { user } = useAuthWithProfile();

  useEffect(() => {
    const loadSchedules = async () => {
      if (!user?.uid) {
        setSchedules([]);
        setLoading(false);
        return;
      }

      try {
        setLoading(true);
        const appointmentsCol: any = collection("appointments");
        const snap = await appointmentsCol
          .where("agentId", "==", user.uid)
          .where("acceptance", "==", "accepted")
          .get();

        const loaded: Schedule[] = snap.docs.map((docSnap: any) => {
          const data = docSnap.data() || {};

          const nextRunSource =
            data.nextRunDate ||
            (data.date && data.time
              ? `${data.date}T${data.time}:00`
              : undefined);

          const nextRun = nextRunSource ? new Date(nextRunSource) : TODAY;
          const nextRunDateKey = toISODate(nextRun);
          const nextRunLabel = buildNextRunLabel(nextRun, data.time);

          const frequency = buildFrequencyLabel(data.repeatType, data.interval);

          const status: ScheduleStatus =
            data.scheduleStatus === "paused" ||
            data.scheduleStatus === "stopped"
              ? data.scheduleStatus
              : "active";

          return {
            id: String(docSnap.id),
            recipientName:
              data.fullName || data.email || data.phoneNumber || "Unknown",
            label: data.notes || "",
            amount:
              typeof data.amount === "number"
                ? data.amount.toString()
                : String(data.amount ?? ""),
            currency: "ETB",
            nextRunDate: nextRunDateKey,
            nextRunLabel,
            frequency,
            status,
          };
        });

        setSchedules(loaded);
      } catch (error) {
        console.error(
          "[Schedules] Failed to load appointments as schedules",
          error
        );
      } finally {
        setLoading(false);
      }
    };

    loadSchedules();
  }, [user]);

  const showToast = (
    title: string,
    description?: string,
    variant: "success" | "error" | "warning" | "info" = "info"
  ) => {
    if (toastTimeoutRef.current) {
      clearTimeout(toastTimeoutRef.current);
    }

    setToastTitle(title);
    setToastDescription(description);
    setToastVariant(variant);
    setToastVisible(true);

    toastTimeoutRef.current = setTimeout(() => {
      setToastVisible(false);
      toastTimeoutRef.current = null;
    }, 2500);
  };

  const handleUpdateStatus = async (id: string, next: ScheduleStatus) => {
    try {
      const ref = doc("appointments", id);
      await ref.update({
        scheduleStatus: next,
        updatedAt: FieldValue.serverTimestamp(),
      });

      setSchedules((prev) =>
        prev.map((sch) => (sch.id === id ? { ...sch, status: next } : sch))
      );
      setSelected((prev) =>
        prev && prev.id === id ? { ...prev, status: next } : prev
      );
    } catch (error) {
      console.error("[Schedules] Failed to update scheduleStatus", id, error);
    }
  };

  const activeCount = schedules.filter((s) => s.status === "active").length;
  const pausedCount = schedules.filter((s) => s.status === "paused").length;
  const stoppedCount = schedules.filter((s) => s.status === "stopped").length;

  const dateFiltered = schedules.filter(
    (s) => s.nextRunDate === selectedDateKey
  );

  const filteredSchedules =
    statusFilter === "all"
      ? dateFiltered
      : dateFiltered.filter((s) => s.status === statusFilter);

  return (
    <ScreenWrapper edges={[]}>
      <BackButton />
      <View className="flex-1 bg-white">
        <ScrollView
          className="flex-1"
          contentContainerStyle={{ paddingBottom: 32 }}
          showsVerticalScrollIndicator={false}
        >
          <View className="px-5 pt-4">
            <Text className="text-lg font-dmsans-bold text-primary mb-1">
              Schedules
            </Text>
            <Text className="text-sm font-dmsans text-gray-500 mb-4">
              View and manage your recurring payment schedules.
            </Text>

            {/* Week day selector */}
            <ScrollView
              horizontal
              showsHorizontalScrollIndicator={false}
              className="mb-4 -mx-1"
              contentContainerStyle={{ paddingHorizontal: 4 }}
            >
              {WEEK_DAYS.map((day) => {
                const isSelected = day.key === selectedDateKey;
                const hasSchedulesForDay = schedules.some(
                  (s) => s.nextRunDate === day.key
                );

                return (
                  <TouchableOpacity
                    key={day.key}
                    activeOpacity={0.8}
                    className={`mx-1 px-3 py-2 rounded-2xl border items-center justify-center min-w-[44px] ${
                      isSelected
                        ? "bg-primary/10 border-primary"
                        : "bg-white border-gray-200"
                    }`}
                    onPress={() => setSelectedDateKey(day.key)}
                  >
                    <Text
                      className={`text-[11px] font-dmsans-medium mb-0.5 ${
                        isSelected ? "text-primary" : "text-gray-600"
                      }`}
                    >
                      {day.label}
                    </Text>
                    <Text
                      className={`text-[11px] font-dmsans ${
                        isSelected ? "text-primary" : "text-gray-800"
                      }`}
                    >
                      {day.dateNumber}
                    </Text>
                    <View className="mt-1 h-1.5 items-center justify-center">
                      {hasSchedulesForDay && (
                        <View className="w-1.5 h-1.5 rounded-full bg-primary" />
                      )}
                    </View>
                  </TouchableOpacity>
                );
              })}
            </ScrollView>
            {loading && (
              <View className="mb-6">
                {[1, 2, 3].map((i) => (
                  <View key={i} className="py-2">
                    <Skeleton width="100%" height={120} radius={24} />
                  </View>
                ))}
              </View>
            )}

            {!loading && filteredSchedules.length === 0 && (
              <View className="items-center justify-center py-10">
                <Text className="text-sm font-dmsans text-gray-400">
                  No schedules match your filters.
                </Text>
              </View>
            )}

            {!loading && filteredSchedules.length > 0 && (
              <View className="space-y-4 mb-6">
                {filteredSchedules.map((sch) => {
                  return (
                    <View
                      key={sch.id}
                      className="bg-white rounded-3xl mb-2 border border-gray-100"
                      style={{
                        shadowColor: "#000",
                        shadowOpacity: 0.02,
                        shadowRadius: 40,
                        shadowOffset: { width: 0, height: 8 },
                        elevation: 2,
                      }}
                    >
                      <View className="px-4 py-4">
                        <View className="flex-row items-center justify-between mb-1.5">
                          <View className="flex-1 mr-2">
                            <Text className="text-base font-dmsans-bold text-gray-900">
                              {sch.recipientName}
                            </Text>
                            <Text className="text-[12px] font-dmsans text-gray-500">
                              {sch.label}
                            </Text>
                          </View>
                        </View>

                        <View className="flex-row items-center justify-between mt-2 mb-2">
                          <View>
                            <Text className="text-[11px] font-dmsans text-gray-500">
                              Next run
                            </Text>
                            <Text className="text-[12px] font-dmsans-medium text-gray-900">
                              {sch.nextRunLabel}
                            </Text>
                          </View>
                          <View className="items-end">
                            <Text className="text-[11px] font-dmsans text-gray-500">
                              Amount
                            </Text>
                            <Text className="text-sm font-dmsans-bold text-gray-900">
                              {sch.currency} {sch.amount}
                            </Text>
                          </View>
                        </View>

                        <View className="flex-row items-center justify-between mt-1">
                          <View>
                            <Text className="text-[11px] font-dmsans text-gray-500">
                              Frequency
                            </Text>
                            <Text className="text-[12px] font-dmsans-medium text-gray-900">
                              {sch.frequency}
                            </Text>
                          </View>
                          <View className="flex-row gap-2">
                            <TouchableOpacity
                              activeOpacity={0.9}
                              className="px-3 py-1.5 rounded-2xl border border-gray-200 bg-white"
                              onPress={() => setSelected(sch)}
                            >
                              <Text className="text-[11px] font-dmsans-medium text-gray-800">
                                View details
                              </Text>
                            </TouchableOpacity>
                          </View>
                        </View>
                      </View>
                    </View>
                  );
                })}
              </View>
            )}

            <Button
              className="mt-1 mb-6 bg-white border border-gray-200 rounded-2xl h-11"
              onPress={() => router.push(ROUTES.SCHEDULES_ALL)}
            >
              <Text className="text-sm font-dmsans-medium text-gray-800">
                View all schedules
              </Text>
            </Button>
          </View>
        </ScrollView>
      </View>
      <BottomSheet
        visible={!!selected}
        onClose={() => setSelected(null)}
        maxHeightRatio={0.45}
      >
        {selected && (
          <View className="w-full  pt-4 pb-6">
            <Text className="text-base font-dmsans-bold text-primary mb-2 text-center">
              Schedule Details
            </Text>
            <Text className="text-lg font-dmsans-bold text-gray-900 text-center mb-1">
              {selected.recipientName}
            </Text>
            <Text className="text-[12px] font-dmsans text-gray-500 text-center mb-3">
              {selected.label}
            </Text>

            <View className="space-y-2 mb-5">
              <View className="flex-row justify-between">
                <Text className="text-[12px] font-dmsans text-gray-500">
                  Next run
                </Text>
                <Text className="text-[12px] font-dmsans-medium text-gray-900">
                  {selected.nextRunLabel}
                </Text>
              </View>
              <View className="flex-row justify-between">
                <Text className="text-[12px] font-dmsans text-gray-500">
                  Amount
                </Text>
                <Text className="text-[12px] font-dmsans-medium text-gray-900">
                  {selected.currency} {selected.amount}
                </Text>
              </View>
              <View className="flex-row justify-between">
                <Text className="text-[12px] font-dmsans text-gray-500">
                  Frequency
                </Text>
                <Text className="text-[12px] font-dmsans-medium text-gray-900">
                  {selected.frequency}
                </Text>
              </View>
            </View>

            <View className="flex-row gap-3 mt-2">
              <TouchableOpacity
                activeOpacity={0.8}
                className="flex-1 bg-primary rounded-2xl py-3 items-center justify-center"
                onPress={() => router.push(ROUTES.SEND_OR_REQUEST_MONEY)}
              >
                <Text className="text-sm font-dmsans-medium text-white">
                  Pay now
                </Text>
              </TouchableOpacity>
            </View>

            <Button
              className="mt-4 bg-primary/10 border border-primary/30 rounded-2xl h-11"
              onPress={() => syncScheduleToCalendar(selected, showToast)}
            >
              <Text className="text-sm font-dmsans-medium text-primary">
                Sync this schedule to calendar
              </Text>
            </Button>
          </View>
        )}
      </BottomSheet>
      <ModalToast
        visible={toastVisible}
        title={toastTitle}
        description={toastDescription}
        variant={toastVariant}
      />
    </ScreenWrapper>
  );
}
