package main

import (
	"encoding/json"
	"fmt"
	"os"
	"strings"
)

// GerberJob represents a KiCad .gbrjob file
type GerberJob struct {
	Header struct {
		GenerationSoftware struct {
			Vendor      string `json:"Vendor"`
			Application string `json:"Application"`
			Version     string `json:"Version"`
		} `json:"GenerationSoftware"`
	} `json:"Header"`
	GeneralSpecs struct {
		ProjectId struct {
			Name string `json:"Name"`
		} `json:"ProjectId"`
		Size struct {
			X float64 `json:"X"`
			Y float64 `json:"Y"`
		} `json:"Size"`
		BoardThickness float64 `json:"BoardThickness"`
	} `json:"GeneralSpecs"`
	FilesAttributes []struct {
		Path         string `json:"Path"`
		FileFunction string `json:"FileFunction"`
		FilePolarity string `json:"FilePolarity"`
	} `json:"FilesAttributes"`
}

// GerberJobResult contains the auto-discovered file assignments
type GerberJobResult struct {
	ProjectName    string
	BoardWidth     float64 // mm
	BoardHeight    float64 // mm
	BoardThickness float64 // mm
	EdgeCutsFile   string  // Profile
	FabFile        string  // AssemblyDrawing,Top
	CourtyardFile  string  // matches courtyard naming
	SoldermaskFile string  // matches mask naming
}

// ParseGerberJob parses a .gbrjob file and returns auto-discovered file mappings
func ParseGerberJob(filename string) (*GerberJobResult, error) {
	data, err := os.ReadFile(filename)
	if err != nil {
		return nil, fmt.Errorf("read gbrjob: %w", err)
	}

	var job GerberJob
	if err := json.Unmarshal(data, &job); err != nil {
		return nil, fmt.Errorf("parse gbrjob JSON: %w", err)
	}

	result := &GerberJobResult{
		ProjectName:    job.GeneralSpecs.ProjectId.Name,
		BoardWidth:     job.GeneralSpecs.Size.X,
		BoardHeight:    job.GeneralSpecs.Size.Y,
		BoardThickness: job.GeneralSpecs.BoardThickness,
	}

	// Map FileFunction to our layer types
	for _, f := range job.FilesAttributes {
		fn := strings.ToLower(f.FileFunction)
		path := f.Path

		switch {
		case fn == "profile":
			result.EdgeCutsFile = path
		case strings.HasPrefix(fn, "assemblydrawing"):
			// F.Fab = AssemblyDrawing,Top
			if strings.Contains(fn, "top") {
				result.FabFile = path
			}
		}

		// Also match by filename patterns for courtyard/mask
		lp := strings.ToLower(path)
		switch {
		case strings.Contains(lp, "courtyard") || strings.Contains(lp, "courty"):
			if strings.Contains(lp, "f_courty") || strings.Contains(lp, "f.courty") || strings.Contains(lp, "-f_courty") {
				result.CourtyardFile = path
			}
		case strings.Contains(lp, "mask") || strings.Contains(lp, "f_mask") || strings.Contains(lp, "f.mask"):
			if strings.Contains(lp, "f_mask") || strings.Contains(lp, "f.mask") || strings.Contains(lp, "-f_mask") {
				result.SoldermaskFile = path
			}
		}
	}

	fmt.Printf("GerberJob: project=%s, board=%.1fx%.1fmm, thickness=%.1fmm\n",
		result.ProjectName, result.BoardWidth, result.BoardHeight, result.BoardThickness)
	fmt.Printf("  EdgeCuts: %s\n", result.EdgeCutsFile)
	fmt.Printf("  F.Fab: %s\n", result.FabFile)
	fmt.Printf("  F.Courtyard: %s\n", result.CourtyardFile)
	fmt.Printf("  F.Mask: %s\n", result.SoldermaskFile)

	if result.EdgeCutsFile == "" {
		return nil, fmt.Errorf("no Edge.Cuts (Profile) layer found in gbrjob")
	}

	return result, nil
}
