import { apiRequest } from "@/shared/api/request";
import { API_ENDPOINTS, API_OPERATIONS, apiEndpointPath } from "@/shared/api/generated/endpoints";
import type { ApiPage, CoinLedgerUserDto, EntityId, PageQuery } from "@/shared/api/types";
import { resourceIdentityAutoGrantTypes } from "@/features/resources/constants.js";

export interface ResourceDto {
    appCode?: string;
    resourceId: number;
    resourceCode?: string;
    resourceType?: string;
    name?: string;
    status?: string;
    grantable?: boolean;
    managerGrantEnabled?: boolean;
    grantStrategy?: string;
    walletAssetType?: string;
    walletAssetAmount?: number;
    priceType?: string;
    coinPrice?: number;
    avatarFrameKind?: string;
    badgeForm?: string;
    badgeKind?: string;
    levelTrack?: string;
    usageScopes?: string[];
    assetUrl?: string;
    previewUrl?: string;
    animationUrl?: string;
    metadataJson?: string;
    sortOrder?: number;
    createdAtMs?: number;
    updatedAtMs?: number;
}

export interface ResourcePayload {
    amount: number;
    animationUrl?: string;
    assetUrl: string;
    avatarFrameKind?: string;
    badgeForm?: string;
    badgeKind?: string;
    coinPrice: number;
    levelTrack?: string;
    managerGrantEnabled: boolean;
    metadataJson?: string;
    name: string;
    previewUrl: string;
    priceType: string;
    resourceCode: string;
    resourceType: string;
    sortOrder: number;
    status: string;
}

export interface ResourceMp4LayoutUpdatePayload {
    metadataJson: string;
    resourceId: EntityId;
}

export interface ResourceMp4LayoutsPayload {
    items: ResourceMp4LayoutUpdatePayload[];
}

export interface EmojiPackDto {
    appCode?: string;
    resourceId: number;
    resourceCode?: string;
    name?: string;
    status?: string;
    category?: string;
    pricingType?: string;
    coverUrl?: string;
    animationUrl?: string;
    regionIds?: number[];
    sortOrder?: number;
    createdAtMs?: number;
    updatedAtMs?: number;
}

export interface EmojiPackPayload {
    animationUrl: string;
    category: string;
    coverUrl: string;
    name: string;
    pricingType: string;
    regionIds: number[];
    sortOrder: number;
}

export interface ResourceGroupItemDto {
    groupItemId: number;
    itemType?: string;
    resourceId: number;
    resource?: ResourceDto;
    walletAssetType?: string;
    walletAssetAmount?: number;
    quantity?: number;
    durationMs?: number;
    sortOrder?: number;
}

export interface ResourceGroupDto {
    appCode?: string;
    groupId: number;
    groupCode?: string;
    name?: string;
    status?: string;
    description?: string;
    sortOrder?: number;
    items?: ResourceGroupItemDto[];
    createdAtMs?: number;
    updatedAtMs?: number;
}

export type ResourceIdentityAutoGrantType = "host" | "bd" | "bd_leader" | "agency" | "manager";

export interface ResourceIdentityAutoGrantItemDto {
    identityType: ResourceIdentityAutoGrantType;
    resourceGroupId: number;
    resourceGroup?: ResourceGroupDto;
    createdAtMs?: number;
    updatedAtMs?: number;
}

export interface ResourceIdentityAutoGrantConfigDto {
    items: ResourceIdentityAutoGrantItemDto[];
    updatedByAdminId?: number;
    createdAtMs?: number;
    updatedAtMs?: number;
}

export interface ResourceIdentityAutoGrantConfigPayload {
    items: Array<{
        identity_type: ResourceIdentityAutoGrantType;
        resource_group_id: number;
    }>;
}

export interface ResourceShopItemDto {
    appCode?: string;
    shopItemId: number;
    resourceId: number;
    resource?: ResourceDto;
    status?: string;
    durationDays?: number;
    priceType?: string;
    coinPrice?: number;
    effectiveFromMs?: number;
    effectiveToMs?: number;
    sortOrder?: number;
    createdAtMs?: number;
    updatedAtMs?: number;
}

export interface ResourceShopPurchaseOrderDto {
    appCode?: string;
    orderId: string;
    commandId?: string;
    userId?: string;
    user?: ResourceGrantUserDto;
    shopItemId?: number;
    resourceId: number;
    resource?: ResourceDto;
    durationDays?: number;
    priceCoin?: number;
    status?: string;
    walletTransactionId?: string;
    resourceGrantId?: string;
    entitlementId?: string;
    createdAtMs?: number;
    updatedAtMs?: number;
}

export interface GiftDto {
    appCode?: string;
    giftId: string;
    resourceId: number;
    resource?: ResourceDto;
    status?: string;
    name?: string;
    sortOrder?: number;
    presentationJson?: string;
    priceVersion?: string;
    giftTypeCode?: string;
    cpRelationType?: string;
    chargeAssetType?: string;
    coinPrice?: number;
    effectiveFromMs?: number;
    effectiveToMs?: number;
    effectTypes?: string[];
    createdAtMs?: number;
    updatedAtMs?: number;
    regionIds?: number[];
}

export interface GiftTypeDto {
    appCode?: string;
    tabKey?: string;
    displayName?: string;
    tabName?: string;
    status?: string;
    sortOrder?: number;
    createdByUserId?: number;
    updatedByUserId?: number;
    createdAtMs?: number;
    updatedAtMs?: number;
}

export interface GiftPayload {
    giftId: string;
    resourceId: number;
    status: string;
    name: string;
    sortOrder: number;
    presentationJson: string;
    priceVersion: string;
    giftTypeCode: string;
    cpRelationType: string;
    chargeAssetType: string;
    coinPrice: number;
    effectiveAtMs: number;
    effectiveFromMs: number;
    effectiveToMs: number;
    effectTypes: string[];
    regionIds: number[];
}

export interface BatchCreateGiftsPayload {
    items: GiftPayload[];
}

export interface GiftTypePayload {
    displayName: string;
    tabName: string;
    status: string;
    sortOrder: number;
}

export interface GiftTypesPayload {
    items: Array<GiftTypePayload & { tabKey: string }>;
}

export interface ResourceGrantItemDto {
    createdAtMs?: number;
    durationMs?: number;
    entitlementId?: string;
    grantId?: string;
    grantItemId?: number;
    quantity?: number;
    resourceId?: number;
    resourceSnapshotJson?: string;
    resultType?: string;
    walletTransactionId?: string;
}

export interface ResourceGrantOperatorDto {
    avatar?: string;
    displayUserId?: string;
    prettyDisplayUserId?: string;
    prettyId?: string;
    name?: string;
    source?: string;
    userId?: string;
    username?: string;
}

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

export interface ResourceGrantDto {
    appCode?: string;
    commandId?: string;
    createdAtMs?: number;
    grantId: string;
    grantSource?: string;
    grantSubjectId?: string;
    grantSubjectType?: string;
    operator?: ResourceGrantOperatorDto;
    items?: ResourceGrantItemDto[];
    operatorUserId?: number;
    reason?: string;
    revokedAtMs?: number;
    revokedByUserId?: string;
    revokeReason?: string;
    status?: string;
    targetUser?: ResourceGrantUserDto;
    targetUserId?: string;
    updatedAtMs?: number;
}

export interface GrantResourcePayload {
    commandId: string;
    durationMs: number;
    quantity: number;
    reason: string;
    resourceId: number;
    targetUserId: string;
}

export interface GrantResourceGroupPayload {
    commandId: string;
    groupId: number;
    reason: string;
    targetUserId: string;
}

export interface ResourceGroupItemPayload {
    itemType: string;
    amount?: number;
    assetType?: string;
    durationDays?: number;
    resourceId?: number;
    sortOrder: number;
}

export interface ResourceGroupPayload {
    groupCode: string;
    name: string;
    status: string;
    description: string;
    sortOrder: number;
    items: ResourceGroupItemPayload[];
}

export interface ResourceShopItemPayload {
    coinPrice: number;
    durationDays: number;
    effectiveFromMs: number;
    effectiveToMs: number;
    resourceId: number;
    shopItemId?: number;
    sortOrder: number;
    status: string;
}

export interface ResourceShopItemsPayload {
    items: ResourceShopItemPayload[];
}

export interface BatchDeleteResourcesPayload {
    resourceIds: EntityId[];
}

export function listResources(query: PageQuery = {}): Promise<ApiPage<ResourceDto>> {
    const endpoint = API_ENDPOINTS.listResources;
    return apiRequest<ApiPage<ResourceDto>>(apiEndpointPath(API_OPERATIONS.listResources), {
        method: endpoint.method,
        query,
    });
}

export function createResource(payload: ResourcePayload): Promise<ResourceDto> {
    const endpoint = API_ENDPOINTS.createResource;
    return apiRequest<ResourceDto, ResourcePayload>(apiEndpointPath(API_OPERATIONS.createResource), {
        body: payload,
        method: endpoint.method,
    });
}

export function updateResource(resourceId: EntityId, payload: ResourcePayload): Promise<ResourceDto> {
    const endpoint = API_ENDPOINTS.updateResource;
    return apiRequest<ResourceDto, ResourcePayload>(
        apiEndpointPath(API_OPERATIONS.updateResource, { resource_id: resourceId }),
        {
            body: payload,
            method: endpoint.method,
        },
    );
}

export function deleteResource(resourceId: EntityId): Promise<ResourceDto> {
    const endpoint = API_ENDPOINTS.deleteResource;
    return apiRequest<ResourceDto>(apiEndpointPath(API_OPERATIONS.deleteResource, { resource_id: resourceId }), {
        method: endpoint.method,
    });
}

export function batchDeleteResources(resourceIds: EntityId[]): Promise<ResourceDto[]> {
    const endpoint = API_ENDPOINTS.batchDeleteResources;
    return apiRequest<ResourceDto[], BatchDeleteResourcesPayload>(
        apiEndpointPath(API_OPERATIONS.batchDeleteResources),
        {
            body: { resourceIds },
            method: endpoint.method,
        },
    );
}

export function updateResourceMp4Layouts(items: ResourceMp4LayoutUpdatePayload[]): Promise<ResourceDto[]> {
    return apiRequest<ResourceDto[], ResourceMp4LayoutsPayload>("/v1/admin/resources/mp4-layouts/batch", {
        body: { items },
        method: "PUT",
    });
}

export function enableResource(resourceId: EntityId): Promise<ResourceDto> {
    const endpoint = API_ENDPOINTS.enableResource;
    return apiRequest<ResourceDto>(apiEndpointPath(API_OPERATIONS.enableResource, { resource_id: resourceId }), {
        method: endpoint.method,
    });
}

export function disableResource(resourceId: EntityId): Promise<ResourceDto> {
    const endpoint = API_ENDPOINTS.disableResource;
    return apiRequest<ResourceDto>(apiEndpointPath(API_OPERATIONS.disableResource, { resource_id: resourceId }), {
        method: endpoint.method,
    });
}

export function listResourceGroups(query: PageQuery = {}): Promise<ApiPage<ResourceGroupDto>> {
    const endpoint = API_ENDPOINTS.listResourceGroups;
    return apiRequest<ApiPage<ResourceGroupDto>>(apiEndpointPath(API_OPERATIONS.listResourceGroups), {
        method: endpoint.method,
        query,
    });
}

export function listResourceShopItems(query: PageQuery = {}): Promise<ApiPage<ResourceShopItemDto>> {
    const endpoint = API_ENDPOINTS.listResourceShopItems;
    return apiRequest<ApiPage<ResourceShopItemDto>>(apiEndpointPath(API_OPERATIONS.listResourceShopItems), {
        method: endpoint.method,
        query,
    });
}

export function listResourceShopPurchaseOrders(query: PageQuery = {}): Promise<ApiPage<ResourceShopPurchaseOrderDto>> {
    const endpoint = API_ENDPOINTS.listResourceShopPurchaseOrders;
    return apiRequest<ApiPage<ResourceShopPurchaseOrderDto>>(
        apiEndpointPath(API_OPERATIONS.listResourceShopPurchaseOrders),
        {
            method: endpoint.method,
            query,
        },
    );
}

export function upsertResourceShopItems(payload: ResourceShopItemsPayload): Promise<ResourceShopItemDto[]> {
    const endpoint = API_ENDPOINTS.upsertResourceShopItems;
    return apiRequest<ResourceShopItemDto[], ResourceShopItemsPayload>(
        apiEndpointPath(API_OPERATIONS.upsertResourceShopItems),
        {
            body: payload,
            method: endpoint.method,
        },
    );
}

export function enableResourceShopItem(shopItemId: EntityId): Promise<ResourceShopItemDto> {
    const endpoint = API_ENDPOINTS.enableResourceShopItem;
    return apiRequest<ResourceShopItemDto>(
        apiEndpointPath(API_OPERATIONS.enableResourceShopItem, { shop_item_id: shopItemId }),
        {
            method: endpoint.method,
        },
    );
}

export function disableResourceShopItem(shopItemId: EntityId): Promise<ResourceShopItemDto> {
    const endpoint = API_ENDPOINTS.disableResourceShopItem;
    return apiRequest<ResourceShopItemDto>(
        apiEndpointPath(API_OPERATIONS.disableResourceShopItem, { shop_item_id: shopItemId }),
        {
            method: endpoint.method,
        },
    );
}

export function createResourceGroup(payload: ResourceGroupPayload): Promise<ResourceGroupDto> {
    const endpoint = API_ENDPOINTS.createResourceGroup;
    return apiRequest<ResourceGroupDto, ResourceGroupPayload>(apiEndpointPath(API_OPERATIONS.createResourceGroup), {
        body: payload,
        method: endpoint.method,
    });
}

export function updateResourceGroup(groupId: EntityId, payload: ResourceGroupPayload): Promise<ResourceGroupDto> {
    const endpoint = API_ENDPOINTS.updateResourceGroup;
    return apiRequest<ResourceGroupDto, ResourceGroupPayload>(
        apiEndpointPath(API_OPERATIONS.updateResourceGroup, { group_id: groupId }),
        {
            body: payload,
            method: endpoint.method,
        },
    );
}

export function enableResourceGroup(groupId: EntityId): Promise<ResourceGroupDto> {
    const endpoint = API_ENDPOINTS.enableResourceGroup;
    return apiRequest<ResourceGroupDto>(apiEndpointPath(API_OPERATIONS.enableResourceGroup, { group_id: groupId }), {
        method: endpoint.method,
    });
}

export function disableResourceGroup(groupId: EntityId): Promise<ResourceGroupDto> {
    const endpoint = API_ENDPOINTS.disableResourceGroup;
    return apiRequest<ResourceGroupDto>(apiEndpointPath(API_OPERATIONS.disableResourceGroup, { group_id: groupId }), {
        method: endpoint.method,
    });
}

export function getResourceIdentityAutoGrantConfig(): Promise<ResourceIdentityAutoGrantConfigDto> {
    const endpoint = API_ENDPOINTS.getResourceIdentityAutoGrantConfig;
    return apiRequest<RawResourceIdentityAutoGrantConfig | RawResourceIdentityAutoGrantItem[]>(
        apiEndpointPath(API_OPERATIONS.getResourceIdentityAutoGrantConfig),
        {
            method: endpoint.method,
        },
    ).then(normalizeResourceIdentityAutoGrantConfig);
}

export function updateResourceIdentityAutoGrantConfig(
    payload: ResourceIdentityAutoGrantConfigPayload,
): Promise<ResourceIdentityAutoGrantConfigDto> {
    const endpoint = API_ENDPOINTS.updateResourceIdentityAutoGrantConfig;
    return apiRequest<
        RawResourceIdentityAutoGrantConfig | RawResourceIdentityAutoGrantItem[],
        ResourceIdentityAutoGrantConfigPayload
    >(apiEndpointPath(API_OPERATIONS.updateResourceIdentityAutoGrantConfig), {
        body: payload,
        method: endpoint.method,
    }).then(normalizeResourceIdentityAutoGrantConfig);
}

export function listGifts(query: PageQuery = {}): Promise<ApiPage<GiftDto>> {
    const endpoint = API_ENDPOINTS.listGifts;
    return apiRequest<ApiPage<GiftDto>>(apiEndpointPath(API_OPERATIONS.listGifts), {
        method: endpoint.method,
        query,
    });
}

export function listGiftTypes(): Promise<GiftTypeDto[]> {
    const endpoint = API_ENDPOINTS.listGiftTypes;
    return apiRequest<GiftTypeDto[]>(apiEndpointPath(API_OPERATIONS.listGiftTypes), {
        method: endpoint.method,
    });
}

export function updateGiftType(tabKey: string, payload: GiftTypePayload): Promise<GiftTypeDto> {
    const endpoint = API_ENDPOINTS.updateGiftType;
    return apiRequest<GiftTypeDto, GiftTypePayload>(
        apiEndpointPath(API_OPERATIONS.updateGiftType, { type_code: tabKey }),
        {
            body: payload,
            method: endpoint.method,
        },
    );
}

export function updateGiftTypes(payload: GiftTypesPayload): Promise<GiftTypeDto[]> {
    const endpoint = API_ENDPOINTS.updateGiftTypes;
    return apiRequest<GiftTypeDto[], GiftTypesPayload>(apiEndpointPath(API_OPERATIONS.updateGiftTypes), {
        body: payload,
        method: endpoint.method,
    });
}

export function createGift(payload: GiftPayload): Promise<GiftDto> {
    const endpoint = API_ENDPOINTS.createGift;
    return apiRequest<GiftDto, GiftPayload>(apiEndpointPath(API_OPERATIONS.createGift), {
        body: payload,
        method: endpoint.method,
    });
}

export function batchCreateGifts(payloads: GiftPayload[]): Promise<GiftDto[]> {
    const endpoint = API_ENDPOINTS.batchCreateGifts;
    return apiRequest<GiftDto[], BatchCreateGiftsPayload>(apiEndpointPath(API_OPERATIONS.batchCreateGifts), {
        body: { items: payloads },
        method: endpoint.method,
    });
}

export function updateGift(giftId: string, payload: GiftPayload): Promise<GiftDto> {
    const endpoint = API_ENDPOINTS.updateGift;
    return apiRequest<GiftDto, GiftPayload>(apiEndpointPath(API_OPERATIONS.updateGift, { gift_id: giftId }), {
        body: payload,
        method: endpoint.method,
    });
}

export function deleteGift(giftId: string): Promise<GiftDto> {
    const endpoint = API_ENDPOINTS.deleteGift;
    return apiRequest<GiftDto>(apiEndpointPath(API_OPERATIONS.deleteGift, { gift_id: giftId }), {
        method: endpoint.method,
    });
}

export function enableGift(giftId: string): Promise<GiftDto> {
    const endpoint = API_ENDPOINTS.enableGift;
    return apiRequest<GiftDto>(apiEndpointPath(API_OPERATIONS.enableGift, { gift_id: giftId }), {
        method: endpoint.method,
    });
}

export function disableGift(giftId: string): Promise<GiftDto> {
    const endpoint = API_ENDPOINTS.disableGift;
    return apiRequest<GiftDto>(apiEndpointPath(API_OPERATIONS.disableGift, { gift_id: giftId }), {
        method: endpoint.method,
    });
}

export function listEmojiPacks(query: PageQuery = {}): Promise<ApiPage<EmojiPackDto>> {
    const endpoint = API_ENDPOINTS.listEmojiPacks;
    return apiRequest<ApiPage<EmojiPackDto>>(apiEndpointPath(API_OPERATIONS.listEmojiPacks), {
        method: endpoint.method,
        query,
    });
}

export function listEmojiPackCategories(): Promise<string[]> {
    const endpoint = API_ENDPOINTS.listEmojiPackCategories;
    return apiRequest<string[]>(apiEndpointPath(API_OPERATIONS.listEmojiPackCategories), {
        method: endpoint.method,
    });
}

export function createEmojiPack(payload: EmojiPackPayload): Promise<EmojiPackDto> {
    const endpoint = API_ENDPOINTS.createEmojiPack;
    return apiRequest<EmojiPackDto, EmojiPackPayload>(apiEndpointPath(API_OPERATIONS.createEmojiPack), {
        body: payload,
        method: endpoint.method,
    });
}

export function listResourceGrants(query: PageQuery = {}): Promise<ApiPage<ResourceGrantDto>> {
    const endpoint = API_ENDPOINTS.listResourceGrants;
    return apiRequest<ApiPage<ResourceGrantDto>>(apiEndpointPath(API_OPERATIONS.listResourceGrants), {
        method: endpoint.method,
        query,
    });
}

export function lookupResourceGrantTarget(userIdOrDisplayId: string | number): Promise<CoinLedgerUserDto> {
    const endpoint = API_ENDPOINTS.lookupResourceGrantTarget;
    return apiRequest<CoinLedgerUserDto>(apiEndpointPath(API_OPERATIONS.lookupResourceGrantTarget), {
        method: endpoint.method,
        query: { user_id: String(userIdOrDisplayId).trim() },
    });
}

export function grantResource(payload: GrantResourcePayload): Promise<ResourceGrantDto> {
    const endpoint = API_ENDPOINTS.grantResource;
    return apiRequest<ResourceGrantDto, GrantResourcePayload>(apiEndpointPath(API_OPERATIONS.grantResource), {
        body: payload,
        method: endpoint.method,
    });
}

export function grantResourceGroup(payload: GrantResourceGroupPayload): Promise<ResourceGrantDto> {
    const endpoint = API_ENDPOINTS.grantResourceGroup;
    return apiRequest<ResourceGrantDto, GrantResourceGroupPayload>(apiEndpointPath(API_OPERATIONS.grantResourceGroup), {
        body: payload,
        method: endpoint.method,
    });
}

export function revokeResourceGrant(grantId: string): Promise<ResourceGrantDto> {
    const endpoint = API_ENDPOINTS.revokeResourceGrant;
    return apiRequest<ResourceGrantDto>(apiEndpointPath(API_OPERATIONS.revokeResourceGrant, { grant_id: grantId }), {
        method: endpoint.method,
    });
}

type RawResourceIdentityAutoGrantItem = ResourceIdentityAutoGrantItemDto & {
    created_at_ms?: unknown;
    identity_type?: unknown;
    resource_group?: unknown;
    resource_group_id?: unknown;
    updated_at_ms?: unknown;
};

type RawResourceIdentityAutoGrantConfig = ResourceIdentityAutoGrantConfigDto & {
    configs?: RawResourceIdentityAutoGrantItem[];
    created_at_ms?: unknown;
    items?: RawResourceIdentityAutoGrantItem[];
    updated_at_ms?: unknown;
    updated_by_admin_id?: unknown;
};

function normalizeResourceIdentityAutoGrantConfig(
    source: RawResourceIdentityAutoGrantConfig | RawResourceIdentityAutoGrantItem[],
): ResourceIdentityAutoGrantConfigDto {
    const rawItems = Array.isArray(source) ? source : source.items || source.configs || [];
    return {
        items: rawItems.map(normalizeResourceIdentityAutoGrantItem),
        updatedByAdminId: Array.isArray(source) ? 0 : numberValue(source.updatedByAdminId ?? source.updated_by_admin_id),
        createdAtMs: Array.isArray(source) ? 0 : numberValue(source.createdAtMs ?? source.created_at_ms),
        updatedAtMs: Array.isArray(source) ? 0 : numberValue(source.updatedAtMs ?? source.updated_at_ms),
    };
}

function normalizeResourceIdentityAutoGrantItem(
    item: RawResourceIdentityAutoGrantItem,
): ResourceIdentityAutoGrantItemDto {
    const resourceGroup = item.resourceGroup ?? item.resource_group;
    return {
        identityType: normalizeIdentityType(item.identityType ?? item.identity_type),
        resourceGroupId: numberValue(item.resourceGroupId ?? item.resource_group_id),
        resourceGroup: resourceGroup && typeof resourceGroup === "object" ? (resourceGroup as ResourceGroupDto) : undefined,
        createdAtMs: numberValue(item.createdAtMs ?? item.created_at_ms),
        updatedAtMs: numberValue(item.updatedAtMs ?? item.updated_at_ms),
    };
}

function normalizeIdentityType(value: unknown): ResourceIdentityAutoGrantType {
    const identityType = stringValue(value) as ResourceIdentityAutoGrantType;
    return resourceIdentityAutoGrantTypes.includes(identityType) ? identityType : "host";
}

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

function stringValue(value: unknown): string {
    return value === undefined || value === null ? "" : String(value);
}
