// Copyright 2020-2026 Buf Technologies, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//nolint:gosec
package main

import (
	"archive/tar"
	"bytes"
	"compress/gzip"
	"context"
	"errors"
	"flag"
	"fmt"
	"go/format"
	"io"
	"net/http"
	"os"
	"path/filepath"
	"runtime/debug"
	"time"

	"github.com/bufbuild/protocompile/internal/ext/bitsx"
	"github.com/bufbuild/protocompile/internal/ext/flagx"
)

func main() {
	flagx.Main(func() (e error) {
		commit := flag.Arg(0)

		out := fmt.Sprintf("googleapis-%s.tar.gz", commit)
		_, err := os.Stat(out)
		if err == nil || !errors.Is(err, os.ErrNotExist) {
			return err
		}

		url := fmt.Sprintf("https://github.com/googleapis/googleapis/archive/%s.tar.gz", commit)

		start := time.Now()
		req, err := http.NewRequestWithContext(context.Background(), http.MethodGet, url, nil)
		if err != nil {
			return err
		}
		resp, err := http.DefaultClient.Do(req)
		if err != nil {
			return err
		}

		if resp.Body != nil {
			defer func() {
				if err = resp.Body.Close(); err != nil && e == nil {
					e = err
				}
			}()
		}

		if resp.StatusCode != http.StatusOK {
			return fmt.Errorf("downloading %s resulted in status code %s", url, resp.Status)
		}

		ar, err := os.Create(out)
		if err != nil {
			return err
		}

		dir := "googleapis-" + commit
		total, err := filterArchive(ar, resp.Body, func(path string) string {
			rel, err := filepath.Rel(dir, path)
			if err != nil || filepath.Ext(path) != ".proto" {
				return ""
			}
			return rel
		})
		if err != nil {
			return err
		}
		elapsed := time.Since(start)

		stat, err := os.Stat(out)
		if err != nil {
			return err
		}

		fmt.Printf("googleapis: downloaded commit %v (%v, compressed to %v, %0.3f%%) in %v\n",
			commit, bitsx.ByteSize(total), bitsx.ByteSize(stat.Size()), float64(stat.Size())/float64(total)*100, elapsed)

		info, ok := debug.ReadBuildInfo()
		if !ok {
			return errors.New("debug: could not read build info")
		}

		embed := new(bytes.Buffer)
		fmt.Fprintf(embed, "// Code generated by %s. DO NOT EDIT.\n\n", info.Path)
		fmt.Fprintf(embed, "package %s\n\n", os.Getenv("GOPACKAGE"))
		fmt.Fprintf(embed, "import _ \"embed\"\n\n")

		fmt.Fprintf(embed, "//go:embed %s\n", out)
		fmt.Fprintf(embed, "var archive string\n")

		src, err := format.Source(embed.Bytes())
		if err != nil {
			return err
		}
		return os.WriteFile("archive.go", src, 0666)
	})
}

func filterArchive(dst io.Writer, src io.Reader, filter func(string) string) (total int64, err error) {
	dstGz, err := gzip.NewWriterLevel(dst, gzip.BestCompression)
	if err != nil {
		return total, err
	}
	dstAr := tar.NewWriter(dstGz)

	SrcGz, err := gzip.NewReader(src)
	if err != nil {
		return total, err
	}
	srcAr := tar.NewReader(SrcGz)

	for {
		hdr, err := srcAr.Next()
		if err == io.EOF {
			break
		}
		if err != nil {
			return total, err
		}

		if hdr == nil || hdr.Typeflag != tar.TypeReg {
			continue
		}

		hdr.Name = filter(hdr.Name)
		if hdr.Name == "" {
			continue
		}

		if err := dstAr.WriteHeader(hdr); err != nil {
			return total, err
		}

		n, err := io.Copy(dstAr, srcAr)
		if err != nil {
			return total, err
		}
		total += n
	}

	if err := dstAr.Close(); err != nil {
		return total, err
	}
	if err := dstGz.Close(); err != nil {
		return total, err
	}
	return total, err
}
