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 SevenDayCheckInRewardDto {
    dayIndex: number;
    resourceGroupId: number;
}

export interface SevenDayCheckInConfigDto {
    appCode?: string;
    enabled: boolean;
    configVersion: number;
    rewards: SevenDayCheckInRewardDto[];
    updatedByAdminId?: number;
    createdAtMs?: number;
    updatedAtMs?: number;
}

export interface SevenDayCheckInConfigPayload {
    enabled: boolean;
    rewards: Array<{
        day_index: number;
        resource_group_id: number;
    }>;
}

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

export interface SevenDayCheckInClaimDto {
    claimId: string;
    commandId?: string;
    userId: string;
    user?: SevenDayCheckInClaimUserDto;
    cycleNo: number;
    checkinDay?: string;
    dayIndex: number;
    configVersion: number;
    resourceGroupId: number;
    walletCommandId?: string;
    walletGrantId?: string;
    status?: string;
    failureReason?: string;
    signedAtMs?: number;
    grantedAtMs?: number;
    createdAtMs?: number;
    updatedAtMs?: number;
}

type RawReward = SevenDayCheckInRewardDto & Record<string, unknown>;
type RawConfig = Omit<SevenDayCheckInConfigDto, "rewards"> & { rewards?: RawReward[] } & Record<string, unknown>;
type RawClaim = SevenDayCheckInClaimDto & Record<string, unknown>;

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

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

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

function normalizeConfig(item: RawConfig): SevenDayCheckInConfigDto {
    return {
        appCode: stringValue(item.appCode ?? item.app_code),
        enabled: Boolean(item.enabled),
        configVersion: numberValue(item.configVersion ?? item.config_version),
        rewards: normalizeRewards(item.rewards),
        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 normalizeRewards(rewards?: RawReward[]) {
    const byDay = new Map<number, SevenDayCheckInRewardDto>();
    for (const reward of rewards || []) {
        const dayIndex = numberValue(reward.dayIndex ?? reward.day_index);
        if (dayIndex >= 1 && dayIndex <= 7) {
            byDay.set(dayIndex, {
                dayIndex,
                resourceGroupId: numberValue(reward.resourceGroupId ?? reward.resource_group_id),
            });
        }
    }
    return Array.from({ length: 7 }, (_, index) => {
        const dayIndex = index + 1;
        return byDay.get(dayIndex) || { dayIndex, resourceGroupId: 0 };
    });
}

function normalizeClaim(item: RawClaim): SevenDayCheckInClaimDto {
    const rawUser = (item.user || {}) as Record<string, unknown>;
    return {
        claimId: stringValue(item.claimId ?? item.claim_id),
        commandId: stringValue(item.commandId ?? item.command_id),
        userId: stringValue(item.userId ?? item.user_id),
        user: {
            userId: stringValue(rawUser.userId ?? rawUser.user_id),
            displayUserId: stringValue(rawUser.displayUserId ?? rawUser.display_user_id),
            prettyDisplayUserId: stringValue(rawUser.prettyDisplayUserId ?? rawUser.pretty_display_user_id),
            prettyId: stringValue(rawUser.prettyId ?? rawUser.pretty_id),
            username: stringValue(rawUser.username),
            avatar: stringValue(rawUser.avatar),
        },
        cycleNo: numberValue(item.cycleNo ?? item.cycle_no),
        checkinDay: stringValue(item.checkinDay ?? item.checkin_day),
        dayIndex: numberValue(item.dayIndex ?? item.day_index),
        configVersion: numberValue(item.configVersion ?? item.config_version),
        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),
        signedAtMs: numberValue(item.signedAtMs ?? item.signed_at_ms),
        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 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;
}
