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 type CPRelationType = "cp" | "brother" | "sister";

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

export interface CPGiftSnapshotDto {
    giftId: string;
    giftName: string;
    giftIconUrl: string;
    giftAnimationUrl: string;
    giftCount: number;
    giftValue: number;
    billingReceiptId: string;
}

export interface CPRelationshipDto {
    relationshipId: string;
    relationType: CPRelationType;
    status: string;
    userA: CPUserProfileDto;
    userB: CPUserProfileDto;
    intimacyValue: number;
    level: number;
    durationDays: number;
    gift?: CPGiftSnapshotDto;
    formedAtMs: number;
    updatedAtMs: number;
    endedAtMs: number;
}

export interface CPApplicationDto {
    applicationId: string;
    relationType: CPRelationType;
    status: string;
    requester: CPUserProfileDto;
    target: CPUserProfileDto;
    gift: CPGiftSnapshotDto;
    roomId: string;
    roomRegionId: number;
    createdAtMs: number;
    updatedAtMs: number;
    expiresAtMs: number;
    decidedAtMs: number;
}

export interface CPRelationshipPageDto extends ApiPage<CPRelationshipDto> {
    serverTimeMs?: number;
}

export interface CPApplicationPageDto extends ApiPage<CPApplicationDto> {
    serverTimeMs?: number;
}

export interface CPLevelDto {
    level: number;
    intimacyThreshold: number;
    rewardResourceGroupId: number;
    levelIconUrl: string;
    status: string;
    updatedAtMs?: number;
}

export interface CPRelationConfigDto {
    relationType: CPRelationType;
    displayName: string;
    maxCountPerUser: number;
    applicationExpireHours: number;
    breakupCostCoins: number;
    status: string;
    levels: CPLevelDto[];
    updatedAtMs?: number;
}

export interface CPConfigDto {
    appCode: string;
    relations: CPRelationConfigDto[];
    weeklyRank: CPWeeklyRankDto;
    serverTimeMs?: number;
}

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

export interface CPWeeklyRankDto {
    enabled: boolean;
    relationType: CPRelationType;
    topCount: number;
    rewards: CPWeeklyRankRewardDto[];
    updatedByAdminId?: number;
    createdAtMs?: number;
    updatedAtMs?: number;
}

export interface CPConfigPayload {
    relations: Array<{
        relationType: CPRelationType;
        maxCountPerUser: number;
        applicationExpireHours: number;
        breakupCostCoins: number;
        status: string;
        levels: Array<{
            level: number;
            intimacyThreshold: number;
            rewardResourceGroupId: number;
            levelIconUrl: string;
            status: string;
        }>;
    }>;
}

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

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

export function listCPRelationships(query: PageQuery = {}): Promise<CPRelationshipPageDto> {
    const endpoint = API_ENDPOINTS.listCPRelationships;
    return apiRequest<RawRelationshipPage>(apiEndpointPath(API_OPERATIONS.listCPRelationships), {
        method: endpoint.method,
        query,
    }).then(normalizeRelationshipPage);
}

export function listCPApplications(query: PageQuery = {}): Promise<CPApplicationPageDto> {
    const endpoint = API_ENDPOINTS.listCPApplications;
    return apiRequest<RawApplicationPage>(apiEndpointPath(API_OPERATIONS.listCPApplications), {
        method: endpoint.method,
        query,
    }).then(normalizeApplicationPage);
}

type RawConfig = CPConfigDto & Record<string, unknown>;
type RawRelation = CPRelationConfigDto & Record<string, unknown>;
type RawLevel = CPLevelDto & Record<string, unknown>;
type RawWeeklyRank = CPWeeklyRankDto & Record<string, unknown>;
type RawRelationship = CPRelationshipDto & Record<string, unknown>;
type RawApplication = CPApplicationDto & Record<string, unknown>;
type RawUser = CPUserProfileDto & Record<string, unknown>;
type RawGift = CPGiftSnapshotDto & Record<string, unknown>;
type RawRelationshipPage = ApiPage<RawRelationship> & {
    relationships?: RawRelationship[];
    page_size?: number | string;
    server_time_ms?: number | string;
} & Record<string, unknown>;
type RawApplicationPage = ApiPage<RawApplication> & {
    applications?: RawApplication[];
    page_size?: number | string;
    server_time_ms?: number | string;
} & Record<string, unknown>;

function normalizeConfig(raw: RawConfig): CPConfigDto {
    const item = asRecord(raw) as RawConfig;
    return {
        appCode: stringValue(item.appCode ?? item.app_code),
        relations: arrayValue(item.relations).map(normalizeRelation),
        weeklyRank: normalizeWeeklyRank(item.weeklyRank ?? item.weekly_rank),
        serverTimeMs: numberValue(item.serverTimeMs ?? item.server_time_ms),
    };
}

function normalizeRelation(raw: unknown): CPRelationConfigDto {
    const item = asRecord(raw) as RawRelation;
    const relationType = normalizeRelationType(item.relationType ?? item.relation_type);
    return {
        relationType,
        displayName: stringValue(item.displayName ?? item.display_name) || relationLabel(relationType),
        maxCountPerUser: numberValue(item.maxCountPerUser ?? item.max_count_per_user),
        applicationExpireHours: numberValue(item.applicationExpireHours ?? item.application_expire_hours),
        breakupCostCoins: numberValue(item.breakupCostCoins ?? item.breakup_cost_coins),
        status: stringValue(item.status) || "active",
        levels: arrayValue(item.levels).map(normalizeLevel),
        updatedAtMs: numberValue(item.updatedAtMs ?? item.updated_at_ms),
    };
}

function normalizeWeeklyRank(raw: unknown): CPWeeklyRankDto {
    const item = asRecord(raw) as RawWeeklyRank;
    return {
        enabled: item.enabled !== false,
        relationType: normalizeRelationType(item.relationType ?? item.relation_type),
        topCount: numberValue(item.topCount ?? item.top_count) || 3,
        rewards: arrayValue(item.rewards).map((reward) => {
            const rawReward = asRecord(reward);
            return {
                rankNo: numberValue(rawReward.rankNo ?? rawReward.rank_no),
                resourceGroupId: numberValue(rawReward.resourceGroupId ?? rawReward.resource_group_id),
            };
        }),
        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 normalizeLevel(raw: unknown): CPLevelDto {
    const item = asRecord(raw) as RawLevel;
    return {
        level: numberValue(item.level),
        intimacyThreshold: numberValue(item.intimacyThreshold ?? item.intimacy_threshold),
        rewardResourceGroupId: numberValue(item.rewardResourceGroupId ?? item.reward_resource_group_id),
        levelIconUrl: stringValue(item.levelIconUrl ?? item.level_icon_url),
        status: stringValue(item.status) || "active",
        updatedAtMs: numberValue(item.updatedAtMs ?? item.updated_at_ms),
    };
}

function normalizeRelationshipPage(page: RawRelationshipPage): CPRelationshipPageDto {
    const response = asRecord(page) as RawRelationshipPage;
    const items = arrayValue(response.items ?? response.relationships).map(normalizeRelationship);
    return {
        items,
        page: numberValue(response.page) || 1,
        pageSize: numberValue(response.pageSize ?? response.page_size) || items.length || 50,
        total: numberValue(response.total),
        serverTimeMs: numberValue(response.serverTimeMs ?? response.server_time_ms),
    };
}

function normalizeApplicationPage(page: RawApplicationPage): CPApplicationPageDto {
    const response = asRecord(page) as RawApplicationPage;
    const items = arrayValue(response.items ?? response.applications).map(normalizeApplication);
    return {
        items,
        page: numberValue(response.page) || 1,
        pageSize: numberValue(response.pageSize ?? response.page_size) || items.length || 50,
        total: numberValue(response.total),
        serverTimeMs: numberValue(response.serverTimeMs ?? response.server_time_ms),
    };
}

function normalizeRelationship(raw: unknown): CPRelationshipDto {
    const item = asRecord(raw) as RawRelationship;
    const userA = normalizeUser(item.userA ?? item.user_a ?? item.me ?? item.requester);
    const userB = normalizeUser(item.userB ?? item.user_b ?? item.partner ?? item.target);
    const gift = normalizeGift(
        item.gift ?? item.sourceGift ?? item.source_gift ?? item.applicationGift ?? item.application_gift,
    );
    return {
        relationshipId: stringValue(item.relationshipId ?? item.relationship_id),
        relationType: normalizeRelationType(item.relationType ?? item.relation_type),
        status: stringValue(item.status) || "active",
        userA,
        userB,
        intimacyValue: numberValue(
            item.intimacyValue ?? item.intimacy_value ?? item.experienceValue ?? item.experience_value,
        ),
        level: numberValue(item.level ?? item.levelNo ?? item.level_no),
        durationDays: numberValue(item.durationDays ?? item.duration_days ?? item.days),
        gift: gift.giftId || gift.giftName || gift.giftValue ? gift : undefined,
        formedAtMs: numberValue(item.formedAtMs ?? item.formed_at_ms ?? item.createdAtMs ?? item.created_at_ms),
        updatedAtMs: numberValue(item.updatedAtMs ?? item.updated_at_ms),
        endedAtMs: numberValue(item.endedAtMs ?? item.ended_at_ms),
    };
}

function normalizeApplication(raw: unknown): CPApplicationDto {
    const item = asRecord(raw) as RawApplication;
    return {
        applicationId: stringValue(item.applicationId ?? item.application_id),
        relationType: normalizeRelationType(item.relationType ?? item.relation_type),
        status: stringValue(item.status) || "pending",
        requester: normalizeUser(
            item.requester ?? item.requesterUser ?? item.requester_user ?? item.userA ?? item.user_a,
        ),
        target: normalizeUser(item.target ?? item.targetUser ?? item.target_user ?? item.userB ?? item.user_b),
        gift: normalizeGift(item.gift ?? item.sourceGift ?? item.source_gift),
        roomId: stringValue(item.roomId ?? item.room_id),
        roomRegionId: numberValue(item.roomRegionId ?? item.room_region_id),
        createdAtMs: numberValue(item.createdAtMs ?? item.created_at_ms),
        updatedAtMs: numberValue(item.updatedAtMs ?? item.updated_at_ms),
        expiresAtMs: numberValue(item.expiresAtMs ?? item.expires_at_ms),
        decidedAtMs: numberValue(item.decidedAtMs ?? item.decided_at_ms),
    };
}

function normalizeUser(raw: unknown): CPUserProfileDto {
    const item = asRecord(raw) as RawUser;
    return {
        userId: stringValue(item.userId ?? item.user_id),
        displayUserId: optionalString(item.displayUserId ?? item.display_user_id),
        prettyDisplayUserId: optionalString(item.prettyDisplayUserId ?? item.pretty_display_user_id),
        prettyId: optionalString(item.prettyId ?? item.pretty_id),
        username: optionalString(item.username ?? item.name),
        avatar: optionalString(item.avatar),
    };
}

function normalizeGift(raw: unknown): CPGiftSnapshotDto {
    const item = asRecord(raw) as RawGift;
    return {
        giftId: stringValue(item.giftId ?? item.gift_id),
        giftName: stringValue(item.giftName ?? item.gift_name ?? item.name),
        giftIconUrl: stringValue(item.giftIconUrl ?? item.gift_icon_url ?? item.iconUrl ?? item.icon_url),
        giftAnimationUrl: stringValue(
            item.giftAnimationUrl ?? item.gift_animation_url ?? item.animationUrl ?? item.animation_url,
        ),
        giftCount: numberValue(item.giftCount ?? item.gift_count ?? item.count),
        giftValue: numberValue(item.giftValue ?? item.gift_value ?? item.value),
        billingReceiptId: stringValue(item.billingReceiptId ?? item.billing_receipt_id),
    };
}

function normalizeRelationType(value: unknown): CPRelationType {
    const relationType = stringValue(value).toLowerCase();
    if (relationType === "brother" || relationType === "sister") {
        return relationType;
    }
    return "cp";
}

function relationLabel(relationType: CPRelationType) {
    return relationType === "brother" ? "兄弟" : relationType === "sister" ? "姐妹" : "CP";
}

function asRecord(value: unknown): Record<string, unknown> {
    return value && typeof value === "object" && !Array.isArray(value) ? (value as Record<string, unknown>) : {};
}

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 optionalString(value: unknown) {
    const text = stringValue(value).trim();
    return text || undefined;
}

function numberValue(value: unknown) {
    const number = Number(value || 0);
    return Number.isFinite(number) ? number : 0;
}
