import { useCallback, useEffect, useMemo, useState } from "react";
import Dialog from "@mui/material/Dialog";
import DialogContent from "@mui/material/DialogContent";
import DialogTitle from "@mui/material/DialogTitle";
import {
  approveFinanceApplication,
  approveFinanceWithdrawalApplication,
  createFinanceApplication,
  fetchFinanceApplicationOptions,
  fetchFinanceSession,
  filterOperationsByPermissions,
  listFinanceApplications,
  listFinanceRechargeDetails,
  listMyFinanceApplications,
  listFinanceWithdrawalApplications,
  rejectFinanceApplication,
  rejectFinanceWithdrawalApplication
} from "./api.js";
import { FinanceApplicationForm } from "./components/FinanceApplicationForm.jsx";
import { FinanceApplicationList } from "./components/FinanceApplicationList.jsx";
import { FinanceAuditDialog } from "./components/FinanceAuditDialog.jsx";
import { FinanceMyApplicationList } from "./components/FinanceMyApplicationList.jsx";
import { FinanceRechargeDetailList } from "./components/FinanceRechargeDetailList.jsx";
import { FinanceShell } from "./components/FinanceShell.jsx";
import { FinanceWithdrawalApplicationList } from "./components/FinanceWithdrawalApplicationList.jsx";
import { DEFAULT_APPLICATION_FORM } from "./constants.js";
import { buildApplicationPayload, validateApplicationPayload } from "./format.js";
import { useToast } from "@/shared/ui/ToastProvider.jsx";

const emptyOptions = { apps: [], operations: [], walletIdentities: [] };
const pageSize = 50;

export function FinanceApp() {
  const { showToast } = useToast();
  const [sessionState, setSessionState] = useState({ error: "", loading: true, session: null });
  const [optionsState, setOptionsState] = useState({ data: emptyOptions, error: "", loading: false });
  const [rechargeDetailsState, setRechargeDetailsState] = useState({ data: { items: [], page: 1, pageSize, total: 0 }, error: "", loading: false });
  const [myApplicationsState, setMyApplicationsState] = useState({ data: { items: [], page: 1, pageSize, total: 0 }, error: "", loading: false });
  const [applicationsState, setApplicationsState] = useState({ data: { items: [], page: 1, pageSize, total: 0 }, error: "", loading: false });
  const [withdrawalsState, setWithdrawalsState] = useState({ data: { items: [], page: 1, pageSize, total: 0 }, error: "", loading: false });
  const [activeView, setActiveView] = useState("create");
  const [rechargeDetailFilters, setRechargeDetailFilters] = useState({ appCode: "", keyword: "", page: 1, timeRange: { endMs: "", startMs: "" } });
  const [myFilters, setMyFilters] = useState({ appCode: "", keyword: "", operation: "", page: 1, status: "" });
  const [filters, setFilters] = useState({ appCode: "", keyword: "", operation: "", page: 1, status: "pending" });
  const [withdrawalFilters, setWithdrawalFilters] = useState({ appCode: "", keyword: "", page: 1 });
  const [form, setForm] = useState(DEFAULT_APPLICATION_FORM);
  const [createDialogOpen, setCreateDialogOpen] = useState(false);
  const [submitting, setSubmitting] = useState(false);
  const [auditTarget, setAuditTarget] = useState(null);
  const [auditLoading, setAuditLoading] = useState(false);
  const [withdrawalAuditTarget, setWithdrawalAuditTarget] = useState(null);
  const [withdrawalAuditLoading, setWithdrawalAuditLoading] = useState(false);

  useEffect(() => {
    let mounted = true;
    fetchFinanceSession()
      .then((session) => {
        if (!mounted) {
          return;
        }
        setSessionState({ error: "", loading: false, session });
        setActiveView(
          session.canViewAppRechargeDetails
            ? "rechargeDetails"
            : session.canAuditApplication
              ? "applications"
              : session.canCreateApplication
                ? "create"
                : "withdrawals"
        );
      })
      .catch((err) => {
        if (mounted) {
          setSessionState({ error: err.message || "登录已失效", loading: false, session: null });
        }
      });
    return () => {
      mounted = false;
    };
  }, []);

  const session = sessionState.session;
  const canLoadOptions = Boolean(session?.canAccessFinance);
  const rechargeDetailQuery = useMemo(
    () => ({
      app_code: rechargeDetailFilters.appCode,
      end_at_ms: rechargeDetailFilters.timeRange.endMs,
      keyword: rechargeDetailFilters.keyword,
      page: rechargeDetailFilters.page,
      page_size: pageSize,
      start_at_ms: rechargeDetailFilters.timeRange.startMs,
      stat_tz: "Asia/Shanghai",
      status: "succeeded"
    }),
    [rechargeDetailFilters]
  );
  const myApplicationQuery = useMemo(
    () => ({
      app_code: myFilters.appCode,
      keyword: myFilters.keyword,
      operation: myFilters.operation,
      page: myFilters.page,
      page_size: pageSize,
      status: myFilters.status
    }),
    [myFilters]
  );
  const applicationQuery = useMemo(
    () => ({
      app_code: filters.appCode,
      keyword: filters.keyword,
      operation: filters.operation,
      page: filters.page,
      page_size: pageSize,
      status: filters.status
    }),
    [filters]
  );
  const withdrawalQuery = useMemo(
    () => ({
      app_code: withdrawalFilters.appCode,
      keyword: withdrawalFilters.keyword,
      page: withdrawalFilters.page,
      page_size: pageSize
    }),
    [withdrawalFilters]
  );

  const loadOptions = useCallback(async () => {
    if (!canLoadOptions) {
      return;
    }
    setOptionsState((current) => ({ ...current, error: "", loading: true }));
    try {
      const data = await fetchFinanceApplicationOptions();
      setOptionsState({ data, error: "", loading: false });
    } catch (err) {
      setOptionsState({ data: emptyOptions, error: err.message || "加载财务选项失败", loading: false });
    }
  }, [canLoadOptions]);

  const loadMyApplications = useCallback(async () => {
    if (!session?.canCreateApplication) {
      return;
    }
    setMyApplicationsState((current) => ({ ...current, error: "", loading: true }));
    try {
      const data = await listMyFinanceApplications(myApplicationQuery);
      setMyApplicationsState({ data, error: "", loading: false });
    } catch (err) {
      setMyApplicationsState((current) => ({ ...current, error: err.message || "加载我的申请列表失败", loading: false }));
    }
  }, [myApplicationQuery, session?.canCreateApplication]);

  const loadRechargeDetails = useCallback(async () => {
    if (!session?.canViewAppRechargeDetails) {
      return;
    }
    setRechargeDetailsState((current) => ({ ...current, error: "", loading: true }));
    try {
      const data = await listFinanceRechargeDetails(rechargeDetailQuery, optionsState.data.apps);
      setRechargeDetailsState({ data, error: "", loading: false });
    } catch (err) {
      setRechargeDetailsState((current) => ({ ...current, error: err.message || "加载 APP 充值详情失败", loading: false }));
    }
  }, [optionsState.data.apps, rechargeDetailQuery, session?.canViewAppRechargeDetails]);

  const loadApplications = useCallback(async () => {
    if (!session?.canAuditApplication) {
      return;
    }
    setApplicationsState((current) => ({ ...current, error: "", loading: true }));
    try {
      const data = await listFinanceApplications(applicationQuery);
      setApplicationsState({ data, error: "", loading: false });
    } catch (err) {
      setApplicationsState((current) => ({ ...current, error: err.message || "加载申请列表失败", loading: false }));
    }
  }, [applicationQuery, session?.canAuditApplication]);

  const loadWithdrawals = useCallback(async () => {
    if (!session?.canViewWithdrawalApplications) {
      return;
    }
    setWithdrawalsState((current) => ({ ...current, error: "", loading: true }));
    try {
      const data = await listFinanceWithdrawalApplications(withdrawalQuery);
      setWithdrawalsState({ data, error: "", loading: false });
    } catch (err) {
      setWithdrawalsState((current) => ({ ...current, error: err.message || "加载提现申请列表失败", loading: false }));
    }
  }, [session?.canViewWithdrawalApplications, withdrawalQuery]);

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

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

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

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

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

  const operationOptions = useMemo(
    () => filterOperationsByPermissions(optionsState.data.operations, session?.permissions || []),
    [optionsState.data.operations, session?.permissions]
  );

  const submitApplication = async (event) => {
    event.preventDefault();
    if (!session?.canCreateApplication) {
      showToast("无发起财务申请权限", "error");
      return;
    }

    const payload = buildApplicationPayload(form);
    const validationMessage = validateApplicationPayload(payload);
    if (validationMessage) {
      showToast(validationMessage, "warning");
      return;
    }

    setSubmitting(true);
    try {
      const result = await createFinanceApplication(cleanPayload(payload));
      setForm({ ...DEFAULT_APPLICATION_FORM, appCode: payload.appCode });
      setCreateDialogOpen(false);
      showToast(result?.dingTalkNotified === false ? "申请已提交，钉钉通知未确认" : "申请已提交并通知财务", "success");
      await loadMyApplications();
      if (session.canAuditApplication) {
        await loadApplications();
      }
    } catch (err) {
      showToast(err.message || "发起申请失败", "error");
    } finally {
      setSubmitting(false);
    }
  };

  const submitAudit = async ({ decision, remark }) => {
    if (!auditTarget?.id || !session?.canAuditApplication) {
      return;
    }
    setAuditLoading(true);
    try {
      const submitter = decision === "approved" ? approveFinanceApplication : rejectFinanceApplication;
      await submitter(auditTarget.id, { auditRemark: remark });
      showToast(decision === "approved" ? "申请已通过" : "申请已拒绝", "success");
      setAuditTarget(null);
      await loadApplications();
    } catch (err) {
      showToast(err.message || "审核失败", "error");
    } finally {
      setAuditLoading(false);
    }
  };

  const submitWithdrawalAudit = async ({ auditImageUrl, decision, remark }) => {
    if (!withdrawalAuditTarget?.id || !session?.canAuditWithdrawalApplications) {
      return;
    }
    setWithdrawalAuditLoading(true);
    try {
      const submitter = decision === "approved" ? approveFinanceWithdrawalApplication : rejectFinanceWithdrawalApplication;
      await submitter(withdrawalAuditTarget.id, cleanPayload({ auditImageUrl, auditRemark: remark }));
      showToast(decision === "approved" ? "提现申请已通过" : "提现申请已拒绝", "success");
      setWithdrawalAuditTarget(null);
      await loadWithdrawals();
    } catch (err) {
      showToast(err.message || "审核提现申请失败", "error");
    } finally {
      setWithdrawalAuditLoading(false);
    }
  };

  const updateFilters = (nextFilters) => {
    setFilters((current) => ({ ...current, ...nextFilters, page: nextFilters.page || 1 }));
  };

  const updateRechargeDetailFilters = (nextFilters) => {
    setRechargeDetailFilters((current) => ({ ...current, ...nextFilters, page: nextFilters.page || 1 }));
  };

  const updateMyFilters = (nextFilters) => {
    setMyFilters((current) => ({ ...current, ...nextFilters, page: nextFilters.page || 1 }));
  };

  const updateWithdrawalFilters = (nextFilters) => {
    setWithdrawalFilters((current) => ({ ...current, ...nextFilters, page: nextFilters.page || 1 }));
  };

  const closeCreateDialog = (_, reason) => {
    if (submitting || reason === "backdropClick") {
      return;
    }
    setCreateDialogOpen(false);
  };

  if (sessionState.loading) {
    return <StateScreen title="正在进入财务系统" />;
  }

  if (sessionState.error) {
    return <StateScreen actionHref="/login" actionText="重新登录" title={sessionState.error} />;
  }

  if (!session?.canAccessFinance) {
    return <StateScreen title="无财务系统权限" />;
  }

  return (
    <FinanceShell
      activeView={activeView}
      canAudit={session.canAuditApplication}
      canCreate={session.canCreateApplication}
      canViewRechargeDetails={session.canViewAppRechargeDetails}
      canViewWithdrawals={session.canViewWithdrawalApplications}
      loading={optionsState.loading || rechargeDetailsState.loading || myApplicationsState.loading || applicationsState.loading || withdrawalsState.loading}
      session={session}
      onRefresh={() => {
        loadOptions();
        loadRechargeDetails();
        loadMyApplications();
        loadApplications();
        loadWithdrawals();
      }}
      onViewChange={setActiveView}
    >
      {activeView === "rechargeDetails" && session.canViewAppRechargeDetails ? (
        <FinanceRechargeDetailList
          bills={rechargeDetailsState.data}
          error={rechargeDetailsState.error}
          filters={rechargeDetailFilters}
          loading={rechargeDetailsState.loading}
          options={optionsState.data}
          onFiltersChange={updateRechargeDetailFilters}
          onReload={loadRechargeDetails}
        />
      ) : activeView === "applications" && session.canAuditApplication ? (
        <FinanceApplicationList
          applications={applicationsState.data}
          error={applicationsState.error}
          filters={filters}
          loading={applicationsState.loading}
          operations={optionsState.data.operations}
          options={optionsState.data}
          onAudit={setAuditTarget}
          onFiltersChange={updateFilters}
          onReload={loadApplications}
        />
      ) : activeView === "withdrawals" && session.canViewWithdrawalApplications ? (
        <FinanceWithdrawalApplicationList
          applications={withdrawalsState.data}
          canAudit={session.canAuditWithdrawalApplications}
          error={withdrawalsState.error}
          filters={withdrawalFilters}
          loading={withdrawalsState.loading}
          options={optionsState.data}
          onAudit={setWithdrawalAuditTarget}
          onFiltersChange={updateWithdrawalFilters}
          onReload={loadWithdrawals}
        />
      ) : (
        <FinanceMyApplicationList
          applications={myApplicationsState.data}
          error={myApplicationsState.error}
          filters={myFilters}
          loading={myApplicationsState.loading}
          operations={optionsState.data.operations}
          options={optionsState.data}
          onCreate={() => setCreateDialogOpen(true)}
          onFiltersChange={updateMyFilters}
          onReload={loadMyApplications}
        />
      )}
      <Dialog
        fullWidth
        maxWidth="md"
        open={createDialogOpen}
        slotProps={{ paper: { className: "finance-create-dialog-paper" } }}
        onClose={closeCreateDialog}
      >
        <DialogTitle>发起申请</DialogTitle>
        <DialogContent className="finance-create-dialog">
          <FinanceApplicationForm
            apps={optionsState.data.apps}
            disabled={!session.canCreateApplication}
            error={optionsState.error}
            form={form}
            loading={optionsState.loading || submitting}
            operations={operationOptions}
            walletIdentities={optionsState.data.walletIdentities}
            onCancel={closeCreateDialog}
            onChange={setForm}
            onSubmit={submitApplication}
          />
        </DialogContent>
      </Dialog>
      <FinanceAuditDialog
        application={auditTarget}
        loading={auditLoading}
        operations={optionsState.data.operations}
        open={Boolean(auditTarget)}
        onClose={() => setAuditTarget(null)}
        onSubmit={submitAudit}
      />
      <FinanceAuditDialog
        application={withdrawalAuditTarget}
        loading={withdrawalAuditLoading}
        operations={optionsState.data.operations}
        open={Boolean(withdrawalAuditTarget)}
        requireApprovalImage
        requireRejectRemark
        onClose={() => setWithdrawalAuditTarget(null)}
        onSubmit={submitWithdrawalAudit}
      />
    </FinanceShell>
  );
}

function StateScreen({ actionHref = "", actionText = "", title }) {
  return (
    <main className="finance-state-screen">
      <section className="finance-state-panel">
        <h1>{title}</h1>
        {actionHref ? <a href={actionHref}>{actionText}</a> : null}
      </section>
    </main>
  );
}

function cleanPayload(payload) {
  return Object.fromEntries(Object.entries(payload).filter(([, value]) => value !== ""));
}
