package com.starry.admin.modules.clerk.task;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.starry.admin.modules.clerk.enums.ClerkMediaUsage;
import com.starry.admin.modules.clerk.module.entity.PlayClerkUserInfoEntity;
import com.starry.admin.modules.clerk.service.IPlayClerkMediaAssetService;
import com.starry.admin.modules.clerk.service.IPlayClerkUserInfoService;
import com.starry.admin.modules.media.entity.PlayMediaEntity;
import com.starry.admin.modules.media.enums.MediaKind;
import com.starry.admin.modules.media.enums.MediaOwnerType;
import com.starry.admin.modules.media.enums.MediaStatus;
import com.starry.admin.modules.media.service.IPlayMediaService;
import com.starry.admin.utils.SecurityUtils;
import com.starry.common.utils.IdUtils;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

/**
 * 一次性迁移旧相册数据到媒资表。启用方式：启动时配置
 * {@code clerk.media.migration-enabled=true}。
 */
@Component
@ConditionalOnProperty(prefix = "clerk.media", name = "migration-enabled", havingValue = "true")
@RequiredArgsConstructor
@Slf4j
public class ClerkAlbumMigrationRunner implements ApplicationRunner {

    private final IPlayClerkUserInfoService clerkUserInfoService;
    private final IPlayMediaService mediaService;
    private final IPlayClerkMediaAssetService clerkMediaAssetService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void run(ApplicationArguments args) {
        log.info("[ClerkAlbumMigration] start migration from legacy album column");
        List<PlayClerkUserInfoEntity> candidates = clerkUserInfoService.listWithAlbumIgnoringTenant();

        if (CollectionUtil.isEmpty(candidates)) {
            log.info("[ClerkAlbumMigration] no clerk records with legacy album found, skip");
            return;
        }

        AtomicInteger migratedOwners = new AtomicInteger();
        AtomicInteger migratedMedia = new AtomicInteger();
        String originalTenantId = SecurityUtils.getTenantId();
        for (PlayClerkUserInfoEntity clerk : candidates) {
            String tenantId = StrUtil.blankToDefault(clerk.getTenantId(), originalTenantId);
            SecurityUtils.setTenantId(tenantId);
            try {
                List<String> album = clerk.getAlbum();
                if (CollectionUtil.isEmpty(album)) {
                    continue;
                }
                List<String> sanitizedAlbum = album.stream()
                        .filter(StrUtil::isNotBlank)
                        .map(String::trim)
                        .distinct()
                        .collect(Collectors.toList());
                if (CollectionUtil.isEmpty(sanitizedAlbum)) {
                    continue;
                }
        List<String> approvedMediaIds = new ArrayList<>();
        for (String value : sanitizedAlbum) {
            PlayMediaEntity media = resolveMediaEntity(clerk, value);
            if (media == null) {
                continue;
            }
            media.setStatus(MediaStatus.READY.getCode());
            mediaService.updateById(media);
            clerkMediaAssetService.linkDraftAsset(clerk.getTenantId(), clerk.getId(), media.getId(),
                    ClerkMediaUsage.PROFILE);
            approvedMediaIds.add(media.getId());
        }

                clerkMediaAssetService.applyReviewDecision(clerk.getId(), ClerkMediaUsage.PROFILE, approvedMediaIds,
                        null, null);
                migratedOwners.incrementAndGet();
                migratedMedia.addAndGet(approvedMediaIds.size());
                log.info("[ClerkAlbumMigration] processed {} media for clerk {}", approvedMediaIds.size(),
                        clerk.getId());
            } finally {
                SecurityUtils.setTenantId(originalTenantId);
            }
        }
        log.info("[ClerkAlbumMigration] completed, owners migrated: {}, media migrated: {}", migratedOwners.get(),
                migratedMedia.get());
    }

    private PlayMediaEntity resolveMediaEntity(PlayClerkUserInfoEntity clerk, String value) {
        if (StrUtil.isBlank(value)) {
            return null;
        }
        PlayMediaEntity byId = mediaService.getById(value);
        if (byId != null) {
            return byId;
        }
        PlayMediaEntity byUrl = mediaService.lambdaQuery()
                .eq(PlayMediaEntity::getOwnerType, MediaOwnerType.CLERK)
                .eq(PlayMediaEntity::getOwnerId, clerk.getId())
                .eq(PlayMediaEntity::getUrl, value)
                .last("limit 1")
                .one();
        if (byUrl != null) {
            return byUrl;
        }
        PlayMediaEntity media = new PlayMediaEntity();
        media.setId(IdUtils.getUuid());
        media.setTenantId(clerk.getTenantId());
        media.setOwnerType(MediaOwnerType.CLERK);
        media.setOwnerId(clerk.getId());
        media.setKind(MediaKind.IMAGE.getCode());
        media.setStatus(MediaStatus.READY.getCode());
        media.setUrl(value);
        Map<String, Object> metadata = new HashMap<>();
        metadata.put("legacySource", "album_migration");
        media.setMetadata(metadata);
        mediaService.normalizeAndSave(media);
        return media;
    }
}
