package common

const (
	Chat2Query = "chat2query"
	OSSInsight = "ossinsight"
)

type CheckPoint struct {
	Timestamp int64 `json:"timestamp"`
}

type ClusterIDMap struct {
	ClusterID map[string]map[string]bool
}

var (
	Chat2QueryTitle = []string{"session_id", "cluster_id", "user_id", "question",
		"prompt", "response", "status",
		"model_param_model", "model_param_prompt", "model_param_max_token",
		"model_param_temperature", "model_param_top_p", "model_param_n",
		"model_param_stream", "model_param_log_probs", "model_param_stop"}
	OssInsightTitle = []string{"question_id", "cluster_id", "user_id", "prompt", "title",
		"status", "query_sql", "result", "feedback_type", "feedback_content"}
)

const (
	Root              = "/mnt/data/"
	RawDataPath       = Root + "raw-data"
	JoinedDataPath    = Root + "joined-data"
	CleanedDataPath   = Root + "cleaned-data"
	ProcessedDataPath = Root + "processed-data"
	MergedDataPath    = Root + "merged-data"
)

func GetDataTitle(dataSource string) []string {
	switch dataSource {
	case Chat2Query:
		return Chat2QueryTitle
	case OSSInsight:
		return OssInsightTitle
	default:
		return nil
	}
}

var (
	OssInsightClusterIDMap = make(map[string]map[string]bool)
	Chat2QueryClusterIDMap = make(map[string]map[string]bool)
)

func GetClusterIDMap(dataSource string) map[string]map[string]bool {
	switch dataSource {
	case Chat2Query:
		return Chat2QueryClusterIDMap
	case OSSInsight:
		return OssInsightClusterIDMap
	default:
		return nil
	}
}

type Tables struct {
	// db []DataBase
}

type DataBase struct {
	ColumnNames         []ColumnNames `json:"column_names"`
	ColumnNamesOriginal []ColumnNames `json:"column_names_original"`
	ColumnTypes         []string      `json:"column_types"`
	DbId                string        `json:"db_id"`
	ForeignKey          [][]int       `json:"foreign_key"`
	PrimaryKey          []int         `json:"primary_key"`
	TableNames          []string      `json:"table_names"`
	TableNamesOriginal  []string      `json:"table_names_original"`
}

type ColumnNames struct {
	// names []interface{}
}

type OssInsightResult struct {
	Fields []Field                  `json:"fields"`
	Rows   []map[string]interface{} `json:"rows"`
}

type Field struct {
	Name string `json:"name"`
}

type ResultType string

const (
	Null        ResultType = "null"
	Empty       ResultType = "empty"
	ResultEmpty ResultType = "result_empty"
	Normal      ResultType = "normal"
)

type Chat2QueryModelParam string

var (
	Model       Chat2QueryModelParam = "text-davinci-003"
	MaxTokens   Chat2QueryModelParam = "512"
	Temperature Chat2QueryModelParam = "0"
	TopP        Chat2QueryModelParam = "0.4"
	N           Chat2QueryModelParam = "1"
	Stream      Chat2QueryModelParam = "false"
	Logprobs    Chat2QueryModelParam = "0"
	Stop        Chat2QueryModelParam = "#, ---"
)

var DefaultOssInsightPrompt = `
# MySQL SQL
# Table Schema
Table github_events, columns = [id, type, created_at, repo_id, repo_name, actor_id, actor_login, additions, deletions, action, number, org_login, org_id, state, closed_at, comments, pr_merged_at, pr_merged, pr_changed_files, pr_review_comments, pr_or_issue_id, push_size, push_distinct_size, creator_user_login, creator_user_id, pr_or_issue_created_at]
- Column type, enums = ['PullRequestEvent', 'PushEvent', 'IssueCommentEvent', 'IssuesEvent', 'PullRequestReviewCommentEvent', 'WatchEvent', 'CreateEvent', 'DeleteEvent', 'ForkEvent', 'ReleaseEvent']
- Column action:
* type in [PullRequestReviewCommentEvent, IssueCommentEvent, ReviewEvent]: created
* type in [PullRequestEvent, IssuesEvent]: opened, closed, reopened
- Column number, number is issue number
- Column created_at, closed_at, pr_merged_at, pr_or_issue_created_at DEFAULT '1970-01-01 00:00:00'
- Column additions, deletions: only existed in PullRequestEvent
- Column actor_id, actor_login: who trigger the event

Table github_repos, columns = [repo_id, repo_name, owner_id, owner_login, owner_is_org, description, primary_language, license, stars, forks, parent_repo_id, is_archived, is_deleted, latest_released_at, pushed_at, created_at, updated_at]
- Column repo_id: primary key
- Column primary_language: refers to the primary programming language by the repo, not the framework or software, invalid = ['']

Table github_users, columns = [id, login, type, name, organization, country_code, followers, followings, created_at, updated_at]
- Column id: primary key
- Column type, enums = ['USR', 'ORG']
- Column country_code, invalid = ['', 'N/A', 'UND']
- Column organization: include company information, invalid = ['',  null]

Table trending_repos, contains the most popular repositories recently, columns = [repo_name, created_at]
Table github_repo_topics, columns = [repo_id, topic]

# Table Relations
github_events.repo_id = github_repos.repo_id
github_events.actor_id = github_users.id
github_events.actor_login = github_users.login
github_events.creator_user_id = github_users.id
github_repos.owner_id = github_users.id
github_repos.repo_id = github_repo_topics.repo_id
trending_repos.repo_name = github_repos.repo_name

Select statement limit 20 by default, if question need more data, please add limit 50
Order by popularity DESC by default
If the time period is not specified, assume a duration of 6 months
Use column alias for all columns: SELECT ge.repo_name AS repo_name
Open to merged time: TIMESTAMPDIFF(SECOND, ge.pr_or_issue_created_at, ge.closed_at)
Exclude bots: actor_login NOT LIKE "%bot%"
xxx(related) projects: LOWER(github_repos.description) LIKE LOWER('%xxx%')
Database, repos about database: LOWER(github_repos.description) LIKE LOWER('%database%')
xxx developers: who contribute to xxx related projects
Filter repos by @org_or_user_login: owner_login = 'org_or_user_login'
Filter events by one repo named @org_or_user_login/repo_name: ge.repo_id = (SELECT repo_id FROM github_repos WHERE repo_name = 'org_or_user_login/repo_name' LIMIT 1)
Star in 2022: WHERE ge.type = 'WatchEvent' AND ge.action = 'started' AND YEAR(ge.created_at) = 2022
The fastest growing repo in 2022 means repo gained the most stars in 2022
Merged PR: type = 'PullRequestEvent' AND action = 'closed' AND pr_merged = 1
Use type = 'PullRequestEvent' AND action = 'opened' to count pull requests
Contributor: a person who submitted a pull request to the repository.
Reviewer: a person who creates PullRequestReviewCommentEvent,IssueCommentEvent and ReviewEvent, filter by action="created"
The number of contributors: COUNT(DISTINCT actor_id)
China's repos means the repo owner is chinese
The most popular(or interesting) repos have the most stars
The most active repos have the most events
Similar repos refer to repositories on GitHub that have the highest number of shared topics with a specified repository. (github_repos JOIN github_repo_topics JOIN {CTE table contains topics of this repo}, order by number of shared topics desc)
Use gu.organization as the only data source of company info
Users have common interest means their starred repos have intersections
Trend of a programming language means new created repos written in this language MoM
Use "count of new created repos written in a spceific language" to calculate programming language rankings, last 3 months by default

# Example
A template for calculating star history of a specified repo across months:
SELECT DATE_FORMAT(ge.created_at, '%Y-%m-01') AS t_month, COUNT(*) AS stars FROM github_events ge WHERE ge.type = 'WatchEvent' AND ge.repo_id = (SELECT repo_id FROM github_repos WHERE repo_name = {fill with repo_name of specified repo and remove @ !!!} LIMIT 1) GROUP BY t_month ORDER BY t_month ASC

# ChartOptions
type Column = string; // must be the column name in the SQL result!!!
PieChart {label: Column; value: Column;}
LineChart {x: Column; y: Column | Column[];}
BarChart {x: Column; y: Column | Column[];}
MapChart {country_code: Column; value: Column;}
NumberCard {value: Column;}
RepoCard {repo_name: Column;}
PersonalCard {user_login: Column;}
Table {columns: Column[];}


use the answer template:
{
The question after revised, marked as RQ, RQ should be a clear and concise statement of the question:
{RQ = {to_fill}}

{sqlCanAnswer:boolean = {to_fill}}

Must follow the rules one by one, use the best practice to write a single SQL to answer RQ (make sure check relations of sub-questions).
rules {
- follow the table schema above strictly, do not use any non-exists table!!!
- use CTEs in SQL to simplify complex queries and reuse intermediate result sets
- avoid "Invalid use of group function" error
- avoid "Unknown column" error
- if using format "{table name}.{column name}", make sure column "{column name}" belongs to table "{table name}"
- avoid ambiguous column references by using table aliases and double-checking column names before generated
- if there is no specific repo, scan all repos
- if question is talking about comparison, compare their stars only
- don't use reserved word as column alias name
}
{sql: string = {to_fill}}
Use chart to display the result, marked as chart:
{chart: {chartName: string; title: string; options: ChartOptions;} = {to_fill}}
}
Begin:
Let's think step by step, generate an answer.json to answer the question "In GitHub, {{question}}":
---
answer.json // must only output a pretty JSON!!!
`
