package idlereminder

import (
	"fmt"
	"strconv"
	"strings"
	"time"

	"github.com/andygrunwald/go-jira"
)

const O11Y_PROJECT_KEY = "O11Y"
const TCOC_PROJECT_KEY = "TCOC"

func buildEmailBodyVars(issues []jira.Issue) (map[string]string, error) {
	res := make(map[string]string)
	tcocIssues := filterIssuesByProject(TCOC_PROJECT_KEY, issues)
	if len(tcocIssues) == 0 {
		res["tcoc_body"] = "No Long-tail TCOC issues."
	} else {
		res["tcoc_body"] = buildProjectBodyVars(TCOC_PROJECT_KEY, tcocIssues)
	}
	o11yIssues := filterIssuesByProject(O11Y_PROJECT_KEY, issues)
	if len(o11yIssues) == 0 {
		res["o11y_body"] = "No Long-tail O11Y issues."
	} else {
		res["o11y_body"] = buildProjectBodyVars(O11Y_PROJECT_KEY, o11yIssues)
	}
	return res, nil
}

func filterIssuesByProject(projectKey string, issues []jira.Issue) []jira.Issue {
	filteredIssues := make([]jira.Issue, 0)
	for _, issue := range issues {
		if issue.Fields.Project.Key == projectKey {
			filteredIssues = append(filteredIssues, issue)
		}
	}
	return filteredIssues
}

func buildProjectBodyVars(project string, issues []jira.Issue) string {
	lineStrs := make([]string, 0)

	keyWidth := 10
	priorityWidth := 10
	assigneeWidth := 20
	componentWidth := 30
	leaderWidth := 20
	timeWidth := 20

	for _, issue := range issues {
		key := issue.Key
		if len(key) > keyWidth {
			keyWidth = len(key)
		}

		priority := issue.Fields.Priority.Name
		if len(priority) > priorityWidth {
			priorityWidth = len(priority)
		}

		assignee := issue.Fields.Assignee.DisplayName
		if len(assignee) > assigneeWidth {
			assigneeWidth = len(assignee)
		}

		componentName := make([]string, 0)
		for _, component := range issue.Fields.Components {
			componentName = append(componentName, component.Name)
		}
		componentStr := strings.Join(componentName, ", ")
		if len(componentStr) > componentWidth {
			componentWidth = len(componentStr)
		}
		if egLeader, exist := issue.Fields.Unknowns[EG_LEADER_FIELD]; exist {
			leaderMap, ok := egLeader.(map[string]interface{})
			if ok {
				displayName, displayNameOk := leaderMap["displayName"].(string)
				if displayNameOk {
					leaderWidth = len(displayName)
				}
			}
		}
	}

	// title
	lineStr := fmt.Sprintf(
		"%-"+strconv.Itoa(keyWidth)+"s  | %-"+strconv.Itoa(priorityWidth)+"s  | %-"+strconv.Itoa(assigneeWidth)+"s  | %-"+strconv.Itoa(leaderWidth)+"s  | %-"+strconv.Itoa(timeWidth)+"s  | %-"+strconv.Itoa(timeWidth)+"s  | %-"+strconv.Itoa(componentWidth)+"s  | %s",
		"<b>KEY</b>",
		"<b>PRIORITY</b>",
		"<b>ASSIGNEE</b>",
		"<b>EG LEADER</b>",
		"<b>TIME FROM CREATION</b>",
		"<b>TIME FROM LAST ASSIGN</b>",
		"<b>COMPONENTS</b>",
		"<b>SUMMARY</b>",
	)
	lineStrs = append(lineStrs, lineStr)

	for _, issue := range issues {
		key := issue.Key
		link := JIRA_BROWSE_LINK + key
		keyStr := fmt.Sprintf("<a href=\"%s\" target=\"_blank\">%s</a>", link, key)
		priority := issue.Fields.Priority.Name
		assignee := issue.Fields.Assignee.DisplayName
		summary := issue.Fields.Summary
		timeJira := time.Time(issue.Fields.Created)
		period := int(time.Since(timeJira).Hours())
		periodStr := fmt.Sprintf("%d hours", period)
		periodLastAssign := buildLastAssignPeriodHours(issue)

		componentName := make([]string, 0)
		for _, component := range issue.Fields.Components {
			componentName = append(componentName, component.Name)
		}
		componentStr := strings.Join(componentName, ", ")

		leaderStr := ""
		if egLeader, exist := issue.Fields.Unknowns[EG_LEADER_FIELD]; exist {
			leaderMap, ok := egLeader.(map[string]interface{})
			if ok {
				displayName, displayNameOk := leaderMap["displayName"].(string)
				if displayNameOk {
					leaderStr = displayName
				}
			}
		}

		lineStr = fmt.Sprintf(
			"%s  | %-"+strconv.Itoa(priorityWidth)+"s  | %-"+strconv.Itoa(assigneeWidth)+"s  | %-"+strconv.Itoa(leaderWidth)+"s  | %-"+strconv.Itoa(timeWidth)+"s  | %-"+strconv.Itoa(timeWidth)+"s  | %-"+strconv.Itoa(componentWidth)+"s  | %s",
			keyStr,
			priority,
			assignee,
			leaderStr,
			periodStr,
			periodLastAssign,
			componentStr,
			summary,
		)
		lineStrs = append(lineStrs, lineStr)
	}

	totalStr := strings.Join(lineStrs, "<br>")
	return totalStr
}

func buildLarkBody(tickets []jira.Issue) (string, string) {
	o11yStrs := make([]string, 0)
	ticketStrs := make([]string, 0)
	for _, ticket := range tickets {
		formatStr := ""
		if ticket.Fields.Assignee != nil {
			formatStr = fmt.Sprintf("[%s(%s)](%s%s)", ticket.Key, ticket.Fields.Assignee.DisplayName, JIRA_BROWSE_LINK, ticket.Key)
		}
		if ticket.Fields.Project.Key == O11Y_PROJECT_KEY {
			o11yStrs = append(o11yStrs, formatStr)
		} else {
			ticketStrs = append(ticketStrs, formatStr)
		}
	}
	finalO11Y := strings.Join(o11yStrs, "<br/>")
	finalTickets := strings.Join(ticketStrs, "<br/>")
	return finalO11Y, finalTickets
}

// func truncateString(s string, maxLength int) string {
// 	if len(s) <= maxLength {
// 		return s
// 	}
// 	return s[:maxLength]
// }

func buildLastAssignPeriodHours(ticket jira.Issue) string {
	const layout = "2006-01-02T15:04:05.000-0700"
	for _, history := range ticket.Changelog.Histories {
		for _, item := range history.Items {
			if item.Field == "assignee" && item.ToString == ticket.Fields.Assignee.DisplayName {
				lastAssignTime := history.Created
				t, err := time.Parse(layout, lastAssignTime)
				if err != nil {
					return "N/A"
				}
				hours := int(time.Since(t).Hours())
				return fmt.Sprintf("%d hours", hours)
			}
		}
	}
	return "N/A"
}
