import { apiRequest } from "@/shared/api/request";
import { API_ENDPOINTS, API_OPERATIONS, apiEndpointPath } from "@/shared/api/generated/endpoints";
import type {
    ApiPage,
    CoinAdjustmentCreateDto,
    CoinAdjustmentDto,
    CoinAdjustmentPayload,
    CoinLedgerEntryDto,
    CoinLedgerUserDto,
    CoinSellerLedgerDto,
    PageQuery,
    ReportDto,
} from "@/shared/api/types";

export interface GiftDiamondRatioItem {
    effectiveRegionId: number;
    giftTypeCode: string;
    ratioPercent: string;
    returnCoinRatioPercent: string;
    regionId: number;
    status: string;
    updatedAtMs?: number;
}

export interface GiftRecordUserDto {
    userId: string;
    displayUserId?: string;
    defaultDisplayUserId?: string;
    prettyDisplayUserId?: string;
    prettyId?: string;
    username?: string;
    avatar?: string;
}

export interface GiftRecordDto {
    transactionId: string;
    scene: "room" | "direct";
    roomId?: string;
    sender: GiftRecordUserDto;
    receiver: GiftRecordUserDto;
    gift: {
        giftId: string;
        name: string;
        coverUrl?: string;
    };
    giftCount: number;
    unitValue: number;
    giftValue: number;
    createdAtMs: number;
}

export interface GiftDiamondRatioResponse {
    regionId: number;
    items: GiftDiamondRatioItem[];
}

export type WheelRewardType = "coin" | "dress" | "gift" | "prop";

export interface WheelTierDto {
    tierId: string;
    displayName: string;
    rewardType: WheelRewardType;
    rewardId: string;
    rewardCount: number;
    rewardCoins: number;
    rtpValueCoins: number;
    probabilityPercent: number;
    enabled: boolean;
    metadataJson: string;
}

export interface WheelConfigDto {
    appCode?: string;
    wheelId: string;
    enabled: boolean;
    ruleVersion: number;
    drawPriceCoins: number;
    targetRTPPercent: number;
    poolRatePercent: number;
    settlementWindowDraws: number;
    initialPoolCoins: number;
    poolReserveCoins: number;
    maxSingleRTPPayout: number;
    effectiveFromMs: number;
    createdByAdminId?: number;
    createdAtMs?: number;
    tiers: WheelTierDto[];
}

export interface WheelConfigPayload {
    wheel_id: string;
    enabled: boolean;
    draw_price_coins: number;
    target_rtp_percent: number;
    pool_rate_percent: number;
    settlement_window_draws: number;
    initial_pool_coins: number;
    pool_reserve_coins: number;
    max_single_rtp_payout: number;
    effective_from_ms: number;
    tiers: Array<{
        tier_id: string;
        display_name: string;
        reward_type: WheelRewardType;
        reward_id: string;
        reward_count: number;
        reward_coins: number;
        rtp_value_coins: number;
        probability_percent: number;
        enabled: boolean;
        metadata_json: string;
    }>;
}

export interface WheelDrawDto {
    drawId: string;
    drawIds: string[];
    commandId: string;
    wheelId: string;
    ruleVersion: number;
    selectedTierId: string;
    rewardType: string;
    rewardId: string;
    rewardCount: number;
    rewardCoins: number;
    rtpValueCoins: number;
    rewardStatus: string;
    rtpWindowIndex: number;
    actualRTPPPM: number;
    createdAtMs: number;
    walletTransactionId: string;
    coinBalanceAfter: number;
    metadataJson: string;
}

export interface WheelDrawSummaryDto {
    wheelId: string;
    totalDraws: number;
    uniqueUsers: number;
    totalSpentCoins: number;
    totalRTPValueCoins: number;
    actualRTPPPM: number;
    pendingDraws: number;
    grantedDraws: number;
    failedDraws: number;
}

type RawWheelConfig = WheelConfigDto & Record<string, unknown>;
type RawWheelTier = WheelTierDto & Record<string, unknown>;
type RawWheelDraw = WheelDrawDto & Record<string, unknown>;
type RawWheelSummary = WheelDrawSummaryDto & Record<string, unknown>;
type WheelSummaryQuery = Record<string, number | string | undefined>;

export function listCoinLedger(query: PageQuery = {}): Promise<ApiPage<CoinLedgerEntryDto>> {
    const endpoint = API_ENDPOINTS.listCoinLedger;
    return apiRequest<ApiPage<CoinLedgerEntryDto>>(apiEndpointPath(API_OPERATIONS.listCoinLedger), {
        method: endpoint.method,
        query,
    });
}

export function listGiftRecords(query: PageQuery = {}): Promise<ApiPage<GiftRecordDto>> {
    const endpoint = API_ENDPOINTS.listGiftRecords;
    return apiRequest<ApiPage<GiftRecordDto>>(apiEndpointPath(API_OPERATIONS.listGiftRecords), {
        method: endpoint.method,
        query,
    });
}

export function listCoinSellerLedger(query: PageQuery = {}): Promise<ApiPage<CoinSellerLedgerDto>> {
    const endpoint = API_ENDPOINTS.listCoinSellerLedger;
    return apiRequest<ApiPage<CoinSellerLedgerDto>>(apiEndpointPath(API_OPERATIONS.listCoinSellerLedger), {
        method: endpoint.method,
        query,
    });
}

export function exportCoinSellerLedger(query: PageQuery = {}): Promise<Response> {
    const endpoint = API_ENDPOINTS.exportCoinSellerLedger;
    return apiRequest(apiEndpointPath(API_OPERATIONS.exportCoinSellerLedger), {
        method: endpoint.method,
        query,
        raw: true,
    });
}

export function listCoinAdjustments(query: PageQuery = {}): Promise<ApiPage<CoinAdjustmentDto>> {
    const endpoint = API_ENDPOINTS.listCoinAdjustments;
    return apiRequest<ApiPage<CoinAdjustmentDto>>(apiEndpointPath(API_OPERATIONS.listCoinAdjustments), {
        method: endpoint.method,
        query,
    });
}

export function listReports(query: PageQuery = {}): Promise<ApiPage<ReportDto>> {
    const endpoint = API_ENDPOINTS.listReports;
    return apiRequest<ApiPage<ReportDto>>(apiEndpointPath(API_OPERATIONS.listReports), {
        method: endpoint.method,
        query,
    });
}

export function lookupCoinAdjustmentTarget(userId: string): Promise<CoinLedgerUserDto> {
    const endpoint = API_ENDPOINTS.lookupCoinAdjustmentTarget;
    return apiRequest<CoinLedgerUserDto>(apiEndpointPath(API_OPERATIONS.lookupCoinAdjustmentTarget), {
        method: endpoint.method,
        query: { user_id: userId },
    });
}

export function createCoinAdjustment(payload: CoinAdjustmentPayload): Promise<CoinAdjustmentCreateDto> {
    const endpoint = API_ENDPOINTS.createCoinAdjustment;
    return apiRequest<CoinAdjustmentCreateDto, CoinAdjustmentPayload>(
        apiEndpointPath(API_OPERATIONS.createCoinAdjustment),
        {
            body: payload,
            method: endpoint.method,
        },
    );
}

export function getGiftDiamondRatios(regionId: string | number): Promise<GiftDiamondRatioResponse> {
    return apiRequest<GiftDiamondRatioResponse>("/v1/admin/operations/gift-diamond-ratios", {
        method: "GET",
        query: { region_id: regionId },
    });
}

export function updateGiftDiamondRatios(payload: {
    regionId: number;
    ratios: Record<string, string>;
    returnCoinRatios: Record<string, string>;
}): Promise<GiftDiamondRatioResponse> {
    return apiRequest<GiftDiamondRatioResponse, typeof payload>("/v1/admin/operations/gift-diamond-ratios", {
        body: payload,
        method: "PUT",
    });
}

export function getWheelConfig(wheelId = "default"): Promise<WheelConfigDto> {
    const endpoint = API_ENDPOINTS.getWheelConfig;
    return apiRequest<RawWheelConfig>(apiEndpointPath(API_OPERATIONS.getWheelConfig), {
        method: endpoint.method,
        query: { wheel_id: wheelId },
    }).then(normalizeWheelConfig);
}

export function updateWheelConfig(payload: WheelConfigPayload): Promise<WheelConfigDto> {
    const endpoint = API_ENDPOINTS.upsertWheelConfig;
    return apiRequest<RawWheelConfig, WheelConfigPayload>(apiEndpointPath(API_OPERATIONS.upsertWheelConfig), {
        body: payload,
        method: endpoint.method,
        query: { wheel_id: payload.wheel_id },
    }).then(normalizeWheelConfig);
}

export function listWheelDraws(query: PageQuery = {}): Promise<ApiPage<WheelDrawDto>> {
    const endpoint = API_ENDPOINTS.listWheelDraws;
    return apiRequest<ApiPage<RawWheelDraw>>(apiEndpointPath(API_OPERATIONS.listWheelDraws), {
        method: endpoint.method,
        query,
    }).then((page) => ({
        ...page,
        items: (page.items || []).map(normalizeWheelDraw),
    }));
}

export function getWheelDrawSummary(query: WheelSummaryQuery = {}): Promise<WheelDrawSummaryDto> {
    const endpoint = API_ENDPOINTS.getWheelDrawSummary;
    return apiRequest<RawWheelSummary>(apiEndpointPath(API_OPERATIONS.getWheelDrawSummary), {
        method: endpoint.method,
        query,
    }).then(normalizeWheelSummary);
}

function normalizeWheelConfig(item: RawWheelConfig): WheelConfigDto {
    // 后端为了兼容 Go DTO 使用 snake_case；页面统一消费 camelCase，
    // 避免表单、表格、保存 payload 混用两套字段名导致配置保存缺字段。
    return {
        appCode: stringValue(item.appCode ?? item.app_code),
        createdAtMs: numberValue(item.createdAtMs ?? item.created_at_ms),
        createdByAdminId: numberValue(item.createdByAdminId ?? item.created_by_admin_id),
        drawPriceCoins: numberValue(item.drawPriceCoins ?? item.draw_price_coins),
        effectiveFromMs: numberValue(item.effectiveFromMs ?? item.effective_from_ms),
        enabled: booleanValue(item.enabled),
        initialPoolCoins: numberValue(item.initialPoolCoins ?? item.initial_pool_coins),
        maxSingleRTPPayout: numberValue(item.maxSingleRTPPayout ?? item.max_single_rtp_payout),
        poolRatePercent: numberValue(item.poolRatePercent ?? item.pool_rate_percent),
        poolReserveCoins: numberValue(item.poolReserveCoins ?? item.pool_reserve_coins),
        ruleVersion: numberValue(item.ruleVersion ?? item.rule_version),
        settlementWindowDraws: numberValue(item.settlementWindowDraws ?? item.settlement_window_draws),
        targetRTPPercent: numberValue(item.targetRTPPercent ?? item.target_rtp_percent),
        tiers: arrayValue(item.tiers).map(normalizeWheelTier),
        wheelId: stringValue(item.wheelId ?? item.wheel_id),
    };
}

function normalizeWheelTier(raw: unknown): WheelTierDto {
    const item = asRecord(raw) as RawWheelTier;
    const rewardType = normalizeRewardType(item.rewardType ?? item.reward_type);
    return {
        displayName: stringValue(item.displayName ?? item.display_name),
        enabled: booleanValue(item.enabled),
        metadataJson: stringValue(item.metadataJson ?? item.metadata_json) || "{}",
        probabilityPercent: numberValue(item.probabilityPercent ?? item.probability_percent),
        rewardCoins: numberValue(item.rewardCoins ?? item.reward_coins),
        rewardCount: numberValue(item.rewardCount ?? item.reward_count),
        rewardId: stringValue(item.rewardId ?? item.reward_id),
        rewardType,
        rtpValueCoins:
            rewardType === "prop" || rewardType === "dress"
                ? 0
                : numberValue(item.rtpValueCoins ?? item.rtp_value_coins),
        tierId: stringValue(item.tierId ?? item.tier_id) || rewardType,
    };
}

function normalizeWheelDraw(item: RawWheelDraw): WheelDrawDto {
    return {
        actualRTPPPM: numberValue(item.actualRTPPPM ?? item.actual_rtp_ppm),
        coinBalanceAfter: numberValue(item.coinBalanceAfter ?? item.coin_balance_after),
        commandId: stringValue(item.commandId ?? item.command_id),
        createdAtMs: numberValue(item.createdAtMs ?? item.created_at_ms),
        drawId: stringValue(item.drawId ?? item.draw_id),
        drawIds: arrayValue(item.drawIds ?? item.draw_ids).map(stringValue),
        metadataJson: stringValue(item.metadataJson ?? item.metadata_json) || "{}",
        rewardCoins: numberValue(item.rewardCoins ?? item.reward_coins),
        rewardCount: numberValue(item.rewardCount ?? item.reward_count),
        rewardId: stringValue(item.rewardId ?? item.reward_id),
        rewardStatus: stringValue(item.rewardStatus ?? item.reward_status),
        rewardType: stringValue(item.rewardType ?? item.reward_type),
        rtpValueCoins: numberValue(item.rtpValueCoins ?? item.rtp_value_coins),
        rtpWindowIndex: numberValue(item.rtpWindowIndex ?? item.rtp_window_index),
        ruleVersion: numberValue(item.ruleVersion ?? item.rule_version),
        selectedTierId: stringValue(item.selectedTierId ?? item.selected_tier_id),
        walletTransactionId: stringValue(item.walletTransactionId ?? item.wallet_transaction_id),
        wheelId: stringValue(item.wheelId ?? item.wheel_id),
    };
}

function normalizeWheelSummary(item: RawWheelSummary): WheelDrawSummaryDto {
    return {
        actualRTPPPM: numberValue(item.actualRTPPPM ?? item.actual_rtp_ppm),
        failedDraws: numberValue(item.failedDraws ?? item.failed_draws),
        grantedDraws: numberValue(item.grantedDraws ?? item.granted_draws),
        pendingDraws: numberValue(item.pendingDraws ?? item.pending_draws),
        totalDraws: numberValue(item.totalDraws ?? item.total_draws),
        totalRTPValueCoins: numberValue(item.totalRTPValueCoins ?? item.total_rtp_value_coins),
        totalSpentCoins: numberValue(item.totalSpentCoins ?? item.total_spent_coins),
        uniqueUsers: numberValue(item.uniqueUsers ?? item.unique_users),
        wheelId: stringValue(item.wheelId ?? item.wheel_id),
    };
}

function asRecord(value: unknown): Record<string, unknown> {
    return value && typeof value === "object" && !Array.isArray(value) ? (value as Record<string, unknown>) : {};
}

function arrayValue(value: unknown): unknown[] {
    return Array.isArray(value) ? value : [];
}

function booleanValue(value: unknown) {
    return value === true || value === "true" || value === 1 || value === "1";
}

function normalizeRewardType(value: unknown): WheelRewardType {
    const normalized = stringValue(value).trim().toLowerCase();
    if (normalized === "dress" || normalized === "gift" || normalized === "prop") {
        return normalized;
    }
    return "coin";
}

function stringValue(value: unknown) {
    return typeof value === "string" ? value : value === undefined || value === null ? "" : String(value);
}

function numberValue(value: unknown) {
    const number = Number(value || 0);
    return Number.isFinite(number) ? number : 0;
}
