package tools

import (
	"context"
	"strings"

	"github.com/google/uuid"
	"github.com/modelcontextprotocol/go-sdk/mcp"

	"git.warky.dev/wdevs/amcs/internal/store"
	ext "git.warky.dev/wdevs/amcs/internal/types"
)

type HouseholdTool struct {
	store *store.DB
}

func NewHouseholdTool(db *store.DB) *HouseholdTool {
	return &HouseholdTool{store: db}
}

// add_household_item

type AddHouseholdItemInput struct {
	Name     string         `json:"name" jsonschema:"name of the item"`
	Category string         `json:"category,omitempty" jsonschema:"category (e.g. paint, appliance, measurement, document)"`
	Location string         `json:"location,omitempty" jsonschema:"where in the home this item is"`
	Details  map[string]any `json:"details,omitempty" jsonschema:"flexible metadata (model numbers, colors, specs, etc.)"`
	Notes    string         `json:"notes,omitempty"`
}

type AddHouseholdItemOutput struct {
	Item ext.HouseholdItem `json:"item"`
}

func (t *HouseholdTool) AddItem(ctx context.Context, _ *mcp.CallToolRequest, in AddHouseholdItemInput) (*mcp.CallToolResult, AddHouseholdItemOutput, error) {
	if strings.TrimSpace(in.Name) == "" {
		return nil, AddHouseholdItemOutput{}, errRequiredField("name")
	}
	if in.Details == nil {
		in.Details = map[string]any{}
	}
	item, err := t.store.AddHouseholdItem(ctx, ext.HouseholdItem{
		Name:     strings.TrimSpace(in.Name),
		Category: strings.TrimSpace(in.Category),
		Location: strings.TrimSpace(in.Location),
		Details:  in.Details,
		Notes:    strings.TrimSpace(in.Notes),
	})
	if err != nil {
		return nil, AddHouseholdItemOutput{}, err
	}
	return nil, AddHouseholdItemOutput{Item: item}, nil
}

// search_household_items

type SearchHouseholdItemsInput struct {
	Query    string `json:"query,omitempty" jsonschema:"search text matching name or notes"`
	Category string `json:"category,omitempty" jsonschema:"filter by category"`
	Location string `json:"location,omitempty" jsonschema:"filter by location"`
}

type SearchHouseholdItemsOutput struct {
	Items []ext.HouseholdItem `json:"items"`
}

func (t *HouseholdTool) SearchItems(ctx context.Context, _ *mcp.CallToolRequest, in SearchHouseholdItemsInput) (*mcp.CallToolResult, SearchHouseholdItemsOutput, error) {
	items, err := t.store.SearchHouseholdItems(ctx, in.Query, in.Category, in.Location)
	if err != nil {
		return nil, SearchHouseholdItemsOutput{}, err
	}
	if items == nil {
		items = []ext.HouseholdItem{}
	}
	return nil, SearchHouseholdItemsOutput{Items: items}, nil
}

// get_household_item

type GetHouseholdItemInput struct {
	ID uuid.UUID `json:"id" jsonschema:"item id"`
}

type GetHouseholdItemOutput struct {
	Item ext.HouseholdItem `json:"item"`
}

func (t *HouseholdTool) GetItem(ctx context.Context, _ *mcp.CallToolRequest, in GetHouseholdItemInput) (*mcp.CallToolResult, GetHouseholdItemOutput, error) {
	item, err := t.store.GetHouseholdItem(ctx, in.ID)
	if err != nil {
		return nil, GetHouseholdItemOutput{}, err
	}
	return nil, GetHouseholdItemOutput{Item: item}, nil
}

// add_vendor

type AddVendorInput struct {
	Name        string `json:"name" jsonschema:"vendor name"`
	ServiceType string `json:"service_type,omitempty" jsonschema:"type of service (e.g. plumber, electrician, landscaper)"`
	Phone       string `json:"phone,omitempty"`
	Email       string `json:"email,omitempty"`
	Website     string `json:"website,omitempty"`
	Notes       string `json:"notes,omitempty"`
	Rating      *int   `json:"rating,omitempty" jsonschema:"1-5 rating"`
}

type AddVendorOutput struct {
	Vendor ext.HouseholdVendor `json:"vendor"`
}

func (t *HouseholdTool) AddVendor(ctx context.Context, _ *mcp.CallToolRequest, in AddVendorInput) (*mcp.CallToolResult, AddVendorOutput, error) {
	if strings.TrimSpace(in.Name) == "" {
		return nil, AddVendorOutput{}, errRequiredField("name")
	}
	vendor, err := t.store.AddVendor(ctx, ext.HouseholdVendor{
		Name:        strings.TrimSpace(in.Name),
		ServiceType: strings.TrimSpace(in.ServiceType),
		Phone:       strings.TrimSpace(in.Phone),
		Email:       strings.TrimSpace(in.Email),
		Website:     strings.TrimSpace(in.Website),
		Notes:       strings.TrimSpace(in.Notes),
		Rating:      in.Rating,
	})
	if err != nil {
		return nil, AddVendorOutput{}, err
	}
	return nil, AddVendorOutput{Vendor: vendor}, nil
}

// list_vendors

type ListVendorsInput struct {
	ServiceType string `json:"service_type,omitempty" jsonschema:"filter by service type"`
}

type ListVendorsOutput struct {
	Vendors []ext.HouseholdVendor `json:"vendors"`
}

func (t *HouseholdTool) ListVendors(ctx context.Context, _ *mcp.CallToolRequest, in ListVendorsInput) (*mcp.CallToolResult, ListVendorsOutput, error) {
	vendors, err := t.store.ListVendors(ctx, in.ServiceType)
	if err != nil {
		return nil, ListVendorsOutput{}, err
	}
	if vendors == nil {
		vendors = []ext.HouseholdVendor{}
	}
	return nil, ListVendorsOutput{Vendors: vendors}, nil
}
