package com.yaoai.pipeline.async;

import com.yaoai.domain.entity.AiTask;
import com.yaoai.domain.mapper.AiTaskMapper;
import com.yaoai.pipeline.service.ShotAssetService;
import com.yaoai.storage.service.TosService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.io.ByteArrayInputStream;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.time.Duration;

@Slf4j
@Service
@RequiredArgsConstructor
public class VideoTransferService {

    private final AiTaskMapper aiTaskMapper;
    private final TosService tosService;
    private final ShotAssetService shotAssetService;
    private final HttpClient httpClient = HttpClient.newBuilder()
            .connectTimeout(Duration.ofSeconds(10))
            .build();

    @Async
    public void transferVideoToTos(Long tenantId, Long projectId, Long taskId, String temporaryVideoUrl) {
        try {
            if (temporaryVideoUrl == null || temporaryVideoUrl.isBlank()) {
                return;
            }
            AiTask current = aiTaskMapper.selectById(taskId);
            if (current == null || !tenantId.equals(current.getTenantId())) {
                log.warn("Skip video transfer: task not found or tenant mismatch, taskId={}", taskId);
                return;
            }
            if (!temporaryVideoUrl.equals(current.getResultVideoUrl())) {
                log.info("Skip stale video transfer: taskId={}", taskId);
                return;
            }

            log.info("Video transfer started: taskId={}, temporaryUrl={}", taskId, temporaryVideoUrl);
            HttpRequest request = HttpRequest.newBuilder()
                    .uri(URI.create(temporaryVideoUrl))
                    .timeout(Duration.ofMinutes(2))
                    .GET()
                    .build();
            HttpResponse<byte[]> response = httpClient.send(request, HttpResponse.BodyHandlers.ofByteArray());
            if (response.statusCode() != 200) {
                log.warn("Download provider video failed (status={}), keep temporary URL: taskId={}",
                        response.statusCode(), taskId);
                return;
            }

            byte[] bytes = response.body();
            String key = String.format("%d/%d/video/%d.mp4", tenantId, projectId, taskId);
            try (var input = new ByteArrayInputStream(bytes)) {
                tosService.upload(key, input, bytes.length, "video/mp4");
            }

            AiTask latest = aiTaskMapper.selectById(taskId);
            if (latest == null || !tenantId.equals(latest.getTenantId()) || !temporaryVideoUrl.equals(latest.getResultVideoUrl())) {
                log.info("Skip stale video replace after upload: taskId={}", taskId);
                return;
            }
            String publicUrl = tosService.publicUrl(key);
            AiTask patch = new AiTask();
            patch.setId(taskId);
            patch.setResultVideoUrl(publicUrl);
            patch.setResultTosKey(key);
            aiTaskMapper.updateById(patch);
            shotAssetService.markVideoAssetSucceeded(tenantId, taskId, publicUrl);
            log.info("Video transfer completed: taskId={}, key={}, size={}", taskId, key, bytes.length);
        } catch (Exception e) {
            log.error("Video transfer failed, keep temporary URL: taskId={}", taskId, e);
        }
    }
}
