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";
import { current_month, current_year } from "@/utils/const";
import { toastrC } from "@/utils/helpers";

interface Area {
  code: string;
  id: number;
}

interface AreaResponse {
  code: string;
  id: number;
}

interface LeadReportResponse {
  data: Array<{
    id: number;
    vehicle_registration: string;
    vehicle_make: string;
    vehicle_model: string;
    vehicle_year: string;
    created_at: string;
    updated_at: string;
    status: string;
    area_id: number;
    area_name: string;
  }>;
  total: number;
  per_page: number;
}

interface VehicleDetailResponse {
  data: {
    vehicle_mot_data_json: string;
  };
}

interface LeadStatementContextType {
  // State
  search: string;
  selectedArea: (number | string)[];
  subscribedArea: AreaResponse[];
  selectedFilter: string;
  dateRange: {
    startDate: moment.Moment;
    endDate: moment.Moment;
  };
  currentPage: number;
  totalPagesVal: number;
  isDownloading: boolean;
  area: AreaResponse[] | null;
  perPage: number;
  goToPage: number;
  leadData: LeadReportResponse | null;

  // Actions
  setSearch: (value: string) => void;
  setSelectedArea: (areas: (number | string)[]) => void;
  setSelectedFilter: (filter: string) => void;
  setDateRange: (range: {
    startDate: moment.Moment;
    endDate: moment.Moment;
  }) => void;
  setCurrentPage: (page: number) => void;
  setPerPage: (perPage: number) => void;
  setGoToPage: (page: number) => void;
  handleSetSelArr: (arr: (number | string)[]) => void;
  handleLeadDownload: () => Promise<void>;
  handleView: (id: number) => Promise<void>;
  handleDownload: (id: number) => Promise<void>;
  handlePageChange: (page: number) => void;
  debouncedSearch: (value: string) => void;
}

const LeadStatementContext = createContext<
  LeadStatementContextType | undefined
>(undefined);

export const LeadStatementProvider: React.FC<{ children: React.ReactNode }> = ({
  children
}) => {
  const { state, dispatch, 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("last_90_days");
  const [dateRange, setDateRange] = useState({
    startDate: moment().subtract(90, "days"),
    endDate: moment()
  });
  const [currentPage, setCurrentPage] = useState(1);
  const [totalPagesVal, setTotalPagesVal] = useState(30);
  const [isDownloading, setIsDownloading] = useState(false);
  const [area, setArea] = useState<Area[] | null>(null);
  const [perPage, setPerPage] = useState(20);
  const [goToPage, setGoToPage] = useState(currentPage);
  const [leadData, setLeadData] = useState<LeadReportResponse | 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);
    }
  }, [request]);

  useEffect(() => {
    fetchDetail();
  }, []);

  // Fetch lead data
  useEffect(() => {
    const fetchLeadData = async () => {

      console.log("dateRange*****", dateRange, {
        startDate: moment(dateRange.startDate, "DD/MM/YYYY").format("MM-DD-YYYY"),
        endDate: moment(dateRange.endDate, "DD/MM/YYYY").format("MM-DD-YYYY")
      });

      try {
        const res = await request("LEAD_REPORT", {
          search: search,
          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"),
          area_id: selectedArea.map(id => id.toString()),
          month: `${current_year}-${current_month}`,
          page: currentPage,
          per_page: perPage
        });

        const typedRes = res.data as LeadReportResponse;
        setLeadData(typedRes);
        if (typedRes?.total && typedRes?.per_page) {
          const tp = Math.ceil(typedRes.total / typedRes.per_page);
          setTotalPagesVal(tp);
        }
      } catch (err) {
        console.error("Error fetching lead data", err);
      }
    };

    fetchLeadData();
  }, [selectedArea, dateRange, search, currentPage, perPage, selectedFilter]);

  // Handlers
  const handleSetSelArr = useCallback(
    (arr: (number | string)[]) => {
      setTimeout(() => setSelectedArea(arr), 0);
    },
    [setSelectedArea]
  );

  const handleView = async (id: number) => {
    try {
      const res = await request("LEAD_VEHICLE_DETAIL_ID", {}, { id: `${id}` });

      const typedRes = res as unknown as VehicleDetailResponse;
      if (typedRes.data) {
        dispatch({
          ...state,
          VEHICLE_AND_MOT_DATA: JSON.parse(typedRes.data.vehicle_mot_data_json),
          valuationDetail: typedRes.data
        });
        setTimeout(() => {
          window.open(`/full-valuation-detail`, "_blank");
        }, 200);
      }
    } catch (e) {
      console.log(e);
    }
  };

  const handleDownload = async (id: number) => {
    try {
      const res = await request(
        "DOWNLOAD_LEAD_DETAIL",
        {},
        { id: `${id}` },
        { responseType: "blob" }
      );

      if (!res || !(res instanceof Blob)) {
        toastrC("Invalid response, expected a Blob", "error", "error");
        return;
      }

      const url = window.URL.createObjectURL(res);
      const a = document.createElement("a");
      a.href = url;
      a.download = `lead-${id}.pdf`;
      document.body.appendChild(a);
      a.click();
      document.body.removeChild(a);
      window.URL.revokeObjectURL(url);
    } catch (e) {
      console.log(e);
    }
  };

  const handleLeadDownload = async () => {
    setIsDownloading(true);
    try {
      const res = await request(
        "DOWNLOAD_LEAD_STATEMENT",
        { search: search,
          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"),
          area_id: selectedArea.map(id => id.toString()),
          month: `${current_year}-${current_month}`,},
        {},
        { responseType: "blob" }
      );

      if (!res || !(res instanceof Blob)) {
        toastrC("Invalid response, expected a Blob", "error", "error");
        return;
      }

      const url = window.URL.createObjectURL(res);
      const a = document.createElement("a");
      a.href = url;
      a.download = `lead-report.xlsx`;
      document.body.appendChild(a);
      a.click();
      document.body.removeChild(a);
      window.URL.revokeObjectURL(url);
    } catch (e) {
      console.log(e);
    } finally {
      setIsDownloading(false);
    }
  };

  const handlePageChange = (page: number) => {
    setCurrentPage(page);
  };

  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,
    currentPage,
    totalPagesVal,
    isDownloading,
    area,
    perPage,
    goToPage,
    leadData,

    // Actions
    setSearch,
    setSelectedArea,
    setSelectedFilter,
    setDateRange,
    setCurrentPage,
    setPerPage,
    setGoToPage,
    handleSetSelArr,
    handleLeadDownload,
    handleView,
    handleDownload,
    handlePageChange,
    debouncedSearch
  };

  return (
    <LeadStatementContext.Provider value={value}>
      {children}
    </LeadStatementContext.Provider>
  );
};

export const useLeadStatement = () => {
  const context = useContext(LeadStatementContext);
  if (context === undefined) {
    throw new Error(
      "useLeadStatement must be used within a LeadStatementProvider"
    );
  }
  return context;
};
