package archive

import (
	"archive/zip"
	"context"
	"fmt"

	"git.kmsign.ru/royalcat/tstor/server/src/vfs"
	"github.com/royalcat/ctxio"
)

func (d *Daemon) ZipLoader(ctx context.Context, archivePath string, f vfs.File, size int64) (map[string]fileEntry, error) {
	hash, err := vfs.FileHash(ctx, f)
	if err != nil {
		return nil, err
	}

	reader := ctxio.IoReaderAt(ctx, f)
	zr, err := zip.NewReader(reader, size)
	if err != nil {
		return nil, err
	}

	out := make(map[string]fileEntry)
	for i := range zr.File {
		zipFile := zr.File[i]
		if zipFile.FileInfo().IsDir() {
			continue
		}

		i := i
		af := func(ctx context.Context) (ctxio.ReadCloser, error) {
			reader := ctxio.IoReaderAt(ctx, f)

			zr, err := zip.NewReader(reader, size)
			if err != nil {
				return nil, fmt.Errorf("failed to create zip reader: %w", err)
			}

			rc, err := zr.File[i].Open()
			if err != nil {
				return nil, fmt.Errorf("failed to open file in zip archive: %w", err)
			}

			return ctxio.WrapIoReadCloser(rc), nil
		}

		info := zipFile.FileInfo()

		rr := newRandomReaderFromLinear(d.blockcache, archiveFileIndex{archiveHash: hash, filename: zipFile.Name}, info.Size(), af)

		out[vfs.AbsPath(zipFile.Name)] = fileEntry{
			FileInfo: info,
			open: func(ctx context.Context) (vfs.File, error) {
				return newArchiveFile(info.Name(), info.Size(), rr), nil
			},
		}
	}

	return out, nil
}