syntax = "v1"

// M5: inspire + research + media image + scout

type (
	// --- Inspire ---
	TrendPublic {
		Id          string   `json:"id"`
		Kind        string   `json:"kind"`
		Label       string   `json:"label"`
		Summary     string   `json:"summary"`
		Heat        int      `json:"heat"`
		Keywords    []string `json:"keywords"`
		Samples     []string `json:"samples"`
		SourceLabel string   `json:"source_label"`
		ObservedAt  int64    `json:"observed_at"`
	}
	TrendListData {
		List []TrendPublic `json:"list"`
	}
	InspireElementPublic {
		Id        string `json:"id"`
		Kind      string `json:"kind"`
		Title     string `json:"title"`
		Body      string `json:"body"`
		RefId     string `json:"ref_id,optional"`
		Reusable  bool   `json:"reusable"`
		CreatedAt int64  `json:"created_at"`
		UpdatedAt int64  `json:"updated_at"`
	}
	InspireElementListData {
		List []InspireElementPublic `json:"list"`
	}
	InspireElementSaveReq {
		Id       string `json:"id,optional"`
		Kind     string `json:"kind,optional"`
		Title    string `json:"title"`
		Body     string `json:"body"`
		RefId    string `json:"ref_id,optional"`
		Reusable bool   `json:"reusable,optional"`
	}
	InspireElementIdPath {
		Id string `path:"id"`
	}
	InspireDraftPublic {
		Title string `json:"title,optional"`
		Body  string `json:"body"`
	}
	InspireMessagePublic {
		Id        string             `json:"id"`
		Role      string             `json:"role"`
		Text      string             `json:"text"`
		Draft     InspireDraftPublic `json:"draft,optional"`
		CreatedAt int64              `json:"created_at"`
	}
	InspireSessionPublic {
		Id               string                 `json:"id"`
		Title            string                 `json:"title,optional"`
		Messages         []InspireMessagePublic `json:"messages"`
		PinnedElementIds []string               `json:"pinned_element_ids"`
		CreatedAt        int64                  `json:"created_at,optional"`
		UpdatedAt        int64                  `json:"updated_at"`
	}
	// 列表摘要（不含完整 messages）
	InspireSessionSummaryPublic {
		Id           string `json:"id"`
		Title        string `json:"title"`
		Preview      string `json:"preview"`
		MessageCount int    `json:"message_count"`
		UpdatedAt    int64  `json:"updated_at"`
		CreatedAt    int64  `json:"created_at"`
		Active       bool   `json:"active"`
	}
	InspireSessionListData {
		List []InspireSessionSummaryPublic `json:"list"`
	}
	InspireSessionIdPath {
		Id string `path:"id"`
	}
	InspireSessionCreateReq {
		Title string `json:"title,optional"`
	}
	InspireChatReq {
		Message   string   `json:"message"`
		PinnedIds []string `json:"pinned_ids,optional"`
		Mode      string   `json:"mode,optional"` // chat|generate
		PersonaId string   `json:"persona_id,optional"`
		SessionId string   `json:"session_id,optional"` // 空 = active
		// generate 專用：待改寫素材（鎖定內容）；空則拒絕產文
		Material string `json:"material,optional"`
	}
	InspireChatData {
		Session  InspireSessionPublic   `json:"session"`
		Messages []InspireMessagePublic `json:"messages"`
	}
	// 觀測：與送出相同的 prompt 組裝（不呼叫 AI、不計費）
	InspirePromptPreviewReq {
		Message   string   `json:"message,optional"`
		PinnedIds []string `json:"pinned_ids,optional"`
		Mode      string   `json:"mode,optional"` // chat|generate
		PersonaId string   `json:"persona_id,optional"`
		SessionId string   `json:"session_id,optional"`
		Material  string   `json:"material,optional"`
	}
	InspirePromptPinnedPublic {
		Id    string `json:"id"`
		Kind  string `json:"kind"`
		Title string `json:"title"`
		Body  string `json:"body"`
	}
	InspirePromptBlockPublic {
		Title string `json:"title"`
		Body  string `json:"body"`
	}
	InspirePromptPreviewData {
		Prompt      string                      `json:"prompt"`
		Mode        string                      `json:"mode"`
		Sections    []string                    `json:"sections"`
		Blocks      []InspirePromptBlockPublic  `json:"blocks"`
		Fingerprint string                      `json:"fingerprint"`
		CharCount   int                         `json:"char_count"`
		RuneCount   int                         `json:"rune_count"`
		Pinned      []InspirePromptPinnedPublic `json:"pinned"`
		Note        string                      `json:"note,optional"`
	}
	ResearchSearchReq {
		Query string `json:"query"`
	}
	ResearchHitPublic {
		Id          string   `json:"id"`
		Title       string   `json:"title"`
		Snippet     string   `json:"snippet"`
		Url         string   `json:"url"`
		Summary     string   `json:"summary,optional"`
		LearnPoints []string `json:"learn_points,optional"`
		ReplyHooks  []string `json:"reply_hooks,optional"`
		SourceLabel string   `json:"source_label,optional"`
	}
	ResearchSearchData {
		List []ResearchHitPublic `json:"list"`
	}
	GenerateImageReq {
		Prompt string `json:"prompt"`
	}
	GenerateImageData {
		Id     string `json:"id"`
		Url    string `json:"url"`
		Prompt string `json:"prompt"`
	}

	// --- Scout ---
	BrandPublic {
		Id             string `json:"id"`
		DisplayName    string `json:"display_name"`
		Brief          string `json:"brief"`
		TargetAudience string `json:"target_audience,optional"`
		Goals          string `json:"goals,optional"`
	}
	BrandListData {
		List []BrandPublic `json:"list"`
	}
	BrandSaveReq {
		Id             string `json:"id,optional"`
		DisplayName    string `json:"display_name"`
		Brief          string `json:"brief,optional"`
		TargetAudience string `json:"target_audience,optional"`
		Goals          string `json:"goals,optional"`
	}
	BrandIdPath {
		Id string `path:"id"`
	}
	BrandActiveData {
		Id string `json:"id"`
	}
	BrandSetActiveReq {
		Id string `json:"id"`
	}
	ProductPublic {
		Id             string   `json:"id"`
		BrandId        string   `json:"brand_id"`
		Label          string   `json:"label"`
		ProductContext string   `json:"product_context"`
		MatchTags      []string `json:"match_tags"`
		PainPoints     []string `json:"pain_points"`
		PlacementUrl   string   `json:"placement_url,optional"`
		CreatedAt      int64    `json:"created_at"`
		UpdatedAt      int64    `json:"updated_at"`
	}
	ProductListData {
		List []ProductPublic `json:"list"`
	}
	ProductSaveReq {
		Id             string   `json:"id,optional"`
		BrandId        string   `json:"brand_id"`
		Label          string   `json:"label"`
		ProductContext string   `json:"product_context,optional"`
		MatchTags      []string `json:"match_tags,optional"`
		PainPoints     []string `json:"pain_points,optional"`
		PlacementUrl   string   `json:"placement_url,optional"`
	}
	ProductIdPath {
		Id string `path:"id"`
	}
	ProductListReq {
		BrandId string `form:"brand_id,optional"`
	}
	ImportProductReq {
		Url string `json:"url"`
	}
	ImportProductData {
		Label          string   `json:"label"`
		ProductContext string   `json:"product_context"`
		PainPoints     []string `json:"pain_points"`
		MatchTags      []string `json:"match_tags"`
		PlacementUrl   string   `json:"placement_url"`
		SourceNote     string   `json:"source_note"`
	}
	ScoutBriefReq {
		Intent    string `json:"intent"`
		BrandId   string `json:"brand_id,optional"`
		ProductId string `json:"product_id,optional"`
		Purpose   string `json:"purpose,optional"`
		Deep      bool   `json:"deep,optional"`
	}
	ScoutBriefPublic {
		Intent         string   `json:"intent"`
		Mode           string   `json:"mode"`
		BrandId        string   `json:"brand_id,optional"`
		ProductId      string   `json:"product_id,optional"`
		ProductLabel   string   `json:"product_label,optional"`
		Pains          []string `json:"pains"`
		Tags           []string `json:"tags"`
		Periphery      []string `json:"periphery"`
		ScanTerms      []string `json:"scan_terms"`
		PlacementNote  string   `json:"placement_note,optional"`
		ResponseStance string   `json:"response_stance,optional"`
		ThemeKey       string   `json:"theme_key,optional"`
		ThemeLabel     string   `json:"theme_label,optional"`
		ProductContext string   `json:"product_context,optional"`
	}
	ScoutScanReq {
		Brief ScoutBriefPublic `json:"brief"`
	}
	ScoutScanJobData {
		Job JobPublic `json:"job"`
	}
	ScoutPostPublic {
		Id                  string `json:"id"`
		BrandId             string `json:"brand_id,optional"`
		Author              string `json:"author"`
		Text                string `json:"text"`
		SearchTag           string `json:"search_tag"`
		Opportunity         string `json:"opportunity"`
		OutreachStatus      string `json:"outreach_status"`
		DraftText           string `json:"draft_text,optional"`
		Score               int    `json:"score"`
		MatchedProductId    string `json:"matched_product_id,optional"`
		MatchedProductLabel string `json:"matched_product_label,optional"`
		MatchReason         string `json:"match_reason,optional"`
		ScoutMode           string `json:"scout_mode,optional"`
		IntentSnippet       string `json:"intent_snippet,optional"`
		ThemeKey            string `json:"theme_key,optional"`
		ThemeLabel          string `json:"theme_label,optional"`
		ScanPath            string `json:"scan_path,optional"`
		Classification      string `json:"classification,optional"`
		Permalink           string `json:"permalink,optional"`
		CreatedAt           int64  `json:"created_at"`
	}
	ScoutPostListData {
		List []ScoutPostPublic `json:"list"`
	}
	ScoutPostListReq {
		BrandId string `form:"brand_id,optional"`
	}
	ScoutPostIdPath {
		Id string `path:"id"`
	}
	ScoutDraftPathReq {
		Id        string `path:"id"`
		PersonaId string `json:"persona_id,optional"`
	}
	ScoutSendPathReq {
		Id        string `path:"id"`
		Text      string `json:"text,optional"`
		AccountId string `json:"account_id,optional"`
	}
	ScoutThemePath {
		ThemeKey string `path:"themeKey"`
	}
	ScoutHomeworkPublic {
		ThemeKey   string           `json:"theme_key"`
		ThemeLabel string           `json:"theme_label"`
		Purpose    string           `json:"purpose"`
		Brief      ScoutBriefPublic `json:"brief"`
		CreatedAt  int64            `json:"created_at"`
	}
	ScoutHomeworkListData {
		List []ScoutHomeworkPublic `json:"list"`
	}
	ScoutHomeworkSaveReq {
		ThemeKey   string           `json:"theme_key"`
		ThemeLabel string           `json:"theme_label"`
		Purpose    string           `json:"purpose,optional"`
		Brief      ScoutBriefPublic `json:"brief"`
	}
	ScoutCrawlerSessionReq {
		Token string `json:"token"`
	}
)

@server (
	jwt: Auth
	group: inspire
	prefix: /api/v1/inspire
	middleware: AuthJWT
)
service gateway {
	@handler ListTrends
	get /trends returns (TrendListData)

	@handler RefreshTrends
	post /trends/refresh returns (TrendListData)

	@handler ListInspireElements
	get /elements returns (InspireElementListData)

	@handler SaveInspireElement
	post /elements (InspireElementSaveReq) returns (InspireElementPublic)

	@handler RemoveInspireElement
	delete /elements/:id (InspireElementIdPath) returns (OkData)

	@handler GetInspireSession
	get /session returns (InspireSessionPublic)

	@handler ClearInspireSession
	post /session/clear returns (InspireSessionPublic)

	@handler ListInspireSessions
	get /sessions returns (InspireSessionListData)

	@handler CreateInspireSession
	post /sessions (InspireSessionCreateReq) returns (InspireSessionPublic)

	@handler GetInspireSessionById
	get /sessions/:id (InspireSessionIdPath) returns (InspireSessionPublic)

	@handler ActivateInspireSession
	post /sessions/:id/activate (InspireSessionIdPath) returns (InspireSessionPublic)

	@handler DeleteInspireSession
	delete /sessions/:id (InspireSessionIdPath) returns (InspireSessionPublic)

	@handler InspireChat
	post /chat (InspireChatReq) returns (InspireChatData)

	@handler InspirePromptPreview
	post /prompt-preview (InspirePromptPreviewReq) returns (InspirePromptPreviewData)
}

@server (
	jwt: Auth
	group: research
	prefix: /api/v1/research
	middleware: AuthJWT
)
service gateway {
	@handler ResearchSearch
	post /search (ResearchSearchReq) returns (ResearchSearchData)
}

@server (
	jwt: Auth
	group: media
	prefix: /api/v1/media
	middleware: AuthJWT
)
service gateway {
	@handler GenerateImage
	post /generate-image (GenerateImageReq) returns (GenerateImageData)
}

@server (
	jwt: Auth
	group: scout
	prefix: /api/v1/scout
	middleware: AuthJWT
)
service gateway {
	@handler ListBrands
	get /brands returns (BrandListData)

	@handler SaveBrand
	post /brands (BrandSaveReq) returns (BrandPublic)

	@handler GetBrand
	get /brands/:id (BrandIdPath) returns (BrandPublic)

	@handler RemoveBrand
	delete /brands/:id (BrandIdPath) returns (OkData)

	@handler GetActiveBrand
	get /brands-active returns (BrandActiveData)

	@handler SetActiveBrand
	post /brands-active (BrandSetActiveReq) returns (BrandActiveData)

	@handler ListProducts
	get /products (ProductListReq) returns (ProductListData)

	@handler ListAllProducts
	get /products/all returns (ProductListData)

	@handler SaveProduct
	post /products (ProductSaveReq) returns (ProductPublic)

	@handler GetProduct
	get /products/:id (ProductIdPath) returns (ProductPublic)

	@handler RemoveProduct
	delete /products/:id (ProductIdPath) returns (OkData)

	@handler ImportProduct
	post /products/import (ImportProductReq) returns (ImportProductData)

	@handler PrepareBrief
	post /brief (ScoutBriefReq) returns (ScoutBriefPublic)

	@handler RunScan
	post /scan (ScoutScanReq) returns (ScoutScanJobData)

	@handler ListScoutPosts
	get /posts (ScoutPostListReq) returns (ScoutPostListData)

	@handler DraftOutreach
	post /posts/:id/draft (ScoutDraftPathReq) returns (ScoutPostPublic)

	@handler SkipOutreach
	post /posts/:id/skip (ScoutPostIdPath) returns (ScoutPostPublic)

	@handler MarkPublished
	post /posts/:id/mark-published (ScoutPostIdPath) returns (ScoutPostPublic)

	@handler SendOutreach
	post /posts/:id/send (ScoutSendPathReq) returns (ScoutPostPublic)

	@handler RemoveScoutPost
	delete /posts/:id (ScoutPostIdPath) returns (OkData)

	@handler RemoveScoutTheme
	delete /themes/:themeKey (ScoutThemePath) returns (OkData)

	@handler ListHomework
	get /homework returns (ScoutHomeworkListData)

	@handler SaveHomework
	post /homework (ScoutHomeworkSaveReq) returns (ScoutHomeworkPublic)

	@handler GetHomework
	get /homework/:themeKey (ScoutThemePath) returns (ScoutHomeworkPublic)

	@handler RemoveHomework
	delete /homework/:themeKey (ScoutThemePath) returns (OkData)

	@handler SetCrawlerSession
	post /crawler-session (ScoutCrawlerSessionReq) returns (OkData)

	@handler ClearCrawlerSession
	delete /crawler-session returns (OkData)
}
