import { apiRequest, type QueryParams } from "@/shared/api/request";
import { API_ENDPOINTS } from "@/shared/api/generated/endpoints";

export interface CPWeeklyRankRewardDto {
    rankNo: number;
    resourceGroupId: number;
}

export interface CPWeeklyRankConfigDto {
    appCode: string;
    activityCode: string;
    enabled: boolean;
    relationType: string;
    topCount: number;
    rewards: CPWeeklyRankRewardDto[];
    updatedByAdminId?: number;
    createdAtMs?: number;
    updatedAtMs?: number;
}

export interface CPWeeklyRankConfigPayload {
    enabled: boolean;
    top_count: number;
    rewards: Array<{
        rank_no: number;
        resource_group_id: number;
    }>;
}

export interface CPWeeklyRankSettlementDto {
    settlementId: string;
    periodStartMs: number;
    periodEndMs: number;
    rankNo: number;
    relationshipId: string;
    userId: string;
    score: number;
    resourceGroupId: number;
    walletCommandId: string;
    walletGrantId: string;
    status: string;
    failureReason: string;
    attemptCount: number;
    createdAtMs: number;
    updatedAtMs: number;
}

type Raw = Record<string, unknown>;

export function getCPWeeklyRankConfig(): Promise<CPWeeklyRankConfigDto> {
    const endpoint = API_ENDPOINTS.getCPWeeklyRankConfig;
    return apiRequest<Raw>(endpoint.path, { method: endpoint.method }).then(normalizeConfig);
}

export function updateCPWeeklyRankConfig(payload: CPWeeklyRankConfigPayload): Promise<CPWeeklyRankConfigDto> {
    const endpoint = API_ENDPOINTS.updateCPWeeklyRankConfig;
    return apiRequest<Raw, CPWeeklyRankConfigPayload>(endpoint.path, {
        body: payload,
        method: endpoint.method,
    }).then(normalizeConfig);
}

export function listCPWeeklyRankSettlements(query: QueryParams = {}) {
    const endpoint = API_ENDPOINTS.listCPWeeklyRankSettlements;
    return apiRequest<{ items?: Raw[]; total?: number }>(endpoint.path, { method: endpoint.method, query }).then(
        (page) => ({
            items: (page.items || []).map(normalizeSettlement),
            total: numberValue(page.total),
        }),
    );
}

function normalizeConfig(raw: Raw): CPWeeklyRankConfigDto {
    return {
        appCode: stringValue(raw.appCode ?? raw.app_code),
        activityCode: stringValue(raw.activityCode ?? raw.activity_code) || "cp_weekly_rank",
        enabled: raw.enabled !== false,
        relationType: stringValue(raw.relationType ?? raw.relation_type) || "cp",
        topCount: numberValue(raw.topCount ?? raw.top_count) || 3,
        rewards: arrayValue(raw.rewards).map((reward) => {
            const item = asRecord(reward);
            return {
                rankNo: numberValue(item.rankNo ?? item.rank_no),
                resourceGroupId: numberValue(item.resourceGroupId ?? item.resource_group_id),
            };
        }),
        updatedByAdminId: numberValue(raw.updatedByAdminId ?? raw.updated_by_admin_id),
        createdAtMs: numberValue(raw.createdAtMs ?? raw.created_at_ms),
        updatedAtMs: numberValue(raw.updatedAtMs ?? raw.updated_at_ms),
    };
}

function normalizeSettlement(raw: Raw): CPWeeklyRankSettlementDto {
    return {
        settlementId: stringValue(raw.settlementId ?? raw.settlement_id),
        periodStartMs: numberValue(raw.periodStartMs ?? raw.period_start_ms),
        periodEndMs: numberValue(raw.periodEndMs ?? raw.period_end_ms),
        rankNo: numberValue(raw.rankNo ?? raw.rank_no),
        relationshipId: stringValue(raw.relationshipId ?? raw.relationship_id),
        userId: stringValue(raw.userId ?? raw.user_id),
        score: numberValue(raw.score),
        resourceGroupId: numberValue(raw.resourceGroupId ?? raw.resource_group_id),
        walletCommandId: stringValue(raw.walletCommandId ?? raw.wallet_command_id),
        walletGrantId: stringValue(raw.walletGrantId ?? raw.wallet_grant_id),
        status: stringValue(raw.status),
        failureReason: stringValue(raw.failureReason ?? raw.failure_reason),
        attemptCount: numberValue(raw.attemptCount ?? raw.attempt_count),
        createdAtMs: numberValue(raw.createdAtMs ?? raw.created_at_ms),
        updatedAtMs: numberValue(raw.updatedAtMs ?? raw.updated_at_ms),
    };
}

function asRecord(value: unknown): Raw {
    return value && typeof value === "object" && !Array.isArray(value) ? (value as Raw) : {};
}

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

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