import { useCallback, useEffect, useRef, useState } from "react";
import { HttpError } from "../../shared/api/errors";
import type { PageResult } from "../../shared/api/types";
import { auditApi, type AuditApi } from "./auditApi";
import type {
  AuditActionStatisticsItem,
  AuditLogQuery,
  AuditLogSummary,
  AuditTimeRange,
  AuditTrendItem,
  AuditTrendQuery,
  AuditUserStatisticsItem,
  AuditUserStatisticsQuery,
} from "./auditTypes";

export interface RemoteState<T> {
  data: T | null;
  loading: boolean;
  error: HttpError | null;
}

function asHttpError(value: unknown, fallback: string): HttpError {
  return value instanceof HttpError
    ? value
    : new HttpError({
        httpStatus: 0,
        code: "INTERNAL_ERROR",
        message: fallback,
        details: null,
        requestId: "client",
        cause: value,
      });
}

export function useAuditLogs(
  query: AuditLogQuery,
  api: AuditApi = auditApi,
  debounceMs = 300,
) {
  const [state, setState] = useState<RemoteState<PageResult<AuditLogSummary>>>({
    data: null,
    loading: true,
    error: null,
  });
  const [revision, setRevision] = useState(0);
  const requestVersion = useRef(0);
  const refresh = useCallback(() => setRevision((value) => value + 1), []);

  useEffect(() => {
    const version = ++requestVersion.current;
    const controller = new AbortController();
    const timer = window.setTimeout(() => {
      setState((current) => ({ ...current, loading: true, error: null }));
      void api
        .logs(query, controller.signal)
        .then((data) => {
          if (
            !controller.signal.aborted &&
            version === requestVersion.current
          ) {
            setState({ data, loading: false, error: null });
          }
        })
        .catch((error: unknown) => {
          if (
            controller.signal.aborted ||
            version !== requestVersion.current
          ) {
            return;
          }
          setState({
            data: null,
            loading: false,
            error: asHttpError(error, "审计日志加载失败"),
          });
        });
    }, query.keyword ? debounceMs : 0);
    return () => {
      window.clearTimeout(timer);
      controller.abort();
    };
  }, [
    api,
    debounceMs,
    query.actionType,
    query.createdFrom,
    query.createdTo,
    query.keyword,
    query.operationResult,
    query.organizationId,
    query.page,
    query.pageSize,
    query.sortDirection,
    query.targetId,
    query.targetType,
    query.userId,
    revision,
  ]);

  return { ...state, refresh };
}

export function useAuditTrend(
  query: AuditTrendQuery,
  api: AuditApi = auditApi,
) {
  const [state, setState] = useState<RemoteState<AuditTrendItem[]>>({
    data: null,
    loading: true,
    error: null,
  });
  const [revision, setRevision] = useState(0);
  const refresh = useCallback(() => setRevision((value) => value + 1), []);
  const requestVersion = useRef(0);

  useEffect(() => {
    const version = ++requestVersion.current;
    const controller = new AbortController();
    const timer = window.setTimeout(() => {
      setState((current) => ({ ...current, loading: true, error: null }));
      void api
        .trend(query, controller.signal)
        .then((data) => {
          if (
            !controller.signal.aborted &&
            version === requestVersion.current
          ) {
            setState({ data, loading: false, error: null });
          }
        })
        .catch((error: unknown) => {
          if (
            controller.signal.aborted ||
            version !== requestVersion.current
          ) {
            return;
          }
          setState({
            data: null,
            loading: false,
            error: asHttpError(error, "审计趋势加载失败"),
          });
        });
    }, 0);
    return () => {
      window.clearTimeout(timer);
      controller.abort();
    };
  }, [
    api,
    query.createdFrom,
    query.createdTo,
    query.granularity,
    revision,
  ]);

  return { ...state, refresh };
}

export function useAuditBreakdowns(
  range: AuditTimeRange,
  userQuery: AuditUserStatisticsQuery,
  api: AuditApi = auditApi,
) {
  const [actions, setActions] = useState<
    RemoteState<AuditActionStatisticsItem[]>
  >({ data: null, loading: true, error: null });
  const [users, setUsers] = useState<
    RemoteState<AuditUserStatisticsItem[]>
  >({ data: null, loading: true, error: null });
  const [revision, setRevision] = useState(0);
  const refresh = useCallback(() => setRevision((value) => value + 1), []);
  const requestVersion = useRef(0);

  useEffect(() => {
    const version = ++requestVersion.current;
    const controller = new AbortController();
    const timer = window.setTimeout(() => {
      setActions((current) => ({ ...current, loading: true, error: null }));
      setUsers((current) => ({ ...current, loading: true, error: null }));
      void api
        .actions(range, controller.signal)
        .then((data) => {
          if (
            !controller.signal.aborted &&
            version === requestVersion.current
          ) {
            setActions({ data, loading: false, error: null });
          }
        })
        .catch((error: unknown) => {
          if (
            controller.signal.aborted ||
            version !== requestVersion.current
          ) {
            return;
          }
          setActions({
            data: null,
            loading: false,
            error: asHttpError(error, "动作分布加载失败"),
          });
        });
      void api
        .users(userQuery, controller.signal)
        .then((data) => {
          if (
            !controller.signal.aborted &&
            version === requestVersion.current
          ) {
            setUsers({ data, loading: false, error: null });
          }
        })
        .catch((error: unknown) => {
          if (
            controller.signal.aborted ||
            version !== requestVersion.current
          ) {
            return;
          }
          setUsers({
            data: null,
            loading: false,
            error: asHttpError(error, "活跃用户加载失败"),
          });
        });
    }, 0);
    return () => {
      window.clearTimeout(timer);
      controller.abort();
    };
  }, [
    api,
    range.createdFrom,
    range.createdTo,
    userQuery.limit,
    revision,
  ]);

  return { actions, users, refresh };
}

