package esr

import (
	"esr/internal/config"
	"fmt"
	"os"
	"path/filepath"

	"github.com/evanw/esbuild/pkg/api"
)

type Builder struct {
	Config     *config.Config
	EntryPoint string
	BuiltJS    []string
	BuiltCSS   []string
}

func NewBuilder(c *config.Config, e string) *Builder {
	return &Builder{
		Config:     c,
		EntryPoint: e,
	}
}

func (b *Builder) Build(buildOptions *api.BuildOptions) error {
	result := api.Build(*buildOptions)
	if len(result.Errors) > 0 {
		return fmt.Errorf("esr :: build failed: %v", result.Errors)
	}

	b.BuiltJS = []string{}
	b.BuiltCSS = []string{}

	for _, file := range result.OutputFiles {
		dir := filepath.Dir(file.Path)
		if _, err := os.Stat(dir); os.IsNotExist(err) {
			if err := os.MkdirAll(dir, os.ModePerm); err != nil {
				return fmt.Errorf("esr :: failed to create directory: %v", err)
			}
		}
	
		if err := os.WriteFile(file.Path, file.Contents, os.ModePerm); err != nil {
			return fmt.Errorf("esr :: failed to write file: %v", err)
		}
	
		if filepath.Ext(file.Path) != ".map" {
			if filepath.Ext(file.Path) == ".js" || filepath.Ext(file.Path) == ".mjs" {
				b.BuiltJS = append(b.BuiltJS, file.Path)
			}
		
			if filepath.Ext(file.Path) == ".css" {
				b.BuiltCSS = append(b.BuiltCSS, file.Path)
			}
		}
	}

	return nil
}

func (b *Builder) StartWatch(opts *api.BuildOptions, callback func()) error {
	paths := append([]string{b.EntryPoint}, b.Config.Watch.Paths...)
	watcher, err := NewWatcher(paths)
	if err != nil {
		return fmt.Errorf("failed to start watcher: %v", err)
	}

	watcher.Start(func() {
		if err := b.Build(opts); err != nil {
			fmt.Println("Watch build error:", err)
		}
		callback()
	})

	return nil
}
