import { useReducer, useEffect, useRef, useCallback } from "react";
import type { MonthlyTrendItem, CategoryOverTimeData, ImportSource } from "../shared/types";
import { getMonthlyTrends, getCategoryOverTime } from "../services/reportService";
import { getAllImportSources } from "../services/transactionService";
import { useReportsPeriod } from "./useReportsPeriod";

export type TrendsSubView = "global" | "byCategory";

interface State {
  subView: TrendsSubView;
  monthlyTrends: MonthlyTrendItem[];
  categoryOverTime: CategoryOverTimeData;
  accounts: ImportSource[];
  isLoading: boolean;
  error: string | null;
}

type Action =
  | { type: "SET_SUBVIEW"; payload: TrendsSubView }
  | { type: "SET_LOADING"; payload: boolean }
  | { type: "SET_TRENDS"; payload: MonthlyTrendItem[] }
  | { type: "SET_CATEGORY_OVER_TIME"; payload: CategoryOverTimeData }
  | { type: "SET_ACCOUNTS"; payload: ImportSource[] }
  | { type: "SET_ERROR"; payload: string };

const initialState: State = {
  subView: "byCategory",
  monthlyTrends: [],
  categoryOverTime: { categories: [], data: [], colors: {}, categoryIds: {}, types: {}, tree: [] },
  accounts: [],
  isLoading: false,
  error: null,
};

function reducer(state: State, action: Action): State {
  switch (action.type) {
    case "SET_SUBVIEW":
      return { ...state, subView: action.payload };
    case "SET_LOADING":
      return { ...state, isLoading: action.payload };
    case "SET_TRENDS":
      return { ...state, monthlyTrends: action.payload, isLoading: false, error: null };
    case "SET_CATEGORY_OVER_TIME":
      return { ...state, categoryOverTime: action.payload, isLoading: false, error: null };
    case "SET_ACCOUNTS":
      return { ...state, accounts: action.payload };
    case "SET_ERROR":
      return { ...state, error: action.payload, isLoading: false };
    default:
      return state;
  }
}

export function useTrends() {
  const { from, to, accountIds } = useReportsPeriod();
  const [state, dispatch] = useReducer(reducer, initialState);
  const fetchIdRef = useRef(0);

  const fetch = useCallback(
    async (subView: TrendsSubView, dateFrom: string, dateTo: string, ids: number[]) => {
      const id = ++fetchIdRef.current;
      dispatch({ type: "SET_LOADING", payload: true });
      try {
        if (subView === "global") {
          const data = await getMonthlyTrends(dateFrom, dateTo, ids);
          if (id !== fetchIdRef.current) return;
          dispatch({ type: "SET_TRENDS", payload: data });
        } else {
          const data = await getCategoryOverTime(dateFrom, dateTo, undefined, ids);
          if (id !== fetchIdRef.current) return;
          dispatch({ type: "SET_CATEGORY_OVER_TIME", payload: data });
        }
      } catch (e) {
        if (id !== fetchIdRef.current) return;
        dispatch({ type: "SET_ERROR", payload: e instanceof Error ? e.message : String(e) });
      }
    },
    []
  );

  useEffect(() => {
    fetch(state.subView, from, to, accountIds);
  }, [fetch, state.subView, from, to, accountIds]);

  // Load the import-source list once, for the FilterPanel's account checkboxes
  // (same query as the Transactions single-source filter — see useTransactions.ts).
  useEffect(() => {
    (async () => {
      try {
        const accounts = await getAllImportSources();
        dispatch({ type: "SET_ACCOUNTS", payload: accounts });
      } catch (e) {
        dispatch({ type: "SET_ERROR", payload: e instanceof Error ? e.message : String(e) });
      }
    })();
  }, []);

  const setSubView = useCallback((sv: TrendsSubView) => {
    dispatch({ type: "SET_SUBVIEW", payload: sv });
  }, []);

  return { ...state, setSubView, from, to };
}
