package exporting

import (
	"archive/zip"
	"encoding/json"
	"errors"
	"fmt"
	"os"
	"path"
	"strings"

	"code.nonshy.com/nonshy/website/pkg/log"
	"code.nonshy.com/nonshy/website/pkg/models"
	"code.nonshy.com/nonshy/website/pkg/photo"
)

// ExportUser creates a data export archive of ALL data stored about a user account..
func ExportUser(user *models.User, filename string) error {
	if !strings.HasSuffix(filename, ".zip") {
		return errors.New("output file should be a .zip file")
	}

	// Prepare the output zip writer.
	fh, err := os.Create(filename)
	if err != nil {
		return fmt.Errorf("creating output file (%s): %s", filename, err)
	}

	zw := zip.NewWriter(fh)
	defer zw.Close()

	// Export all their database tables into the zip.
	return ExportModels(zw, user)
}

// ZipJson serializes a JSON file into the zipfile.
func ZipJson(zw *zip.Writer, filename string, v any) error {
	fh, err := zw.Create(filename)
	if err != nil {
		return err
	}

	encoder := json.NewEncoder(fh)
	encoder.SetIndent("", " ")

	return encoder.Encode(v)
}

// ZipPhoto copies a user photo into the ZIP archive.
func ZipPhoto(zw *zip.Writer, prefix, filename string) error {
	var (
		diskPath  = photo.DiskPath(filename)
		data, err = os.ReadFile(diskPath)
	)
	if err != nil {
		if os.IsNotExist(err) {
			// Not fatal but log it.
			log.Error("ZipPhoto(%s): read from disk: %s", diskPath, err)
			return nil
		}
		return fmt.Errorf("ZipPhoto(%s): read from disk: %s", diskPath, err)
	}

	outfh, err := zw.Create(path.Join(prefix, filename))
	if err != nil {
		return fmt.Errorf("ZipPhoto(%s): create in zip: %s", filename, err)
	}

	log.Info("Add photo to zip: %s", filename)

	_, err = outfh.Write(data)
	return err
}
