package main

import (
	"bytes"
	"fmt"
	"io"
	"mime/multipart"
	"net/http"
	"os"
)

func main() {
	filePath := "C:\\Users\\lx\\Downloads\\ubuntu-22.04.4-live-server-amd64.iso"
	chunkSize := int64(1024 * 1024 * 100) // 100MB 分块大小
	fileID := "unique-file-id"            // 文件唯一标识符

	// 打开文件
	file, err := os.Open(filePath)
	if err != nil {
		panic(err)
	}
	defer file.Close()

	// 获取文件信息
	fileInfo, err := file.Stat()
	if err != nil {
		panic(err)
	}
	fileSize := fileInfo.Size()

	// 计算总块数
	totalChunks := (fileSize + chunkSize - 1) / chunkSize

	// 记录已上传的块（可以保存在文件或数据库中）
	uploadedChunks := make(map[int64]bool)

	// 遍历每个块并上传
	for chunkIndex := int64(0); chunkIndex < totalChunks; chunkIndex++ {
		if uploadedChunks[chunkIndex] {
			// 如果该块已经上传，则跳过
			continue
		}

		// 创建块的缓冲区
		buffer := make([]byte, chunkSize)
		readBytes, err := file.Read(buffer)
		if err != nil && err != io.EOF {
			panic(err)
		}
		if readBytes == 0 {
			break
		}

		// 上传块
		err = uploadChunk(buffer[:readBytes], chunkIndex, totalChunks, fileID, fileInfo.Name())
		if err != nil {
			fmt.Printf("Failed to upload chunk %d: %v\n", chunkIndex, err)
			continue
		}

		// 记录已上传块
		uploadedChunks[chunkIndex] = true
	}
}

func uploadChunk(chunkData []byte, chunkIndex, totalChunks int64, fileID, filename string) error {
	// 创建 multipart 请求体
	body := new(bytes.Buffer)
	writer := multipart.NewWriter(body)

	// 添加文件块
	part, err := writer.CreateFormFile("file", filename)
	if err != nil {
		return err
	}
	part.Write(chunkData)

	// 添加其他字段
	writer.WriteField("chunkIndex", fmt.Sprintf("%d", chunkIndex))
	writer.WriteField("totalChunks", fmt.Sprintf("%d", totalChunks))
	writer.WriteField("fileID", fileID)

	// 关闭 multipart 编写器
	err = writer.Close()
	if err != nil {
		return err
	}

	// 发送请求
	req, err := http.NewRequest("POST", "http://localhost:8080/upload", body)
	if err != nil {
		return err
	}
	req.Header.Set("Content-Type", writer.FormDataContentType())

	client := &http.Client{}
	resp, err := client.Do(req)
	if err != nil {
		return err
	}
	defer resp.Body.Close()

	// 读取响应
	respBody, err := io.ReadAll(resp.Body)
	if err != nil {
		return err
	}

	fmt.Printf("Response: %s\n", string(respBody))
	return nil
}
