package cloudconvert

import (
	cc "Yimaru-Backend/internal/pkgs/cloudconvert"
	"bytes"
	"context"
	"fmt"
	"io"
	"time"

	"go.uber.org/zap"
)

type Service struct {
	client *cc.Client
	logger *zap.Logger
}

func NewService(apiKey string, logger *zap.Logger) *Service {
	return &Service{
		client: cc.NewClient(apiKey),
		logger: logger,
	}
}

type CompressResult struct {
	Data     io.ReadCloser
	FileSize int64
	Filename string
}

func (s *Service) CompressVideo(ctx context.Context, filename string, fileData io.Reader, fileSize int64) (*CompressResult, error) {
	s.logger.Info("Creating CloudConvert compression job", zap.String("filename", filename), zap.Int64("original_size", fileSize))

	job, err := s.client.CreateVideoCompressionJob(ctx)
	if err != nil {
		s.logger.Error("Failed to create CloudConvert job", zap.Error(err))
		return nil, fmt.Errorf("failed to create compression job: %w", err)
	}

	var uploadForm *cc.UploadForm
	for _, task := range job.Tasks {
		if task.Name == "import-video" && task.Result != nil && task.Result.Form != nil {
			uploadForm = task.Result.Form
			break
		}
	}

	if uploadForm == nil {
		return nil, fmt.Errorf("no upload form found in job response")
	}

	s.logger.Info("Uploading video to CloudConvert", zap.String("job_id", job.ID))

	if err := s.client.UploadFile(ctx, uploadForm, filename, fileData); err != nil {
		s.logger.Error("Failed to upload file to CloudConvert", zap.Error(err))
		return nil, fmt.Errorf("failed to upload file: %w", err)
	}

	s.logger.Info("Waiting for CloudConvert job to complete", zap.String("job_id", job.ID))

	completedJob, err := s.client.WaitForJob(ctx, job.ID, 5*time.Second, 30*time.Minute)
	if err != nil {
		s.logger.Error("CloudConvert job failed", zap.String("job_id", job.ID), zap.Error(err))
		return nil, fmt.Errorf("compression job failed: %w", err)
	}

	var exportURL string
	var exportFilename string
	for _, task := range completedJob.Tasks {
		if task.Name == "export-video" && task.Result != nil && len(task.Result.Files) > 0 {
			exportURL = task.Result.Files[0].URL
			exportFilename = task.Result.Files[0].Filename
			break
		}
	}

	if exportURL == "" {
		return nil, fmt.Errorf("no export URL found in completed job")
	}

	s.logger.Info("Downloading compressed video from CloudConvert", zap.String("job_id", job.ID), zap.String("filename", exportFilename))

	body, contentLength, err := s.client.DownloadFile(ctx, exportURL)
	if err != nil {
		return nil, fmt.Errorf("failed to download compressed file: %w", err)
	}

	if contentLength <= 0 {
		data, err := io.ReadAll(body)
		body.Close()
		if err != nil {
			return nil, fmt.Errorf("failed to read compressed file: %w", err)
		}
		contentLength = int64(len(data))
		body = io.NopCloser(bytes.NewReader(data))
	}

	s.logger.Info("Video compression complete",
		zap.Int64("original_size", fileSize),
		zap.Int64("compressed_size", contentLength),
		zap.String("filename", exportFilename),
	)

	return &CompressResult{
		Data:     body,
		FileSize: contentLength,
		Filename: exportFilename,
	}, nil
}
