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

export interface RoomRocketRewardItemDto {
    rewardItemId: string;
    resourceGroupId: number;
    weight: number;
    quantity: number;
    displayName?: string;
    iconUrl?: string;
}

export interface RoomRocketLevelDto {
    level: number;
    fuelThreshold: number;
    coverUrl?: string;
    animationUrl?: string;
    launchAnimationUrl?: string;
    launchedImageUrl?: string;
    inRoomRewards: RoomRocketRewardItemDto[];
    top1Rewards: RoomRocketRewardItemDto[];
    igniterRewards: RoomRocketRewardItemDto[];
}

export interface GiftFuelRuleDto {
    ruleId: string;
    giftId?: string;
    giftTypeCode?: string;
    multiplierPpm: number;
    fixedFuel: number;
    excluded: boolean;
}

export interface RoomRocketConfigDto {
    appCode?: string;
    enabled: boolean;
    configVersion: number;
    fuelSource: string;
    launchDelayMs: number;
    broadcastEnabled: boolean;
    broadcastScope: string;
    broadcastDelayMs: number;
    rewardStackPolicy: string;
    levels: RoomRocketLevelDto[];
    giftFuelRules: GiftFuelRuleDto[];
    updatedByAdminId?: number;
    createdAtMs?: number;
    updatedAtMs?: number;
}

export type RoomRocketConfigPayload = Pick<
    RoomRocketConfigDto,
    | "broadcastDelayMs"
    | "broadcastEnabled"
    | "broadcastScope"
    | "enabled"
    | "fuelSource"
    | "giftFuelRules"
    | "levels"
    | "launchDelayMs"
    | "rewardStackPolicy"
>;

type RawReward = RoomRocketRewardItemDto & Record<string, unknown>;
type RawLevel = Omit<RoomRocketLevelDto, "igniterRewards" | "inRoomRewards" | "top1Rewards"> & {
    igniterRewards?: RawReward[];
    igniter_rewards?: RawReward[];
    inRoomRewards?: RawReward[];
    in_room_rewards?: RawReward[];
    top1Rewards?: RawReward[];
    top1_rewards?: RawReward[];
} & Record<string, unknown>;
type RawGiftFuelRule = GiftFuelRuleDto & Record<string, unknown>;
type RawConfig = Omit<RoomRocketConfigDto, "giftFuelRules" | "levels"> & {
    giftFuelRules?: RawGiftFuelRule[];
    levels?: RawLevel[];
} & Record<string, unknown>;

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

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

function normalizeConfig(item: RawConfig): RoomRocketConfigDto {
    return {
        appCode: stringValue(item.appCode ?? item.app_code),
        enabled: Boolean(item.enabled),
        configVersion: numberValue(item.configVersion ?? item.config_version),
        fuelSource: normalizeFuelSource(item.fuelSource),
        launchDelayMs: numberValue(item.launchDelayMs ?? item.launch_delay_ms),
        broadcastEnabled: Boolean(item.broadcastEnabled ?? item.broadcast_enabled),
        broadcastScope: stringValue(item.broadcastScope ?? item.broadcast_scope) || "region",
        broadcastDelayMs: numberValue(item.broadcastDelayMs ?? item.broadcast_delay_ms),
        rewardStackPolicy: stringValue(item.rewardStackPolicy ?? item.reward_stack_policy) || "allow_stack",
        levels: normalizeLevels(item.levels),
        giftFuelRules: normalizeGiftFuelRules(item.giftFuelRules),
        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 normalizeFuelSource(value: unknown) {
    const source = stringValue(value);
    if (!source) {
        return "heat_value";
    }
    return source;
}

function normalizeLevels(levels?: RawLevel[]): RoomRocketLevelDto[] {
    const byLevel = new Map<number, RoomRocketLevelDto>();
    for (const level of levels || []) {
        const levelNo = numberValue(level.level);
        if (levelNo < 1 || levelNo > 5) {
            continue;
        }
        byLevel.set(levelNo, {
            level: levelNo,
            fuelThreshold: numberValue(level.fuelThreshold),
            coverUrl: stringValue(level.coverUrl ?? level.cover_url),
            animationUrl: stringValue(level.animationUrl ?? level.animation_url),
            launchAnimationUrl: stringValue(level.launchAnimationUrl ?? level.launch_animation_url),
            launchedImageUrl: stringValue(level.launchedImageUrl ?? level.launched_image_url),
            inRoomRewards: normalizeRewards(level.inRoomRewards ?? level.in_room_rewards),
            top1Rewards: normalizeRewards(level.top1Rewards ?? level.top1_rewards),
            igniterRewards: normalizeRewards(level.igniterRewards ?? level.igniter_rewards),
        });
    }
    return Array.from({ length: 5 }, (_, index) => {
        const level = index + 1;
        return byLevel.get(level) || defaultLevel(level);
    });
}

function defaultLevel(level: number): RoomRocketLevelDto {
    const thresholds = [1000, 3000, 6000, 10000, 15000];
    return {
        level,
        fuelThreshold: thresholds[level - 1] || 0,
        coverUrl: "",
        animationUrl: "",
        launchAnimationUrl: "",
        launchedImageUrl: "",
        inRoomRewards: [],
        top1Rewards: [],
        igniterRewards: [],
    };
}

function normalizeRewards(rewards?: RawReward[]): RoomRocketRewardItemDto[] {
    return (rewards || [])
        .map((reward, index) => ({
            rewardItemId: stringValue(reward.rewardItemId ?? reward.reward_item_id) || `reward_${index + 1}`,
            resourceGroupId: numberValue(reward.resourceGroupId ?? reward.resource_group_id),
            weight: numberValue(reward.weight),
            quantity: positiveNumberValue(reward.quantity) || 1,
            displayName: stringValue(reward.displayName ?? reward.display_name),
            iconUrl: stringValue(reward.iconUrl ?? reward.icon_url),
        }))
        .filter(
            (reward) =>
                reward.resourceGroupId > 0 ||
                reward.weight > 0 ||
                reward.quantity > 0 ||
                reward.displayName ||
                reward.iconUrl,
        );
}

function normalizeGiftFuelRules(rules?: RawGiftFuelRule[]): GiftFuelRuleDto[] {
    return (rules || [])
        .map((rule, index) => ({
            ruleId: stringValue(rule.ruleId ?? rule.rule_id) || `gift_fuel_rule_${index + 1}`,
            giftId: stringValue(rule.giftId ?? rule.gift_id),
            giftTypeCode: stringValue(rule.giftTypeCode ?? rule.gift_type_code),
            multiplierPpm: numberValue(rule.multiplierPpm ?? rule.multiplier_ppm),
            fixedFuel: numberValue(rule.fixedFuel),
            excluded: Boolean(rule.excluded),
        }))
        .filter(
            (rule) => rule.giftId || rule.giftTypeCode || rule.multiplierPpm > 0 || rule.fixedFuel > 0 || rule.excluded,
        );
}

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

function positiveNumberValue(value: unknown) {
    const number = numberValue(value);
    return number > 0 ? number : 0;
}
