package browser

import (
	"context"
	"fmt"

	"github.com/chromedp/cdproto/page"
	"github.com/chromedp/chromedp"
)

type PrintPDFOptions struct {
	Width         float64
	Height        float64
	Address       string
	ReadySelector string
	// MaxWait       time.Duration
}

func Navigate(
	ctx context.Context,
	addr string,
) error {
	return chromedp.Run(ctx, chromedp.Navigate(addr))
}

func PrintPDF(
	ctx context.Context,
	opts PrintPDFOptions,
) ([]byte, error) {
	var pdfBuffer []byte

	storages := LocalStorageFromContext(ctx)

	tasks := make(chromedp.Tasks, 0)

	// Navigate first to fix the localstorage domain
	// tasks = append(tasks, chromedp.Navigate(opts.Address))

	if len(storages) > 0 {
		js := ""
		for _, l := range storages {
			js += fmt.Sprintf("localStorage.setItem('%s', '%s');", l.Key, l.Value)

		}
		tasks = append(tasks, chromedp.Evaluate(js, nil))
	}

	tasks = append(tasks, chromedp.Navigate(opts.Address))

	if opts.ReadySelector != "" {
		tasks = append(tasks, chromedp.WaitVisible(opts.ReadySelector, chromedp.BySearch))
	}

	tasks = append(tasks, chromedp.ActionFunc(
		func(ctx context.Context) error {
			buf, err := pdfBufferAction(ctx, opts)
			if err == nil {
				pdfBuffer = buf
			}
			return err
		},
	))

	err := chromedp.Run(ctx,
		tasks...,
	)

	return pdfBuffer, err
}

func Login(
	ctx context.Context,
	loginUrl string,
	accountEmail, accountPwd string,
	readySelector string,
) error {

	loginTasks := chromedp.Tasks{
		chromedp.Navigate(loginUrl),
	}

	loginTasks = append(loginTasks,
		chromedp.Navigate(loginUrl),
		// wait until the login page is loaded
		chromedp.WaitVisible(`input[type="email"]`, chromedp.ByQuery),
		chromedp.WaitVisible(`input[type="password"]`, chromedp.ByQuery),
		chromedp.WaitVisible(`button[type="submit"]`, chromedp.ByQuery),
		// input the user name and password
		chromedp.SendKeys(`input[type="email"]`, accountEmail, chromedp.ByQuery),
		chromedp.SendKeys(`input[type="password"]`, accountPwd, chromedp.ByQuery),
		// simulate clicking login
		chromedp.Click(`button[type="submit"]`, chromedp.ByQuery),
	)
	if readySelector != "" {
		loginTasks = append(loginTasks, chromedp.WaitVisible(readySelector, chromedp.BySearch))
	}

	err := chromedp.Run(ctx, loginTasks)
	return err
}

func pdfBufferAction(
	ctx context.Context,
	opts PrintPDFOptions,
) ([]byte, error) {
	params := page.
		PrintToPDF().
		WithPrintBackground(true)
	if opts.Width > 0 {
		params = params.WithPaperWidth(opts.Width)
	}
	if opts.Height > 0 {
		params = params.WithPaperHeight(opts.Height)
	}

	buf, _, err := params.Do(ctx)
	if err != nil {
		return nil, err
	}
	return buf, nil
}
