"use client";

import { useCallback, useEffect, useMemo, useState } from "react";
import { useTranslation } from "react-i18next";
import { toast } from "sonner";

import {
  getSettlementBills,
  postSettlementBillConfirm,
  type SettlementBillListScope,
  type SettlementBillRow,
} from "@/api/admin-agent-settlement";
import { AdminListPaginationFooter } from "@/components/admin/admin-list-pagination-footer";
import { AdminLoadingState } from "@/components/admin/admin-loading-state";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from "@/components/ui/select";
import { useAsyncEffect } from "@/hooks/use-async-effect";
import { useConfirmAction } from "@/hooks/use-confirm-action";
import type { AgentSettlementPeriodFilter } from "@/modules/settlement/agent-settlement-period-select";
import { SettlementBillsTable } from "@/modules/settlement/settlement-bills-table";
import { settlementBillOperableByBoundAgent } from "@/modules/settlement/settlement-bill-operable";
import type { SettlementBillScopeFilter } from "@/modules/settlement/settlement-center-nav";
import { LotteryApiBizError } from "@/types/api/errors";

type BillTypeFilter = "all" | "player" | "agent";
type SettlementMainPanelMode = "workbench" | "all";

type BillFilters = {
  ownerKeyword: string;
  billType: BillTypeFilter;
  statusScope: SettlementBillScopeFilter;
};

function filtersForPeriod(
  boundAgentId: number | null,
  billScope: SettlementBillScopeFilter,
): BillFilters {
  return {
    ownerKeyword: "",
    billType: boundAgentId !== null ? "agent" : "all",
    statusScope: billScope,
  };
}

function apiQueryFromFilters(filters: BillFilters): {
  bill_type?: string;
  scope?: SettlementBillListScope;
  keyword?: string;
} {
  const out: {
    bill_type?: string;
    scope?: SettlementBillListScope;
    keyword?: string;
  } = {};

  if (filters.billType === "player" || filters.billType === "agent") {
    out.bill_type = filters.billType;
  }
  if (filters.statusScope !== "all") {
    out.scope = filters.statusScope;
  }
  const keyword = filters.ownerKeyword.trim();
  if (keyword !== "") {
    out.keyword = keyword;
  }

  return out;
}

export type SettlementMainPanelProps = {
  adminSiteId: number;
  currencyCode: string;
  periodFilter: AgentSettlementPeriodFilter;
  billScope?: SettlementBillScopeFilter;
  mode?: SettlementMainPanelMode;
  onOpenBillDetail: (billId: number, focus?: "confirm" | "payment") => void;
  refreshKey?: number;
  canOperateBills?: boolean;
  selectedPeriodStatus?: string | null;
  boundAgentId?: number | null;
};

export function SettlementMainPanel({
  adminSiteId,
  currencyCode,
  periodFilter,
  billScope = "all",
  mode = "all",
  onOpenBillDetail,
  refreshKey = 0,
  canOperateBills = false,
  selectedPeriodStatus,
  boundAgentId = null,
}: SettlementMainPanelProps): React.ReactElement {
  const { t } = useTranslation("settlementCenter");
  const periodId = periodFilter === "all" ? undefined : periodFilter;
  const periodOpen = selectedPeriodStatus === "open";
  const { request: requestConfirm, ConfirmDialog } = useConfirmAction();

  const initialFilters = useMemo(() => {
    const base = filtersForPeriod(boundAgentId, billScope);
    return mode === "workbench" ? { ...base, statusScope: "all" as const } : base;
  }, [boundAgentId, billScope, mode]);

  const [draft, setDraft] = useState<BillFilters>(initialFilters);
  const [applied, setApplied] = useState<BillFilters>(initialFilters);
  const [rows, setRows] = useState<SettlementBillRow[]>([]);
  const [loading, setLoading] = useState(true);
  const [page, setPage] = useState(1);
  const [perPage, setPerPage] = useState(mode === "workbench" ? 100 : 20);
  const [total, setTotal] = useState(0);

  useEffect(() => {
    setDraft(initialFilters);
    setApplied(initialFilters);
    setPage(1);
  }, [initialFilters]);

  const load = useCallback(async () => {
    setLoading(true);
    try {
      const q = apiQueryFromFilters(applied);
      const data = await getSettlementBills({
        admin_site_id: adminSiteId,
        settlement_period_id: periodId,
        bill_type: q.bill_type,
        scope: q.scope,
        keyword: q.keyword,
        page: mode === "workbench" ? 1 : page,
        per_page: mode === "workbench" ? 100 : perPage,
      });
      setRows(data.items ?? []);
      setTotal(data.total ?? data.items?.length ?? 0);
    } catch (err: unknown) {
      setRows([]);
      setTotal(0);
      toast.error(
        err instanceof LotteryApiBizError
          ? err.message
          : t("errors.loadBills", { defaultValue: "账单加载失败" }),
      );
    } finally {
      setLoading(false);
    }
  }, [adminSiteId, applied, mode, page, perPage, periodId, t]);

  useAsyncEffect(() => {
    void load();
  }, [load, refreshKey]);

  const runSearch = () => {
    setPage(1);
    setApplied({ ...draft });
  };

  const resetFilters = () => {
    setDraft(initialFilters);
    setApplied(initialFilters);
    setPage(1);
  };

  const emptyBillMessage = useMemo((): string | undefined => {
    if (periodOpen) {
      return t("empty.billsNeedClose", {
        defaultValue: "账单在关账后生成。请对本账期执行「关账」后再查看。",
      });
    }
    if (applied.statusScope !== "all") {
      return t("billsPanel.emptyFiltered", {
        defaultValue: "当前筛选下暂无账单，请改为「全部状态」或重置筛选。",
      });
    }
    return t("billsPanel.emptyClosed", {
      defaultValue:
        "本期已关账但暂无账单。常见原因：账期内无信用盘玩家的已结算注单，或占成流水不在本账期时间范围内。",
    });
  }, [applied.statusScope, periodOpen, t]);

  const billTypeOptions: BillTypeFilter[] =
    boundAgentId !== null ? ["agent"] : ["all", "player", "agent"];

  const billTypeLabel = (value: BillTypeFilter): string => {
    switch (value) {
      case "player":
        return t("billsPanel.category.player", { defaultValue: "玩家账单" });
      case "agent":
        return t("billsPanel.category.agent", { defaultValue: "代理账单" });
      default:
        return t("billsPanel.filterAllTypes", { defaultValue: "全部类型" });
    }
  };

  const requestConfirmBill = (row: SettlementBillRow): void => {
    requestConfirm({
      title: t("billsPanel.confirmOneTitle", { defaultValue: "确认账单 #{{id}}？", id: row.id }),
      description: t("billsPanel.confirmOneDesc", {
        defaultValue: "确认后进入待收付，可登记线下收付。",
      }),
      confirmLabel: t("billsPanel.confirmOneBtn", { defaultValue: "确认" }),
      onConfirm: async () => {
        try {
          await postSettlementBillConfirm(row.id);
          await load();
          toast.success(t("billsPanel.confirmedOne", { defaultValue: "已确认" }));
        } catch (err: unknown) {
          toast.error(
            err instanceof LotteryApiBizError
              ? err.message
              : t("billsPanel.confirmFailed", { defaultValue: "确认失败" }),
          );
        }
      },
    });
  };

  const canOperateRow = (row: SettlementBillRow): boolean =>
    canOperateBills && settlementBillOperableByBoundAgent(row, boundAgentId ? { id: boundAgentId } : null);

  const pendingConfirmRows = rows.filter((row) => row.status === "pending_confirm");
  const awaitingPaymentRows = rows.filter((row) =>
    ["confirmed", "partial_paid", "overdue"].includes(row.status) && row.unpaid_amount > 0,
  );
  const exceptionRows = rows.filter((row) =>
    ["adjustment", "reversal", "bad_debt"].includes(row.bill_type),
  );
  const hasWorkbenchRows =
    pendingConfirmRows.length > 0 || awaitingPaymentRows.length > 0 || exceptionRows.length > 0;

  const renderBillsTable = (
    tableRows: SettlementBillRow[],
    emptyMessage?: string,
  ): React.ReactElement => (
    <SettlementBillsTable
      rows={tableRows}
      loading={loading}
      currencyCode={currencyCode}
      billTypeFilter={applied.billType}
      emptyMessage={emptyMessage}
      canOperate={canOperateBills}
      boundAgentId={boundAgentId}
      onOpenDetail={(billId) => onOpenBillDetail(billId)}
      onConfirmBill={(row) => {
        if (canOperateRow(row) && row.status === "pending_confirm") {
          requestConfirmBill(row);
        }
      }}
      onPayBill={(row) => {
        if (
          canOperateRow(row) &&
          ["confirmed", "partial_paid", "overdue"].includes(row.status) &&
          row.unpaid_amount > 0
        ) {
          onOpenBillDetail(row.id, "payment");
        }
      }}
    />
  );

  if (mode === "workbench") {
    return (
      <div className="space-y-4">
        <ConfirmDialog />
        {loading && rows.length === 0 ? (
          <AdminLoadingState />
        ) : periodOpen ? (
          renderBillsTable([], emptyBillMessage)
        ) : !hasWorkbenchRows ? (
          renderBillsTable([], t("billsPanel.workbenchEmpty", {
            defaultValue: "本期暂无待处理账单。需要查历史或已结清账单，请进入「全部账单」。",
          }))
        ) : (
          <>
            {pendingConfirmRows.length > 0 ? (
              <section className="space-y-2">
                <div>
                  <h3 className="text-sm font-semibold">
                    {t("billsPanel.workbench.pendingTitle", { defaultValue: "待确认账单" })}
                  </h3>
                  <p className="text-xs text-muted-foreground">
                    {t("billsPanel.workbench.pendingHint", {
                      defaultValue: "先确认金额与双方，确认后进入待收付。",
                    })}
                  </p>
                </div>
                {renderBillsTable(pendingConfirmRows)}
              </section>
            ) : null}
            {awaitingPaymentRows.length > 0 ? (
              <section className="space-y-2">
                <div>
                  <h3 className="text-sm font-semibold">
                    {t("billsPanel.workbench.awaitingTitle", { defaultValue: "待收付账单" })}
                  </h3>
                  <p className="text-xs text-muted-foreground">
                    {t("billsPanel.workbench.awaitingHint", {
                      defaultValue: "按谁付谁登记线下收付，全部收付后账单结清。",
                    })}
                  </p>
                </div>
                {renderBillsTable(awaitingPaymentRows)}
              </section>
            ) : null}
            {exceptionRows.length > 0 ? (
              <section className="space-y-2">
                <div>
                  <h3 className="text-sm font-semibold">
                    {t("billsPanel.workbench.exceptionTitle", { defaultValue: "异常处理" })}
                  </h3>
                  <p className="text-xs text-muted-foreground">
                    {t("billsPanel.workbench.exceptionHint", {
                      defaultValue: "逾期、调账、冲正与坏账记录集中在这里复核。",
                    })}
                  </p>
                </div>
                {renderBillsTable(exceptionRows)}
              </section>
            ) : null}
          </>
        )}
      </div>
    );
  }

  return (
    <div className="space-y-4">
      <ConfirmDialog />

      <div className="admin-list-toolbar">
        <div className="admin-list-field min-w-[12rem] flex-1">
          <Label htmlFor="sb-owner" className="sm:shrink-0">
            {t("billsPanel.ownerKeyword", { defaultValue: "本方 / 对方" })}
          </Label>
          <Input
            id="sb-owner"
            placeholder={t("billsPanel.ownerKeywordPh", { defaultValue: "玩家账号、代理名称" })}
            value={draft.ownerKeyword}
            onChange={(e) => setDraft((d) => ({ ...d, ownerKeyword: e.target.value }))}
            onKeyDown={(e) => {
              if (e.key === "Enter") {
                runSearch();
              }
            }}
          />
        </div>
        {billTypeOptions.length > 1 ? (
          <div className="admin-list-field">
            <Label htmlFor="sb-type" className="sm:shrink-0">
              {t("billsPanel.billType", { defaultValue: "账单类型" })}
            </Label>
            <Select
              modal={false}
              value={draft.billType}
              onValueChange={(v) =>
                setDraft((d) => ({
                  ...d,
                  billType: (v ?? "all") as BillTypeFilter,
                }))
              }
            >
              <SelectTrigger id="sb-type" className="h-9 w-full sm:w-36">
                <SelectValue>{() => billTypeLabel(draft.billType)}</SelectValue>
              </SelectTrigger>
              <SelectContent>
                {billTypeOptions.map((value) => (
                  <SelectItem key={value} value={value}>
                    {billTypeLabel(value)}
                  </SelectItem>
                ))}
              </SelectContent>
            </Select>
          </div>
        ) : null}
        <div className="admin-list-actions">
          <Button type="button" size="sm" onClick={() => runSearch()}>
            {t("billsPanel.searchBtn", { defaultValue: "搜索" })}
          </Button>
          <Button type="button" size="sm" variant="secondary" onClick={() => resetFilters()}>
            {t("billsPanel.reset", { defaultValue: "重置" })}
          </Button>
          <Button type="button" size="sm" variant="secondary" onClick={() => void load()}>
            {t("billsPanel.refresh", { defaultValue: "刷新" })}
          </Button>
        </div>
      </div>

      {loading && rows.length === 0 ? (
        <AdminLoadingState />
      ) : (
        <>
          {renderBillsTable(rows, emptyBillMessage)}
          <AdminListPaginationFooter
            selectId="settlement-bills-per-page"
            page={page}
            perPage={perPage}
            total={total}
            lastPage={Math.max(1, Math.ceil(total / Math.max(1, perPage)))}
            loading={loading}
            onPageChange={setPage}
            onPerPageChange={(next) => {
              setPerPage(next);
              setPage(1);
            }}
          />
        </>
      )}
    </div>
  );
}
