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

export interface WeeklyStarGiftDto {
    giftId: string;
    sortOrder: number;
}

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

export interface WeeklyStarCycleDto {
    cycleId: string;
    activityCode: string;
    regionId: number;
    title: string;
    status: string;
    startMs: number;
    endMs: number;
    gifts: WeeklyStarGiftDto[];
    rewards: WeeklyStarRewardDto[];
    settledAtMs?: number;
    createdAtMs?: number;
    updatedAtMs?: number;
}

export interface WeeklyStarCyclePayload {
    cycle_id?: string;
    title: string;
    status: string;
    region_id: number;
    start_ms: number;
    end_ms: number;
    gift_ids: string[];
    top1_resource_group_id: number;
    top2_resource_group_id: number;
    top3_resource_group_id: number;
}

export interface WeeklyStarEntryDto {
    rankNo: number;
    userId: string;
    score: number;
    firstScoredAtMs: number;
    lastScoredAtMs: number;
}

export interface WeeklyStarSettlementDto {
    settlementId: string;
    cycleId: string;
    rankNo: number;
    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 listWeeklyStarCycles(query: QueryParams = {}) {
    const endpoint = API_ENDPOINTS.listWeeklyStarCycles;
    return apiRequest<{ items?: Raw[]; total?: number; page?: number; page_size?: number }>(endpoint.path, {
        method: endpoint.method,
        query,
    }).then((page) => ({
        ...page,
        items: (page.items || []).map(normalizeCycle),
    }));
}

export function createWeeklyStarCycle(payload: WeeklyStarCyclePayload) {
    const endpoint = API_ENDPOINTS.createWeeklyStarCycle;
    return apiRequest<Raw, WeeklyStarCyclePayload>(endpoint.path, {
        body: payload,
        method: endpoint.method,
    }).then(normalizeCycle);
}

export function updateWeeklyStarCycle(cycleId: string, payload: WeeklyStarCyclePayload) {
    const endpoint = API_ENDPOINTS.updateWeeklyStarCycle;
    return apiRequest<Raw, WeeklyStarCyclePayload>(
        apiEndpointPath(API_OPERATIONS.updateWeeklyStarCycle, { cycle_id: cycleId }),
        {
            body: payload,
            method: endpoint.method,
        },
    ).then(normalizeCycle);
}

export function setWeeklyStarCycleStatus(cycleId: string, status: string) {
    const endpoint = API_ENDPOINTS.setWeeklyStarCycleStatus;
    return apiRequest<Raw, { status: string }>(
        apiEndpointPath(API_OPERATIONS.setWeeklyStarCycleStatus, { cycle_id: cycleId }),
        {
            body: { status },
            method: endpoint.method,
        },
    ).then(normalizeCycle);
}

export function listWeeklyStarLeaderboard(cycleId: string) {
    const endpoint = API_ENDPOINTS.listWeeklyStarLeaderboard;
    return apiRequest<{ items?: Raw[]; total?: number }>(
        apiEndpointPath(API_OPERATIONS.listWeeklyStarLeaderboard, { cycle_id: cycleId }),
        {
            method: endpoint.method,
            query: { page_size: 100 },
        },
    ).then((resp) => ({
        total: numberValue(resp.total),
        items: (resp.items || []).map(normalizeEntry),
    }));
}

export function listWeeklyStarSettlements(cycleId: string) {
    const endpoint = API_ENDPOINTS.listWeeklyStarSettlements;
    return apiRequest<Raw[]>(apiEndpointPath(API_OPERATIONS.listWeeklyStarSettlements, { cycle_id: cycleId }), {
        method: endpoint.method,
    }).then((items) => (items || []).map(normalizeSettlement));
}

function normalizeCycle(item: Raw): WeeklyStarCycleDto {
    return {
        cycleId: stringValue(item.cycleId ?? item.cycle_id),
        activityCode: stringValue(item.activityCode ?? item.activity_code),
        regionId: numberValue(item.regionId ?? item.region_id),
        title: stringValue(item.title),
        status: stringValue(item.status),
        startMs: numberValue(item.startMs ?? item.start_ms),
        endMs: numberValue(item.endMs ?? item.end_ms),
        gifts: Array.isArray(item.gifts) ? item.gifts.map((gift) => normalizeGift(gift as Raw)) : [],
        rewards: Array.isArray(item.rewards) ? item.rewards.map((reward) => normalizeReward(reward as Raw)) : [],
        settledAtMs: numberValue(item.settledAtMs ?? item.settled_at_ms),
        createdAtMs: numberValue(item.createdAtMs ?? item.created_at_ms),
        updatedAtMs: numberValue(item.updatedAtMs ?? item.updated_at_ms),
    };
}

function normalizeGift(item: Raw): WeeklyStarGiftDto {
    return {
        giftId: stringValue(item.giftId ?? item.gift_id),
        sortOrder: numberValue(item.sortOrder ?? item.sort_order),
    };
}

function normalizeReward(item: Raw): WeeklyStarRewardDto {
    return {
        rankNo: numberValue(item.rankNo ?? item.rank_no),
        resourceGroupId: numberValue(item.resourceGroupId ?? item.resource_group_id),
    };
}

function normalizeEntry(item: Raw): WeeklyStarEntryDto {
    return {
        rankNo: numberValue(item.rankNo ?? item.rank_no),
        userId: stringValue(item.userId ?? item.user_id),
        score: numberValue(item.score),
        firstScoredAtMs: numberValue(item.firstScoredAtMs ?? item.first_scored_at_ms),
        lastScoredAtMs: numberValue(item.lastScoredAtMs ?? item.last_scored_at_ms),
    };
}

function normalizeSettlement(item: Raw): WeeklyStarSettlementDto {
    return {
        settlementId: stringValue(item.settlementId ?? item.settlement_id),
        cycleId: stringValue(item.cycleId ?? item.cycle_id),
        rankNo: numberValue(item.rankNo ?? item.rank_no),
        userId: stringValue(item.userId ?? item.user_id),
        score: numberValue(item.score),
        resourceGroupId: numberValue(item.resourceGroupId ?? item.resource_group_id),
        walletCommandId: stringValue(item.walletCommandId ?? item.wallet_command_id),
        walletGrantId: stringValue(item.walletGrantId ?? item.wallet_grant_id),
        status: stringValue(item.status),
        failureReason: stringValue(item.failureReason ?? item.failure_reason),
        attemptCount: numberValue(item.attemptCount ?? item.attempt_count),
        createdAtMs: numberValue(item.createdAtMs ?? item.created_at_ms),
        updatedAtMs: numberValue(item.updatedAtMs ?? item.updated_at_ms),
    };
}

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