import React, {
  createContext,
  useContext,
  useState,
  useCallback,
  useEffect
} from "react";
import { useRequest } from "@/components/App/request";
import { useApp } from "@/components/App";
import moment from "moment";
import { debounce } from "@/utils/helpers";

interface Area {
  code: string;
  id: number;
}

interface AreaResponse {
  code: string;
  id: number;
}

interface Lead {
  date: string;
  total_leads: number;
}

interface LeadResponse {
  member_id: number;
  filter: string;
  leads: Lead[];
  start_date: string;
  end_date: string;
}

interface GraphContextType {
  // State
  search: string;
  selectedArea: (number | string)[];
  subscribedArea: AreaResponse[];
  selectedFilter: string;
  dateRange: {
    startDate: string;
    endDate: string;
  };
  area: AreaResponse[] | null;
  leadData: LeadResponse | null;

  // Actions
  setSearch: (value: string) => void;
  setSelectedArea: (areas: (number | string)[]) => void;
  setSelectedFilter: (filter: string) => void;
  setDateRange: (range: {
    startDate: string;
    endDate: string;
  }) => void;
  handleSetSelArr: (arr: (number | string)[]) => void;
  debouncedSearch: (value: string) => void;
}

const GraphContext = createContext<GraphContextType | undefined>(undefined);

export const GraphProvider: React.FC<{ children: React.ReactNode }> = ({
  children
}) => {
  const { userDetail } = useApp();
  const { request } = useRequest();

  // State
  const [search, setSearch] = useState("");
  const [selectedArea, setSelectedArea] = useState<(number | string)[]>([]);
  const [subscribedArea, setSubscribedArea] = useState<AreaResponse[]>([]);
  const [selectedFilter, setSelectedFilter] = useState("monthly");
  const [dateRange, setDateRange] = useState({
    startDate: moment().subtract(90, "days").format("DD/MM/YYYY"),
    endDate: moment().format("DD/MM/YYYY")
  });
  const [area, setArea] = useState<Area[] | null>(null);
  const [leadData, setLeadData] = useState<LeadResponse | null>(null);

  // Fetch area list
  const fetchDetail = useCallback(async () => {
    try {
      const res = await request("AREA_LIST");
      const areaData = (res.data ?? []) as Area[];
      setArea(areaData);
    } catch (err) {
      console.error("Error fetching detail", err);
    }
  }, []);

  useEffect(() => {
    fetchDetail();
  }, []);

  // Fetch lead data
  useEffect(() => {
    const fetchLeadData = async () => {
      try {
        const res = await request("LEAD_GRAPH", {
          area_id: selectedArea,
          filter: selectedFilter,
          start_date: moment(dateRange.startDate, "DD/MM/YYYY").format("MM-DD-YYYY"),
          end_date: moment(dateRange.endDate, "DD/MM/YYYY").format("MM-DD-YYYY")
        });

        setLeadData(res.data as LeadResponse);
      } catch (err) {
        console.error("Error fetching lead data", err);
      }
    };

    fetchLeadData();
  }, [selectedArea, dateRange, selectedFilter]);

  // Handlers
  const handleSetSelArr = useCallback(
    (arr: (number | string)[]) => {
      setTimeout(() => setSelectedArea(arr), 0);
    },
    [setSelectedArea]
  );

  const debouncedSearch = debounce((value: string) => {
    setSearch(value);
  }, 500);

  // Set initial areas from userDetail
  useEffect(() => {
    if (userDetail?.areas?.length) {
      const mappedAreas = userDetail.areas.map(item => ({
        code: item.code,
        id: item.id
      }));
      setSubscribedArea(mappedAreas);
    }
  }, [userDetail?.areas]);

  const [subscribedAreaData, setSubscribedAreaData] = useState<number[]>([]);

  // Handle selected area filtering
  useEffect(() => {
    if (area && selectedArea && selectedArea.length > 0) {
      const filteredAreas = area
        .filter(item => selectedArea.includes(item.id))
        .map(item => ({
          code: item.code,
          id: item.id
        }));
      setSubscribedArea(filteredAreas);
    }

    if (
      selectedArea.length > 0 &&
      selectedArea[0] === "subscribed" &&
      userDetail?.areas?.length
    ) {
      const mappedAreas = userDetail.areas.map(item => ({
        code: item.code,
        id: item.id
      }));
      setSubscribedArea(mappedAreas);
      setSubscribedAreaData(mappedAreas.map(item => item.id));
    }
  }, [selectedArea, area, userDetail?.areas]);

  useEffect(() => {
    if (
      subscribedAreaData.length > 0 &&
      (selectedArea.length !== subscribedAreaData.length ||
        !selectedArea.every((v, i) => v === subscribedAreaData[i]))
    ) {
      setSelectedArea(subscribedAreaData);
    }
  }, [subscribedAreaData]);

  const value = {
    // State
    search,
    selectedArea,
    subscribedArea,
    selectedFilter,
    dateRange,
    area,
    leadData,

    // Actions
    setSearch,
    setSelectedArea,
    setSelectedFilter,
    setDateRange,
    handleSetSelArr,
    debouncedSearch
  };

  return (
    <GraphContext.Provider value={value}>
      {children}
    </GraphContext.Provider>
  );
};

export const useGraph = () => {
  const context = useContext(GraphContext);
  if (context === undefined) {
    throw new Error(
      "useGraph must be used within a GraphProvider"
    );
  }
  return context;
}; 