package main

import (
	"context"
	"errors"
	"flag"
	"fmt"
	"io"
	"ipa/IPAGo/models"
	"ipa/IPAGo/wrapper"
	"net/http"
	"os"
	"path/filepath"
	"time"

	"github.com/danielgtaylor/huma/v2"
	"github.com/danielgtaylor/huma/v2/adapters/humago"
)

const (
	version = "1.0.1"
)

func main() {
	port := flag.Int("port", 8888, "Port to listen on")
	flag.Parse()

	mux := http.NewServeMux()
	config := huma.DefaultConfig("IPAGo", version)
	config.CreateHooks = nil
	api := humago.New(mux, config)

	huma.Get(
		api, "/auth/login",
		func(ctx context.Context, input *models.AuthInput) (*models.AuthOutput, error) {
			output := &models.AuthOutput{}
			output.Body.Success = wrapper.Auth(input.User, input.Pswd, input.Code)
			return output, nil
		})

	huma.Get(
		api, "/auth/info",
		func(ctx context.Context, input *models.AuthInfoInput) (*models.AuthInfoOutput, error) {
			output := &models.AuthInfoOutput{}
			output.Body.Success = wrapper.AuthInfo(input.User, input.Pswd)
			return output, nil
		})

	huma.Get(
		api, "/search",
		func(ctx context.Context, input *models.SearchInput) (*models.SearchOutput, error) {
			output := &models.SearchOutput{}
			output.Body.Apps = []wrapper.App{}
			output.Body.Success = false

			if input.Limit == 0 {
				input.Limit = 1
			}
			if input.Query == "" {
				return output, nil
			}

			apps, err := wrapper.Search(input.Query, input.Limit)
			if err != nil {
				return output, nil
			}

			output.Body.Success = true
			output.Body.Apps = apps
			return output, nil
		})

	huma.Get(
		api, "/download",
		func(ctx context.Context, input *models.DownloadInput) (*models.DownloadOutput, error) {
			outputPath := filepath.Join(os.TempDir(), fmt.Sprintf("%s.ipa", time.Now().Format("20060102150405")))
			output := &models.DownloadOutput{}
			if input.BundleID == "" {
				return nil, errors.New("bundleID is empty")
			}
			success := wrapper.Download(input.BundleID, outputPath)
			if !success {
				return nil, errors.New("failed to download")
			}
			output.ContentDisposition = fmt.Sprintf("attachment; filename=%s", filepath.Base(outputPath))
			output.ContentType = "application/octet-stream"
			output.Body = func(hctx huma.Context) {
				file, err := os.Open(outputPath)
				if err != nil {
					return
				}
				defer func() {
					file.Close()
					os.Remove(outputPath)
					fmt.Println("File removed after download")
				}()

				// Set Content-Length header so the client can show progress
				if info, err := file.Stat(); err == nil {
					hctx.SetHeader("Content-Length", fmt.Sprintf("%d", info.Size()))
				}

				_, _ = io.Copy(hctx.BodyWriter(), file)
			}
			return output, nil
		})

	addr := fmt.Sprintf(":%d", *port)
	fmt.Printf("Server is running on %s\n", addr)
	http.ListenAndServe(addr, mux)
}
