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

export interface InviteActivityRewardTierDto {
    tierId: number;
    rewardType: string;
    tierCode: string;
    tierName: string;
    thresholdCoinAmount: number;
    thresholdValidInviteCount: number;
    rewardCoinAmount: number;
    status: string;
    sortOrder: number;
    createdAtMs?: number;
    updatedAtMs?: number;
}

export interface InviteActivityRewardConfigDto {
    appCode?: string;
    enabled: boolean;
    perInviteInviterRewardCoinAmount: number;
    perInviteInviteeRewardCoinAmount: number;
    tiers: InviteActivityRewardTierDto[];
    updatedByAdminId?: number;
    createdAtMs?: number;
    updatedAtMs?: number;
}

export interface InviteActivityRewardConfigPayload {
    enabled: boolean;
    per_invite_inviter_reward_coin_amount: number;
    per_invite_invitee_reward_coin_amount: number;
    tiers: Array<{
        tier_id?: number;
        reward_type: string;
        tier_code: string;
        tier_name: string;
        threshold_coin_amount: number;
        threshold_valid_invite_count: number;
        reward_coin_amount: number;
        status: string;
        sort_order: number;
    }>;
}

export interface InviteActivityRewardClaimUserDto {
    userId?: string;
    displayUserId?: string;
    username?: string;
    avatar?: string;
}

export interface InviteActivityRewardClaimDto {
    claimId: string;
    appCode?: string;
    cycleKey?: string;
    userId: string;
    user?: InviteActivityRewardClaimUserDto;
    rewardType?: string;
    commandId?: string;
    tierId?: number;
    tierCode?: string;
    tierName?: string;
    thresholdCoinAmount?: number;
    thresholdValidInviteCount?: number;
    reachedValue?: number;
    rewardCoinAmount?: number;
    status?: string;
    walletCommandId?: string;
    walletTransactionId?: string;
    failureReason?: string;
    grantedAtMs?: number;
    createdAtMs?: number;
    updatedAtMs?: number;
}

export interface InviteActivityRewardInviteeSummaryDto {
    userId: string;
    user?: InviteActivityRewardClaimUserDto;
    rechargeCoinAmount: number;
    invitedAtMs?: number;
}

export interface InviteActivityRewardSummaryDto {
    key: string;
    appCode?: string;
    cycleKey?: string;
    userId: string;
    user?: InviteActivityRewardClaimUserDto;
    inviteCount: number;
    validInviteCount: number;
    totalRechargeCoinAmount: number;
    totalRewardCoinAmount: number;
    updatedAtMs?: number;
    invitees: InviteActivityRewardInviteeSummaryDto[];
}

type RawConfig = InviteActivityRewardConfigDto & Record<string, unknown>;
type RawTier = InviteActivityRewardTierDto & Record<string, unknown>;
type RawClaim = InviteActivityRewardClaimDto & Record<string, unknown>;
type RawInviteeSummary = InviteActivityRewardInviteeSummaryDto & Record<string, unknown>;
type RawSummary = InviteActivityRewardSummaryDto & Record<string, unknown>;

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

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

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

export function listInviteActivityRewardSummaries(
    query: PageQuery = {},
): Promise<ApiPage<InviteActivityRewardSummaryDto>> {
    return apiRequest<ApiPage<RawSummary>>("/v1/admin/activity/invite-reward/summaries", {
        method: "GET",
        query,
    }).then((page) => ({
        ...page,
        items: (page.items || []).map(normalizeSummary),
    }));
}

function normalizeConfig(item: RawConfig): InviteActivityRewardConfigDto {
    const rawTiers = Array.isArray(item.tiers) ? (item.tiers as RawTier[]) : [];
    return {
        appCode: stringValue(item.appCode ?? item.app_code),
        enabled: Boolean(item.enabled),
        perInviteInviterRewardCoinAmount: numberValue(
            item.perInviteInviterRewardCoinAmount ?? item.per_invite_inviter_reward_coin_amount,
        ),
        perInviteInviteeRewardCoinAmount: numberValue(
            item.perInviteInviteeRewardCoinAmount ?? item.per_invite_invitee_reward_coin_amount,
        ),
        tiers: rawTiers.map(normalizeTier),
        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 normalizeTier(item: RawTier): InviteActivityRewardTierDto {
    return {
        tierId: numberValue(item.tierId ?? item.tier_id),
        rewardType: stringValue(item.rewardType ?? item.reward_type),
        tierCode: stringValue(item.tierCode ?? item.tier_code),
        tierName: stringValue(item.tierName ?? item.tier_name),
        thresholdCoinAmount: numberValue(item.thresholdCoinAmount ?? item.threshold_coin_amount),
        thresholdValidInviteCount: numberValue(item.thresholdValidInviteCount ?? item.threshold_valid_invite_count),
        rewardCoinAmount: numberValue(item.rewardCoinAmount ?? item.reward_coin_amount),
        status: stringValue(item.status) || "active",
        sortOrder: numberValue(item.sortOrder ?? item.sort_order),
        createdAtMs: numberValue(item.createdAtMs ?? item.created_at_ms),
        updatedAtMs: numberValue(item.updatedAtMs ?? item.updated_at_ms),
    };
}

function normalizeClaim(item: RawClaim): InviteActivityRewardClaimDto {
    const rawUser = (item.user || {}) as Record<string, unknown>;
    return {
        claimId: stringValue(item.claimId ?? item.claim_id),
        appCode: stringValue(item.appCode ?? item.app_code),
        cycleKey: stringValue(item.cycleKey ?? item.cycle_key),
        userId: stringValue(item.userId ?? item.user_id),
        user: {
            userId: stringValue(rawUser.userId ?? rawUser.user_id),
            displayUserId: stringValue(rawUser.displayUserId ?? rawUser.display_user_id),
            username: stringValue(rawUser.username),
            avatar: stringValue(rawUser.avatar),
        },
        rewardType: stringValue(item.rewardType ?? item.reward_type),
        commandId: stringValue(item.commandId ?? item.command_id),
        tierId: numberValue(item.tierId ?? item.tier_id),
        tierCode: stringValue(item.tierCode ?? item.tier_code),
        tierName: stringValue(item.tierName ?? item.tier_name),
        thresholdCoinAmount: numberValue(item.thresholdCoinAmount ?? item.threshold_coin_amount),
        thresholdValidInviteCount: numberValue(item.thresholdValidInviteCount ?? item.threshold_valid_invite_count),
        reachedValue: numberValue(item.reachedValue ?? item.reached_value),
        rewardCoinAmount: numberValue(item.rewardCoinAmount ?? item.reward_coin_amount),
        status: stringValue(item.status),
        walletCommandId: stringValue(item.walletCommandId ?? item.wallet_command_id),
        walletTransactionId: stringValue(item.walletTransactionId ?? item.wallet_transaction_id),
        failureReason: stringValue(item.failureReason ?? item.failure_reason),
        grantedAtMs: numberValue(item.grantedAtMs ?? item.granted_at_ms),
        createdAtMs: numberValue(item.createdAtMs ?? item.created_at_ms),
        updatedAtMs: numberValue(item.updatedAtMs ?? item.updated_at_ms),
    };
}

function normalizeSummary(item: RawSummary): InviteActivityRewardSummaryDto {
    const rawUser = (item.user || {}) as Record<string, unknown>;
    const rawInvitees = Array.isArray(item.invitees) ? (item.invitees as RawInviteeSummary[]) : [];
    const cycleKey = stringValue(item.cycleKey ?? item.cycle_key);
    const userId = stringValue(item.userId ?? item.user_id);
    return {
        key: `${cycleKey}:${userId}`,
        appCode: stringValue(item.appCode ?? item.app_code),
        cycleKey,
        userId,
        user: normalizeUser(rawUser),
        inviteCount: numberValue(item.inviteCount ?? item.invite_count),
        validInviteCount: numberValue(item.validInviteCount ?? item.valid_invite_count),
        totalRechargeCoinAmount: numberValue(item.totalRechargeCoinAmount ?? item.total_recharge_coin_amount),
        totalRewardCoinAmount: numberValue(item.totalRewardCoinAmount ?? item.total_reward_coin_amount),
        updatedAtMs: numberValue(item.updatedAtMs ?? item.updated_at_ms),
        invitees: rawInvitees.map(normalizeInviteeSummary),
    };
}

function normalizeInviteeSummary(item: RawInviteeSummary): InviteActivityRewardInviteeSummaryDto {
    const rawUser = (item.user || {}) as Record<string, unknown>;
    return {
        userId: stringValue(item.userId ?? item.user_id),
        user: normalizeUser(rawUser),
        rechargeCoinAmount: numberValue(item.rechargeCoinAmount ?? item.recharge_coin_amount),
        invitedAtMs: numberValue(item.invitedAtMs ?? item.invited_at_ms),
    };
}

function normalizeUser(rawUser: Record<string, unknown>): InviteActivityRewardClaimUserDto {
    return {
        userId: stringValue(rawUser.userId ?? rawUser.user_id),
        displayUserId: stringValue(rawUser.displayUserId ?? rawUser.display_user_id),
        username: stringValue(rawUser.username),
        avatar: stringValue(rawUser.avatar),
    };
}

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