package incident

import (
	"regexp"
	"strings"
	"time"

	coreuser "github.com/tidbcloud/aisupport/packages/sdk-go/contracts/entity/core-server/user/v1"
	"github.com/tidbcloud/devops/api"
	"github.com/tidbcloud/devops/entity"
)

type ListIncidentsResp struct {
	api.BaseResp

	Total     int64              `json:"total"`
	Incidents []*entity.Incident `json:"items"`
}

type ListIncidentsReq struct {
	api.PaginationReq

	WarRoomID         *uint64                `form:"war_room_id" json:"war_room_id"`
	StatusIs          *entity.IncidentStatus `form:"status" json:"status"`
	TierIs            *entity.IncidentTier   `form:"tier" json:"tier"`
	ComponentsContain []string               `form:"components" json:"components"`
	BizRegionsContain []string               `form:"biz_regions" json:"biz_regions"`
}

type GetIncidentResp struct {
	Incident *entity.Incident `json:"incident"`
}

type CreateIncidentReq struct {
	Name string `json:"name"`

	Status string `json:"status"`
	Tier   string `json:"tier"`

	Components string `json:"components"`
	BizRegions string `json:"biz_regions"`

	Oncallers []string `json:"oncallers"`
	Leaders   []string `json:"leaders"`
	FBOwners  []string `json:"fbowners"`

	FeishuUrl      string                         `json:"feishu_url"`
	JiraIssues     string                         `json:"jira_issues"`
	JiraIssueLinks []entity.IncidentJiraIssueLink `json:"jira_issue_links"`

	Description          string     `json:"description"`
	IncidentStartTime    *time.Time `json:"incident_start_time"`
	IncidentResolvedTime *time.Time `json:"incident_resolve_time"`
	WarRoomID            *uint64    `json:"war_room_id"`

	NeedGenerateFeishuMessage bool `json:"need_generate_feishu"`
}

type CreateIncidentResp struct {
	IncidentId uint64 `json:"incident_id"`
}

type UpdateIncidentReq struct {
	Name *string `json:"name"`

	Status *string `json:"status"`
	Tier   *string `json:"tier"`

	Components *string `json:"components"`
	BizRegions *string `json:"biz_regions"`

	Oncallers *[]string `json:"oncallers"`
	Leaders   *[]string `json:"leaders"`
	FBOwners  *[]string `json:"fbowners"`

	FeishuUrl      *string                         `json:"feishu_url"`
	JiraIssues     *string                         `json:"jira_issues"`
	JiraIssueLinks *[]entity.IncidentJiraIssueLink `json:"jira_issue_links"`

	Description          *string    `json:"description"`
	IncidentStartTime    *time.Time `json:"incident_start_time"`
	IncidentResolvedTime *time.Time `json:"incident_resolve_time"`
	WarRoomID            *uint64    `json:"war_room_id"`

	ExtractPostMortemToDoActions bool `json:"extract_postmortem_todo_actions"`
}

type UpdateIncidentResp struct {
	PostMortemToDoActionImportStarted bool   `json:"postmortem_todo_action_import_started"`
	PostMortemToDoActionImportStatus  string `json:"postmortem_todo_action_import_status"`
}

type ImportIncidentPostMortemToDoActionsResp struct {
	PostMortemToDoActionImportStarted bool   `json:"postmortem_todo_action_import_started"`
	PostMortemToDoActionImportStatus  string `json:"postmortem_todo_action_import_status"`
}

type DeleteIncidentResp struct {
	DeletedIncidentId uint64 `json:"deleted_incident_id"`
}

type ListIncidentLogsResp struct {
	IncidentId uint64                    `json:"incident_id"`
	LogItems   []*entity.IncidentLogItem `json:"items"`
}

type GetIncidentLogItem struct {
	IncidentLogItem *entity.IncidentLogItem `json:"incident_logitem"`
}

type CreateIncidentLogItemResp struct {
	LogItemId uint64 `json:"logitem_id"`
}

type UpdateIncidentLogItemResp struct {
}

type DeleteIncidentLogItemResp struct {
	DeletedIncidentLogItemId uint64 `json:"deleted_incident_logitem_id"`
}

type CreateFeishuTaskReq struct {
	Title       string     `json:"title"`
	Description string     `json:"description"`
	DueTime     *time.Time `json:"due_time"`
	IncidentUrl string     `json:"incident_url"`
	Executors   []string   `json:"executors"`
	Followers   []string   `json:"followers"`
}

type CreateFeishuTaskResp struct {
	TaskId string `json:"task_id"`
}

type IncidentPostMortemToDoAction struct {
	Id           uint64           `json:"id"`
	PostMortemId uint64           `json:"postmortem_id"`
	Persons      []*coreuser.User `json:"persons"`
	Deadline     *time.Time       `json:"deadline"`
	Status       string           `json:"status"` // Open or InProgress or Done
}

type ListIncidentPostMortemToDoActionsResp struct {
	IncidentId      uint64                                 `json:"incident_id"`
	ToDoActionItems []*entity.IncidentPostMortemToDoAction `json:"items"`
}

type GetIncidentPostMortemToDoActionResp struct {
	ToDoAction *entity.IncidentPostMortemToDoAction `json:"incident_postmortem_todoaction"`
}

func (req CreateIncidentReq) ToIncidentEntity() *entity.Incident {
	jiraIssues := req.JiraIssues
	if len(req.JiraIssueLinks) > 0 {
		jiraIssues = SerializeIncidentJiraIssueLinks(req.JiraIssueLinks)
	}
	return &entity.Incident{
		Name:                 req.Name,
		Status:               entity.IncidentStatus(req.Status),
		Tier:                 entity.IncidentTier(req.Tier),
		Components:           req.Components,
		BizRegions:           req.BizRegions,
		Oncallers:            emailsToUserEntities(req.Oncallers),
		Leaders:              emailsToUserEntities(req.Leaders),
		FBOwners:             emailsToUserEntities(req.FBOwners),
		FeishuUrl:            req.FeishuUrl,
		JiraIssues:           jiraIssues,
		JiraIssueLinks:       ParseIncidentJiraIssueLinks(jiraIssues),
		Description:          req.Description,
		IncidentStartTime:    NormalizeIncidentTime(req.IncidentStartTime),
		IncidentResolvedTime: NormalizeIncidentTime(req.IncidentResolvedTime),
		WarRoomID:            req.WarRoomID,
	}
}

func (req UpdateIncidentReq) ApplyToIncidentEntity(base *entity.Incident) *entity.Incident {
	merged := *base

	if req.Name != nil {
		merged.Name = *req.Name
	}
	if req.Status != nil {
		merged.Status = entity.IncidentStatus(*req.Status)
	}
	if req.Tier != nil {
		merged.Tier = entity.IncidentTier(*req.Tier)
	}
	if req.Components != nil {
		merged.Components = *req.Components
	}
	if req.BizRegions != nil {
		merged.BizRegions = *req.BizRegions
	}
	if req.Oncallers != nil {
		merged.Oncallers = emailsToUserEntities(*req.Oncallers)
	}
	if req.Leaders != nil {
		merged.Leaders = emailsToUserEntities(*req.Leaders)
	}
	if req.FBOwners != nil {
		merged.FBOwners = emailsToUserEntities(*req.FBOwners)
	}
	if req.FeishuUrl != nil {
		merged.FeishuUrl = *req.FeishuUrl
	}
	if req.JiraIssues != nil {
		merged.JiraIssues = *req.JiraIssues
		merged.JiraIssueLinks = ParseIncidentJiraIssueLinks(merged.JiraIssues)
	}
	if req.JiraIssueLinks != nil {
		merged.JiraIssueLinks = append([]entity.IncidentJiraIssueLink(nil), (*req.JiraIssueLinks)...)
		merged.JiraIssues = SerializeIncidentJiraIssueLinks(*req.JiraIssueLinks)
	}
	if req.Description != nil {
		merged.Description = *req.Description
	}
	if req.IncidentStartTime != nil {
		merged.IncidentStartTime = NormalizeIncidentTime(req.IncidentStartTime)
	}
	if req.IncidentResolvedTime != nil {
		merged.IncidentResolvedTime = NormalizeIncidentTime(req.IncidentResolvedTime)
	}
	if req.WarRoomID != nil {
		merged.WarRoomID = req.WarRoomID
	}

	return &merged
}

var incidentJiraIssueKeyRE = regexp.MustCompile(`([A-Z][A-Z0-9]+-\d+)`)

func ParseIncidentJiraIssueLinks(jiraIssues string) []entity.IncidentJiraIssueLink {
	items := strings.Fields(jiraIssues)
	if len(items) == 0 {
		return nil
	}

	links := make([]entity.IncidentJiraIssueLink, 0, len(items))
	for _, item := range items {
		link := entity.IncidentJiraIssueLink{URL: item}
		if match := incidentJiraIssueKeyRE.FindStringSubmatch(item); len(match) > 1 {
			link.Key = match[1]
		}
		links = append(links, link)
	}
	return links
}

func SerializeIncidentJiraIssueLinks(links []entity.IncidentJiraIssueLink) string {
	if len(links) == 0 {
		return ""
	}

	urls := make([]string, 0, len(links))
	for _, link := range links {
		if strings.TrimSpace(link.URL) == "" {
			continue
		}
		urls = append(urls, strings.TrimSpace(link.URL))
	}
	return strings.Join(urls, " ")
}

func NormalizeIncidentTime(t *time.Time) *time.Time {
	if t == nil {
		return nil
	}
	normalized := t.UTC().Truncate(time.Second)
	return &normalized
}

func NormalizeIncidentTimeForService(t *time.Time) *time.Time {
	return NormalizeIncidentTime(t)
}

func (req CreateFeishuTaskReq) ToIncidentEntity() *entity.FeishuTask {
	return &entity.FeishuTask{
		Title:       req.Title,
		Description: req.Description,
		IncidentUrl: req.IncidentUrl,
		DueTime:     req.DueTime,
		Executors:   req.Executors,
		Followers:   req.Followers,
	}
}

func emailsToUserEntities(emails []string) []*coreuser.User {
	users := []*coreuser.User{}
	for _, email := range emails {
		users = append(users, &coreuser.User{Email: email})
	}
	return users
}

type ListIncidentPostMortemItemsResp struct {
	IncidentId      uint64                       `json:"incident_id"`
	PostMortemItems []*entity.IncidentPostMortem `json:"items"`
}

type GetIncidentPostMortemResp struct {
	PostMortem *entity.IncidentPostMortem `json:"incident_post_mortem"`
}

type CreateIncidentPostMortemReq struct {
	Id                    uint64           `json:"id"`
	IncidentId            uint64           `json:"incident_id"`
	CreatedAt             *time.Time       `json:"created_at"`
	ReviewedAt            *time.Time       `json:"reviewed_at"`
	InvolvedEngineers     []*coreuser.User `json:"involved_engineers"`
	IncidentStartTime     *time.Time       `json:"incident_start_time"`
	IncidentEndTime       *time.Time       `json:"incident_end_time"`
	ImpactedTenants       string           `json:"involved_tenants"`
	TechnicalImpactLevel  string           `json:"technical_impact_level"`
	MinutesToResolved     uint64           `json:"minutes_to_resolved"`
	CustomerImpactMinutes uint64           `json:"customer_impact_minutes"`
	Summary               string           `json:"summary"`
	Impact                string           `json:"impact"`
	MinutesToDetect       uint64           `json:"minutes_to_detect"`
	Resolution            string           `json:"resolution"`
	RootCauses            string           `json:"root_causes"`
	Background            string           `json:"background"`
	BugMechanism          string           `json:"bug_mechanism"`
	WhatWorked            string           `json:"what_worked"`
	WhatDidNotWork        string           `json:"what_did_not_work"`
	WhereWeWereLucky      string           `json:"where_we_were_lucky"`
	TopIssues             string           `json:"top_issues"`
}

type CreateIncidentPostMortemResp struct {
	Id uint64
}

type UpdateIncidentPostMortemReq struct {
	Id                    uint64           `json:"id"`
	IncidentId            uint64           `json:"incident_id"`
	CreatedAt             *time.Time       `json:"created_at"`
	ReviewedAt            *time.Time       `json:"reviewed_at"`
	InvolvedEngineers     []*coreuser.User `json:"involved_engineers"`
	IncidentStartTime     *time.Time       `json:"incident_start_time"`
	IncidentEndTime       *time.Time       `json:"incident_end_time"`
	ImpactedTenants       string           `json:"involved_tenants"`
	TechnicalImpactLevel  string           `json:"technical_impact_level"`
	MinutesToResolved     uint64           `json:"minutes_to_resolved"`
	CustomerImpactMinutes uint64           `json:"customer_impact_minutes"`
	Summary               string           `json:"summary"`
	Impact                string           `json:"impact"`
	MinutesToDetect       uint64           `json:"minutes_to_detect"`
	Resolution            string           `json:"resolution"`
	RootCauses            string           `json:"root_causes"`
	Background            string           `json:"background"`
	BugMechanism          string           `json:"bug_mechanism"`
	WhatWorked            string           `json:"what_worked"`
	WhatDidNotWork        string           `json:"what_did_not_work"`
	WhereWeWereLucky      string           `json:"where_we_were_lucky"`
	TopIssues             string           `json:"top_issues"`
}

type UpdateIncidentPostMortemResp struct {
}

type DeleteIncidentPostMortemResp struct {
}

type ListIncidentPostMortemTimelinesResp struct {
	PostmortemId  uint64                                   `json:"postmortem_id"`
	TimelineItems []*entity.IncidentPostMortemTimelineItem `json:"items"`
}

type GetIncidentPostMortemTimelineResp struct {
	Timeline *entity.IncidentPostMortemTimelineItem `json:"incident_postmortem_timeline"`
}

type CreateIncidentPostMortemTimelineReq struct {
	Id           uint64     `json:"id"`
	PostMortemId uint64     `json:"postmortem_id"`
	HappenedAt   *time.Time `json:"happened_at"`
	ItemType     string     `json:"item_type"`
	Description  string     `json:"description"`
}

type CreateIncidentPostMortemTimelineResp struct {
	Id uint64
}

type UpdateIncidentPostMortemTimelineReq struct {
	Id           uint64     `json:"id"`
	PostMortemId uint64     `json:"postmortem_id"`
	HappenedAt   *time.Time `json:"happened_at"`
	ItemType     string     `json:"item_type"`
	Description  string     `json:"description"`
}

type UpdateIncidentPostMortemTimelineResp struct {
}

type DeleteIncidentPostMortemTimelineResp struct {
}

type CreateIncidentPostMortemToDoActionReq struct {
	Id               uint64     `json:"id"`
	PostMortemId     uint64     `json:"postmortem_id"`
	Persons          []string   `json:"persons"`
	Deadline         *time.Time `json:"deadline"`
	Status           *string    `json:"status"` // Open or InProgress or Done
	Description      string     `json:"description"`
	Title            string     `json:"title"`
	Type             *string    `json:"type"`
	Priority         *string    `json:"priority"`
	LinkedJiraIssue  *string    `json:"linked_jira_issue"`
	CreateFeishuTask bool       `json:"create_feishu_task"`
}

type CreateIncidentPostMortemToDoActionResp struct {
	Id uint64
}

type UpdateIncidentPostMortemToDoActionReq struct {
	Id              uint64     `json:"id"`
	Persons         []string   `json:"persons"`
	Deadline        *time.Time `json:"deadline"`
	Description     *string    `json:"description"`
	Title           *string    `json:"title"`
	Type            *string    `json:"type"`
	Priority        *string    `json:"priority"`
	LinkedJiraIssue *string    `json:"linked_jira_issue"`
	Status          *string    `json:"status"` // Open or InProgress or Done
}

type UpdateIncidentPostMortemToDoActionResp struct {
}

type DeleteIncidentPostMortemToDoActionResp struct {
}

type IncidentComponentDefinition struct {
	Key           string `json:"key"`
	Name          string `json:"name"`
	Enabled       bool   `json:"enabled"`
	Order         int    `json:"order"`
	T1RuleSummary string `json:"t1_rule_summary,omitempty"`
	T2RuleSummary string `json:"t2_rule_summary,omitempty"`
	T3RuleSummary string `json:"t3_rule_summary,omitempty"`
	RuleDocURL    string `json:"rule_doc_url,omitempty"`
}

type GetIncidentComponentOptionsResp struct {
	Components  []string                      `json:"components" binding:"required"`
	Definitions []IncidentComponentDefinition `json:"definitions"`
}
