import { getMe, refreshSession } from "@/features/auth/api";
import { API_ENDPOINTS, API_OPERATIONS, apiEndpointPath } from "@/shared/api/generated/endpoints";
import { apiRequest, getAccessToken } from "@/shared/api/request";
import { FINANCE_PERMISSIONS } from "./constants.js";
import {
  mergeRechargeOverviews,
  mergeRechargeSummaries,
  normalizeCoinSellerRechargeOrder,
  normalizeCoinSellerRechargeOrderPage,
  normalizeRechargeBillPage,
  normalizeRechargeOverview,
  normalizeRechargeRegions,
  normalizeRechargeSummary,
  normalizeWithdrawalApplicationPage
} from "./format.js";

const appCodeHeader = "X-App-Code";

function normalizeUSDTAddress(item = {}) {
  return {
    address: stringValue(item?.address),
    chain: stringValue(item?.chain).toUpperCase(),
    updatedAtMs: Number(item?.updatedAtMs || 0)
  };
}

export async function fetchFinanceSession() {
  const session = await currentSession();
  const permissions = Array.isArray(session.permissions) ? session.permissions : [];
  const canAuditWithdrawalApplications = permissions.includes(FINANCE_PERMISSIONS.auditWithdrawalApplications);
  const canViewWithdrawalApplications = permissions.includes(FINANCE_PERMISSIONS.viewWithdrawalApplications) || canAuditWithdrawalApplications;
  const canAuditOperationsWithdrawalApplications = permissions.includes(FINANCE_PERMISSIONS.auditOperationsWithdrawalApplications);
  const canViewOperationsWithdrawalApplications = permissions.includes(FINANCE_PERMISSIONS.viewOperationsWithdrawalApplications) || canAuditOperationsWithdrawalApplications;
  const canViewAppRechargeDetails = permissions.includes(FINANCE_PERMISSIONS.viewAppRechargeDetails);
  const canViewCoinSellerRechargeOrders = permissions.includes(FINANCE_PERMISSIONS.viewCoinSellerRechargeOrders);
  const canCreateCoinSellerRechargeOrder = permissions.includes(FINANCE_PERMISSIONS.createCoinSellerRechargeOrder);
  const canVerifyCoinSellerRechargeOrder = permissions.includes(FINANCE_PERMISSIONS.verifyCoinSellerRechargeOrder);
  const canGrantCoinSellerRechargeOrder = permissions.includes(FINANCE_PERMISSIONS.grantCoinSellerRechargeOrder);
  const canUpdateUSDTAddress = permissions.includes(FINANCE_PERMISSIONS.updateUSDTAddress);
  const canConfigureCoinSellerRechargeExchangeRate = permissions.includes(FINANCE_PERMISSIONS.configureCoinSellerRechargeExchangeRate);

  return {
    ...session,
    canAccessFinance:
      canViewWithdrawalApplications ||
      canViewOperationsWithdrawalApplications ||
      canViewAppRechargeDetails ||
      canViewCoinSellerRechargeOrders,
    canAuditOperationsWithdrawalApplications,
    canAuditWithdrawalApplications,
    canConfigureCoinSellerRechargeExchangeRate,
    canCreateCoinSellerRechargeOrder,
    canGrantCoinSellerRechargeOrder,
    canUpdateUSDTAddress,
    canVerifyCoinSellerRechargeOrder,
    canViewAppRechargeDetails,
    canViewCoinSellerRechargeOrders,
    canViewOperationsWithdrawalApplications,
    canViewWithdrawalApplications,
    permissions
  };
}

export async function fetchFinanceOptions() {
  const endpoint = API_ENDPOINTS.listApps;
  const data = await apiRequest(apiEndpointPath(API_OPERATIONS.listApps), {
    method: endpoint.method
  });
  return normalizeOptions({ apps: data });
}

export async function fetchFinanceWithdrawalOptions() {
  const endpoint = API_ENDPOINTS.getFinanceScope;
  const data = await apiRequest(apiEndpointPath(API_OPERATIONS.getFinanceScope), {
    method: endpoint.method
  });
  // 提现是跨 App 财务工作台，目录只能使用后端 MoneyAccess 裁剪后的 apps；
  // 不能回退全量 App 或主站 AppScope，否则“全部 APP”会越过财务范围。
  return normalizeOptions({ apps: data?.apps });
}

// 充值详情的 App 目录与其他财务页不同：包含 Yumi 这类 legacy 外部账单源，只用于账单查询。
export async function fetchFinanceRechargeApps() {
  const endpoint = API_ENDPOINTS.listRechargeApps;
  const data = await apiRequest(apiEndpointPath(API_OPERATIONS.listRechargeApps), {
    method: endpoint.method
  });
  return normalizeApps(data);
}

export async function listFinanceWithdrawalApplications(query = {}) {
  const endpoint = API_ENDPOINTS.listFinanceWithdrawalApplications;
  const data = await apiRequest(apiEndpointPath(API_OPERATIONS.listFinanceWithdrawalApplications), {
    method: endpoint.method,
    query
  });
  return normalizeWithdrawalApplicationPage(data);
}

export async function listOperationsWithdrawalApplications(query = {}) {
  const endpoint = API_ENDPOINTS.listOperationsWithdrawalApplications;
  const data = await apiRequest(apiEndpointPath(API_OPERATIONS.listOperationsWithdrawalApplications), {
    method: endpoint.method,
    query
  });
  return normalizeWithdrawalApplicationPage(data);
}

export async function listFinanceCoinSellerRechargeOrders(query = {}) {
  const endpoint = API_ENDPOINTS.listFinanceCoinSellerRechargeOrders;
  const data = await apiRequest(apiEndpointPath(API_OPERATIONS.listFinanceCoinSellerRechargeOrders), {
    method: endpoint.method,
    query
  });
  return normalizeCoinSellerRechargeOrderPage(data);
}

export async function createFinanceCoinSellerRechargeOrder(payload) {
  const endpoint = API_ENDPOINTS.createFinanceCoinSellerRechargeOrder;
  const data = await apiRequest(apiEndpointPath(API_OPERATIONS.createFinanceCoinSellerRechargeOrder), {
    body: payload,
    method: endpoint.method
  });
  return normalizeCoinSellerRechargeOrder(data);
}

export async function quoteFinanceCoinSellerRechargeOrder(payload) {
  const endpoint = API_ENDPOINTS.quoteFinanceCoinSellerRechargeOrder;
  return apiRequest(apiEndpointPath(API_OPERATIONS.quoteFinanceCoinSellerRechargeOrder), {
    body: cleanPayload(payload),
    method: endpoint.method
  });
}

export async function getFinanceCoinSellerRechargeExchangeRate(appCode) {
  const endpoint = API_ENDPOINTS.getFinanceCoinSellerRechargeExchangeRate;
  return apiRequest(apiEndpointPath(API_OPERATIONS.getFinanceCoinSellerRechargeExchangeRate, { app_code: appCode }), {
    method: endpoint.method
  });
}

export async function getFinanceUSDTAddresses(appCode) {
  const endpoint = API_ENDPOINTS.getFinanceUSDTAddresses;
  const data = await apiRequest(apiEndpointPath(API_OPERATIONS.getFinanceUSDTAddresses, { app_code: appCode }), {
    method: endpoint.method
  });
  return {
    appCode: stringValue(data?.appCode ?? appCode),
    items: listItems(data?.items)
      .map(normalizeUSDTAddress)
      .filter((item) => item.address && item.chain)
  };
}

export async function upsertFinanceUSDTAddress(appCode, chain, payload) {
  const endpoint = API_ENDPOINTS.upsertFinanceUSDTAddress;
  const data = await apiRequest(apiEndpointPath(API_OPERATIONS.upsertFinanceUSDTAddress, {
    app_code: appCode,
    chain
  }), {
    body: { address: stringValue(payload?.address) },
    method: endpoint.method
  });
  return {
    ...normalizeUSDTAddress(data),
    appCode: stringValue(data?.appCode ?? appCode)
  };
}

export async function replaceFinanceCoinSellerRechargeExchangeRate(appCode, payload) {
  const endpoint = API_ENDPOINTS.replaceFinanceCoinSellerRechargeExchangeRate;
  return apiRequest(apiEndpointPath(API_OPERATIONS.replaceFinanceCoinSellerRechargeExchangeRate, { app_code: appCode }), {
    body: cleanPayload(payload),
    method: endpoint.method
  });
}

export async function verifyFinanceCoinSellerRechargeReceipt(payload) {
  const endpoint = API_ENDPOINTS.verifyFinanceCoinSellerRechargeReceipt;
  return apiRequest(apiEndpointPath(API_OPERATIONS.verifyFinanceCoinSellerRechargeReceipt), {
    body: cleanPayload(payload),
    method: endpoint.method
  });
}

export async function verifyFinanceCoinSellerRechargeOrder(orderId) {
  const endpoint = API_ENDPOINTS.verifyFinanceCoinSellerRechargeOrder;
  const data = await apiRequest(apiEndpointPath(API_OPERATIONS.verifyFinanceCoinSellerRechargeOrder, { order_id: orderId }), {
    method: endpoint.method
  });
  return normalizeCoinSellerRechargeOrder(data);
}

export async function grantFinanceCoinSellerRechargeOrder(orderId) {
  const endpoint = API_ENDPOINTS.grantFinanceCoinSellerRechargeOrder;
  const data = await apiRequest(apiEndpointPath(API_OPERATIONS.grantFinanceCoinSellerRechargeOrder, { order_id: orderId }), {
    method: endpoint.method
  });
  return normalizeCoinSellerRechargeOrder(data);
}

export async function listFinanceRechargeDetails(query = {}, apps = []) {
  const page = positiveInteger(query.page, 1);
  const pageSize = positiveInteger(query.page_size ?? query.pageSize, 50);
  const selectedAppCode = stringValue(query.app_code ?? query.appCode);
  const cleanQuery = cleanRechargeBillQuery(query);

  if (selectedAppCode) {
    const data = await listRechargeBillsForApp(selectedAppCode, { ...cleanQuery, page, page_size: pageSize });
    return { ...data, page, pageSize };
  }

  const appCodes = normalizeApps(apps).map((app) => app.appCode);
  if (!appCodes.length) {
    return { items: [], page, pageSize, total: 0 };
  }

  const mergedPageSize = page * pageSize;
  const pageResults = await Promise.allSettled(
    appCodes.map((appCode) => listRechargeBillsForApp(appCode, { ...cleanQuery, page: 1, page_size: mergedPageSize }))
  );
  const pages = pageResults.filter((result) => result.status === "fulfilled").map((result) => result.value);
  const items = pages
    .flatMap((data) => data.items || [])
    .sort((left, right) => (right.createdAtMs || 0) - (left.createdAtMs || 0) || String(right.transactionId).localeCompare(String(left.transactionId)));
  const start = (page - 1) * pageSize;

  return {
    items: items.slice(start, start + pageSize),
    page,
    pageSize,
    total: pages.reduce((sum, data) => sum + Number(data.total || 0), 0)
  };
}

export async function fetchFinanceRechargeSummary(query = {}, apps = []) {
  const selectedAppCode = stringValue(query.app_code ?? query.appCode);
  const cleanQuery = cleanRechargeBillQuery(query);

  if (selectedAppCode) {
    return getRechargeSummaryForApp(selectedAppCode, cleanQuery);
  }

  const appCodes = normalizeApps(apps).map((app) => app.appCode);
  if (!appCodes.length) {
    return mergeRechargeSummaries([]);
  }
  const summaries = await Promise.all(appCodes.map((appCode) => getRechargeSummaryForApp(appCode, cleanQuery)));
  return mergeRechargeSummaries(summaries);
}

export async function listFinanceRechargeRegions(appCode) {
  const endpoint = API_ENDPOINTS.listRechargeRegions;
  const data = await apiRequest(apiEndpointPath(API_OPERATIONS.listRechargeRegions), {
    headers: { [appCodeHeader]: appCode },
    method: endpoint.method
  });
  return normalizeRechargeRegions(data);
}

// fetchFinanceRechargeSummaries 返回逐 App 的汇总（App 对比表用）和全局合并值。
export async function fetchFinanceRechargeSummaries(query = {}, apps = []) {
  const selectedAppCode = stringValue(query.app_code ?? query.appCode);
  const cleanQuery = cleanRechargeBillQuery(query);
  const appList = selectedAppCode
    ? normalizeApps(apps).filter((app) => app.appCode === selectedAppCode)
    : normalizeApps(apps);
  if (!appList.length && selectedAppCode) {
    appList.push({ appCode: selectedAppCode, appName: selectedAppCode });
  }
  // 单个 App 查询失败（如后端灰度中）按空汇总降级，不拖垮其余 App 的数据。
  const results = await Promise.allSettled(appList.map((app) => getRechargeSummaryForApp(app.appCode, cleanQuery)));
  const summaries = results.map((result) =>
    result.status === "fulfilled" ? result.value : normalizeRechargeSummary({})
  );
  const perApp = appList.map((app, index) => ({ ...app, summary: summaries[index] }));
  return { merged: mergeRechargeSummaries(summaries), perApp };
}

export async function fetchFinanceRechargeOverview(query = {}, apps = []) {
  const selectedAppCode = stringValue(query.app_code ?? query.appCode);
  const cleanQuery = { ...cleanRechargeBillQuery(query), tz_offset_minutes: 480 };
  if (selectedAppCode) {
    return getRechargeOverviewForApp(selectedAppCode, cleanQuery);
  }
  const appCodes = normalizeApps(apps).map((app) => app.appCode);
  if (!appCodes.length) {
    return normalizeRechargeOverview({});
  }
  const results = await Promise.allSettled(appCodes.map((appCode) => getRechargeOverviewForApp(appCode, cleanQuery)));
  return mergeRechargeOverviews(
    results.filter((result) => result.status === "fulfilled").map((result) => result.value)
  );
}

export async function exportFinanceRechargeBills(appCode, query = {}) {
  const endpoint = API_ENDPOINTS.exportRechargeBills;
  return apiRequest(apiEndpointPath(API_OPERATIONS.exportRechargeBills), {
    headers: { [appCodeHeader]: appCode },
    method: endpoint.method,
    query: cleanRechargeBillQuery(query),
    raw: true
  });
}

export async function refreshFinanceGoogleRechargePaid(appCode, transactionIds) {
  const endpoint = API_ENDPOINTS.refreshGoogleRechargePaid;
  const data = await apiRequest(apiEndpointPath(API_OPERATIONS.refreshGoogleRechargePaid), {
    body: { transactionIds },
    headers: { [appCodeHeader]: appCode },
    method: endpoint.method
  });
  return Array.isArray(data?.items) ? data.items : [];
}

export async function approveFinanceWithdrawalApplication(applicationId, appCode, payload) {
  const endpoint = API_ENDPOINTS.approveFinanceWithdrawalApplication;
  return apiRequest(apiEndpointPath(API_OPERATIONS.approveFinanceWithdrawalApplication, { application_id: applicationId }), {
    body: payload,
    // 审核对象可能来自跨 App 列表；必须用记录所属 App 覆盖主站全局选择，避免按错误 App 锁单和执行钱包命令。
    headers: { [appCodeHeader]: appCode },
    method: endpoint.method
  });
}

export async function rejectFinanceWithdrawalApplication(applicationId, appCode, payload) {
  const endpoint = API_ENDPOINTS.rejectFinanceWithdrawalApplication;
  return apiRequest(apiEndpointPath(API_OPERATIONS.rejectFinanceWithdrawalApplication, { application_id: applicationId }), {
    body: payload,
    headers: { [appCodeHeader]: appCode },
    method: endpoint.method
  });
}

export async function approveOperationsWithdrawalApplication(applicationId, appCode, payload) {
  const endpoint = API_ENDPOINTS.approveOperationsWithdrawalApplication;
  return apiRequest(apiEndpointPath(API_OPERATIONS.approveOperationsWithdrawalApplication, { application_id: applicationId }), {
    body: payload,
    headers: { [appCodeHeader]: appCode },
    method: endpoint.method
  });
}

export async function rejectOperationsWithdrawalApplication(applicationId, appCode, payload) {
  const endpoint = API_ENDPOINTS.rejectOperationsWithdrawalApplication;
  return apiRequest(apiEndpointPath(API_OPERATIONS.rejectOperationsWithdrawalApplication, { application_id: applicationId }), {
    body: payload,
    headers: { [appCodeHeader]: appCode },
    method: endpoint.method
  });
}

async function currentSession() {
  try {
    return await refreshSession();
  } catch {
    if (getAccessToken()) {
      return getMe();
    }
    throw new Error("登录已失效");
  }
}

async function getRechargeOverviewForApp(appCode, query = {}) {
  const endpoint = API_ENDPOINTS.getRechargeBillOverview;
  const data = await apiRequest(apiEndpointPath(API_OPERATIONS.getRechargeBillOverview), {
    headers: { [appCodeHeader]: appCode },
    method: endpoint.method,
    query
  });
  return normalizeRechargeOverview(data);
}

async function getRechargeSummaryForApp(appCode, query = {}) {
  const endpoint = API_ENDPOINTS.getRechargeBillSummary;
  const data = await apiRequest(apiEndpointPath(API_OPERATIONS.getRechargeBillSummary), {
    headers: { [appCodeHeader]: appCode },
    method: endpoint.method,
    query
  });
  return normalizeRechargeSummary(data);
}

async function listRechargeBillsForApp(appCode, query = {}) {
  const endpoint = API_ENDPOINTS.listRechargeBills;
  const data = await apiRequest(apiEndpointPath(API_OPERATIONS.listRechargeBills), {
    headers: { [appCodeHeader]: appCode },
    method: endpoint.method,
    query
  });
  return normalizeRechargeBillPage(data);
}

function normalizeOptions(data = {}) {
  return {
    apps: normalizeApps(data.apps)
  };
}

function normalizeApps(data) {
  return listItems(data)
    .map((item) => {
      const appCode = stringValue(item.appCode ?? item.app_code ?? item.code);
      if (!appCode) {
        return null;
      }
      return {
        appCode,
        appName: stringValue(item.appName ?? item.app_name ?? item.name) || appCode,
        logoUrl: stringValue(item.logoUrl ?? item.logo_url)
      };
    })
    .filter(Boolean);
}

function listItems(data) {
  if (Array.isArray(data)) {
    return data;
  }
  if (Array.isArray(data?.items)) {
    return data.items;
  }
  return [];
}

function cleanRechargeBillQuery(query = {}) {
  const {
    app_code: _appCode,
    appCode: _camelAppCode,
    page: _page,
    page_size: _pageSize,
    pageSize: _camelPageSize,
    ...rest
  } = query;
  return rest;
}

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

function positiveInteger(value, fallback) {
  const number = Number(value);
  return Number.isInteger(number) && number > 0 ? number : fallback;
}

function stringValue(value) {
  return String(value ?? "").trim();
}
