import { API_ENDPOINTS, API_OPERATIONS, apiEndpointPath } from "@/shared/api/generated/endpoints";
import { apiRequest } from "@/shared/api/request";
import type { ApiPage, PageQuery } from "@/shared/api/types";

export interface RedPacketConfigDto {
    appCode?: string;
    enabled: boolean;
    countTiers: number[];
    amountTiers: number[];
    delayedOpenSeconds: number;
    expireSeconds: number;
    dailySendLimit: number;
    ruleUrl?: string;
    updatedByAdminId?: number;
    createdAtMs?: number;
    updatedAtMs?: number;
}

export interface RedPacketConfigPayload {
    enabled: boolean;
    count_tiers: number[];
    amount_tiers: number[];
    delayed_open_seconds: number;
    expire_seconds?: number;
    daily_send_limit: number;
    rule_url?: string;
}

export interface RedPacketClaimDto {
    claimId: string;
    commandId?: string;
    packetId: string;
    userId: string;
    amount: number;
    walletTransactionId?: string;
    status?: string;
    failureReason?: string;
    createdAtMs?: number;
    updatedAtMs?: number;
}

export interface RedPacketDto {
    appCode?: string;
    packetId: string;
    commandId?: string;
    senderUserId: string;
    roomId: string;
    regionId: number;
    packetType: string;
    totalAmount: number;
    packetCount: number;
    remainingAmount: number;
    remainingCount: number;
    status: string;
    openAtMs: number;
    expiresAtMs: number;
    createdAtMs: number;
    updatedAtMs?: number;
    refundAmount?: number;
    refundStatus?: string;
    refundedAtMs?: number;
    claims?: RedPacketClaimDto[];
}

export interface RedPacketQuery extends PageQuery {
    roomId?: string;
    senderUserId?: string;
    region_id?: string;
    packetMode?: string;
    status?: string;
    startTime?: string;
    endTime?: string;
}

type RawConfig = RedPacketConfigDto & Record<string, unknown>;
type RawPacket = RedPacketDto & Record<string, unknown>;
type RawClaim = RedPacketClaimDto & Record<string, unknown>;

export function getRedPacketConfig(): Promise<RedPacketConfigDto> {
    const endpoint = API_ENDPOINTS.getRedPacketConfig;
    return apiRequest<RawConfig>(apiEndpointPath(API_OPERATIONS.getRedPacketConfig), {
        method: endpoint.method,
    }).then(normalizeConfig);
}

export function updateRedPacketConfig(payload: RedPacketConfigPayload): Promise<RedPacketConfigDto> {
    const endpoint = API_ENDPOINTS.updateRedPacketConfig;
    return apiRequest<RawConfig, RedPacketConfigPayload>(apiEndpointPath(API_OPERATIONS.updateRedPacketConfig), {
        body: payload,
        method: endpoint.method,
    }).then(normalizeConfig);
}

export function listRedPackets(query: RedPacketQuery = {}): Promise<ApiPage<RedPacketDto>> {
    const endpoint = API_ENDPOINTS.listRedPackets;
    return apiRequest<ApiPage<RawPacket>>(apiEndpointPath(API_OPERATIONS.listRedPackets), {
        method: endpoint.method,
        query,
    }).then((page) => ({
        ...page,
        items: (page.items || []).map(normalizePacket),
    }));
}

export function getRedPacket(packetId: string): Promise<RedPacketDto> {
    const endpoint = API_ENDPOINTS.getRedPacket;
    return apiRequest<RawPacket>(apiEndpointPath(API_OPERATIONS.getRedPacket, { packet_id: packetId }), {
        method: endpoint.method,
    }).then(normalizePacket);
}

export function retryRedPacketRefund(packetId: string): Promise<unknown> {
    const endpoint = API_ENDPOINTS.retryRedPacketRefund;
    return apiRequest(apiEndpointPath(API_OPERATIONS.retryRedPacketRefund), {
        body: { packetNo: packetId },
        method: endpoint.method,
    });
}

function normalizeConfig(item: RawConfig): RedPacketConfigDto {
    return {
        appCode: stringValue(item.appCode ?? item.app_code),
        enabled: Boolean(item.enabled),
        countTiers: numberArray(item.countTiers ?? item.count_tiers),
        amountTiers: numberArray(item.amountTiers ?? item.amount_tiers),
        delayedOpenSeconds: numberValue(item.delayedOpenSeconds ?? item.delayed_open_seconds),
        expireSeconds: numberValue(item.expireSeconds ?? item.expire_seconds),
        dailySendLimit: numberValue(item.dailySendLimit ?? item.daily_send_limit),
        ruleUrl: stringValue(item.ruleUrl ?? item.rule_url),
        updatedByAdminId: numberValue(item.updatedByAdminId ?? item.updated_by_admin_id),
        createdAtMs: numberValue(item.createdAtMs ?? item.created_at_ms),
        updatedAtMs: numberValue(item.updatedAtMs ?? item.updated_at_ms),
    };
}

function normalizePacket(item: RawPacket): RedPacketDto {
    const rawClaims = Array.isArray(item.claims) ? (item.claims as RawClaim[]) : [];
    return {
        appCode: stringValue(item.appCode ?? item.app_code),
        packetId: stringValue(item.packetId ?? item.packet_id),
        commandId: stringValue(item.commandId ?? item.command_id),
        senderUserId: stringValue(item.senderUserId ?? item.sender_user_id),
        roomId: stringValue(item.roomId ?? item.room_id),
        regionId: numberValue(item.regionId ?? item.region_id),
        packetType: stringValue(item.packetType ?? item.packet_type),
        totalAmount: numberValue(item.totalAmount ?? item.total_amount),
        packetCount: numberValue(item.packetCount ?? item.packet_count),
        remainingAmount: numberValue(item.remainingAmount ?? item.remaining_amount),
        remainingCount: numberValue(item.remainingCount ?? item.remaining_count),
        status: stringValue(item.status),
        openAtMs: numberValue(item.openAtMs ?? item.open_at_ms),
        expiresAtMs: numberValue(item.expiresAtMs ?? item.expires_at_ms),
        createdAtMs: numberValue(item.createdAtMs ?? item.created_at_ms),
        updatedAtMs: numberValue(item.updatedAtMs ?? item.updated_at_ms),
        refundAmount: numberValue(item.refundAmount ?? item.refund_amount),
        refundStatus: stringValue(item.refundStatus ?? item.refund_status),
        refundedAtMs: numberValue(item.refundedAtMs ?? item.refunded_at_ms),
        claims: rawClaims.map(normalizeClaim),
    };
}

function normalizeClaim(item: RawClaim): RedPacketClaimDto {
    return {
        claimId: stringValue(item.claimId ?? item.claim_id),
        commandId: stringValue(item.commandId ?? item.command_id),
        packetId: stringValue(item.packetId ?? item.packet_id),
        userId: stringValue(item.userId ?? item.user_id),
        amount: numberValue(item.amount),
        walletTransactionId: stringValue(item.walletTransactionId ?? item.wallet_transaction_id),
        status: stringValue(item.status),
        failureReason: stringValue(item.failureReason ?? item.failure_reason),
        createdAtMs: numberValue(item.createdAtMs ?? item.created_at_ms),
        updatedAtMs: numberValue(item.updatedAtMs ?? item.updated_at_ms),
    };
}

function numberArray(value: unknown): number[] {
    if (!Array.isArray(value)) {
        return [];
    }
    return value.map(numberValue).filter((item) => item > 0);
}

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;
}
