package infra

import (
	"fmt"
	"strings"
)

// WailsCRUDSpec define la especificación para generar bindings CRUD.
type WailsCRUDSpec struct {
	EntityName string   // Nombre de la entidad (PascalCase, ej: "User")
	Fields     []string // Campos de la entidad (ej: ["Name string", "Email string"])
	WithList   bool     // Generar List method
	WithGet    bool     // Generar Get method
	WithCreate bool     // Generar Create method
	WithUpdate bool     // Generar Update method
	WithDelete bool     // Generar Delete method
}

// GenerateWailsCRUD genera código Go de bindings CRUD para una entidad.
// Retorna el código Go como string — función pura.
func GenerateWailsCRUD(spec WailsCRUDSpec) string {
	var sb strings.Builder
	lower := strings.ToLower(spec.EntityName)
	plural := lower + "s"

	// Tipo
	sb.WriteString(fmt.Sprintf("// %s entity\n", spec.EntityName))
	sb.WriteString(fmt.Sprintf("type %s struct {\n", spec.EntityName))
	sb.WriteString("\tID string `json:\"id\"`\n")
	for _, field := range spec.Fields {
		parts := strings.SplitN(field, " ", 2)
		if len(parts) == 2 {
			jsonTag := strings.ToLower(parts[0])
			sb.WriteString(fmt.Sprintf("\t%s %s `json:\"%s\"`\n", parts[0], parts[1], jsonTag))
		}
	}
	sb.WriteString("}\n\n")

	// List
	if spec.WithList {
		sb.WriteString(fmt.Sprintf("// List%s retorna todos los %s.\n", spec.EntityName+"s", plural))
		sb.WriteString(fmt.Sprintf("func (a *App) List%s() ([]%s, error) {\n", spec.EntityName+"s", spec.EntityName))
		sb.WriteString(fmt.Sprintf("\t// TODO: implement List%s\n", spec.EntityName+"s"))
		sb.WriteString(fmt.Sprintf("\treturn nil, fmt.Errorf(\"not implemented\")\n"))
		sb.WriteString("}\n\n")
	}

	// Get
	if spec.WithGet {
		sb.WriteString(fmt.Sprintf("// Get%s retorna un %s por ID.\n", spec.EntityName, lower))
		sb.WriteString(fmt.Sprintf("func (a *App) Get%s(id string) (%s, error) {\n", spec.EntityName, spec.EntityName))
		sb.WriteString(fmt.Sprintf("\t// TODO: implement Get%s\n", spec.EntityName))
		sb.WriteString(fmt.Sprintf("\treturn %s{}, fmt.Errorf(\"not implemented\")\n", spec.EntityName))
		sb.WriteString("}\n\n")
	}

	// Create
	if spec.WithCreate {
		sb.WriteString(fmt.Sprintf("// Create%s crea un nuevo %s.\n", spec.EntityName, lower))
		sb.WriteString(fmt.Sprintf("func (a *App) Create%s(%s %s) (%s, error) {\n", spec.EntityName, lower, spec.EntityName, spec.EntityName))
		sb.WriteString(fmt.Sprintf("\t// TODO: implement Create%s\n", spec.EntityName))
		sb.WriteString(fmt.Sprintf("\treturn %s, fmt.Errorf(\"not implemented\")\n", lower))
		sb.WriteString("}\n\n")
	}

	// Update
	if spec.WithUpdate {
		sb.WriteString(fmt.Sprintf("// Update%s actualiza un %s existente.\n", spec.EntityName, lower))
		sb.WriteString(fmt.Sprintf("func (a *App) Update%s(%s %s) (%s, error) {\n", spec.EntityName, lower, spec.EntityName, spec.EntityName))
		sb.WriteString(fmt.Sprintf("\t// TODO: implement Update%s\n", spec.EntityName))
		sb.WriteString(fmt.Sprintf("\treturn %s, fmt.Errorf(\"not implemented\")\n", lower))
		sb.WriteString("}\n\n")
	}

	// Delete
	if spec.WithDelete {
		sb.WriteString(fmt.Sprintf("// Delete%s elimina un %s por ID.\n", spec.EntityName, lower))
		sb.WriteString(fmt.Sprintf("func (a *App) Delete%s(id string) error {\n", spec.EntityName))
		sb.WriteString(fmt.Sprintf("\t// TODO: implement Delete%s\n", spec.EntityName))
		sb.WriteString("\treturn fmt.Errorf(\"not implemented\")\n")
		sb.WriteString("}\n\n")
	}

	return sb.String()
}
