package swagger

import (
	"fmt"
	"regexp"
	"strconv"
	"strings"

	apiSpec "github.com/zeromicro/go-zero/tools/goctl/api/spec"
)

// RespDoc 表示一個回應文檔定義
type RespDoc struct {
	StatusCode  int                // HTTP 狀態碼
	Schema      string             // 回應類型名稱（單一回應）
	BizCodes    map[string]BizCode // 業務錯誤碼映射（多個回應）
	Description string             // 描述
}

// BizCode 表示業務錯誤碼定義
type BizCode struct {
	Code        string // 業務錯誤碼（如 300101）
	Schema      string // 對應的類型名稱
	Description string // 描述
}

var (
	// @respdoc-200 (TypeName) description
	respdocSimpleRegex = regexp.MustCompile(`@respdoc-(\d+)\s+\((\w+)\)(?:\s+(.+))?`)

	// 業務錯誤碼格式: 300101: (ValidationError) description
	bizCodeRegex = regexp.MustCompile(`(\d+):\s+\((\w+)\)(?:\s+(.+))?`)
)

// parseRespDocsFromDoc 從 Doc 數組中解析所有 @respdoc 定義
func parseRespDocsFromDoc(doc apiSpec.Doc) []RespDoc {
	// Doc 是字符串數組，合併為一個文本
	var text string
	for _, line := range doc {
		text += line + "\n"
	}
	return parseRespDocsFromText(text)
}

// parseRespDocs 從 AtDoc 註解中解析所有 @respdoc 定義
func parseRespDocs(atDoc apiSpec.AtDoc) []RespDoc {
	return parseRespDocsFromText(atDoc.Text)
}

// parseRespDocsFromText 從文本中解析所有 @respdoc 定義
func parseRespDocsFromText(text string) []RespDoc {
	var respDocs []RespDoc

	if text == "" {
		return respDocs
	}

	lines := strings.Split(text, "\n")
	var currentRespDoc *RespDoc
	var inMultiLine bool

	for _, line := range lines {
		line = strings.TrimSpace(line)

		// 跳過空行和純註釋符號
		if line == "" || line == "/*" || line == "*/" || strings.HasPrefix(line, "//") {
			continue
		}

		// 移除行首的註釋符號
		line = strings.TrimPrefix(line, "*")
		line = strings.TrimSpace(line)

		// 檢查是否為 @respdoc 開頭
		if strings.HasPrefix(line, "@respdoc-") {
			// 保存上一個 respDoc
			if currentRespDoc != nil {
				respDocs = append(respDocs, *currentRespDoc)
			}

			// 解析新的 respdoc
			currentRespDoc = parseRespDocLine(line)

			// 檢查是否為多行格式（含有左括號但不含右括號，或右括號後還有註釋符號）
			if strings.Contains(line, "(") && !strings.Contains(line, ")") {
				inMultiLine = true
			} else {
				inMultiLine = false
			}

			// 如果是單行格式，直接添加
			if !inMultiLine && currentRespDoc != nil {
				respDocs = append(respDocs, *currentRespDoc)
				currentRespDoc = nil
			}
		} else if inMultiLine && currentRespDoc != nil {
			// 處理多行格式中的業務錯誤碼
			if strings.Contains(line, ":") && strings.Contains(line, "(") {
				bizCode := parseBizCodeLine(line)
				if bizCode != nil {
					if currentRespDoc.BizCodes == nil {
						currentRespDoc.BizCodes = make(map[string]BizCode)
					}
					currentRespDoc.BizCodes[bizCode.Code] = *bizCode
				}
			}

			// 檢查是否為多行結束（含有右括號和註釋）
			if strings.Contains(line, ")") && strings.Contains(line, "//") {
				// 提取描述
				parts := strings.SplitN(line, "//", 2)
				if len(parts) == 2 {
					currentRespDoc.Description = strings.TrimSpace(parts[1])
				}
				respDocs = append(respDocs, *currentRespDoc)
				currentRespDoc = nil
				inMultiLine = false
			}
		}
	}

	// 添加最後一個 respDoc
	if currentRespDoc != nil {
		respDocs = append(respDocs, *currentRespDoc)
	}

	return respDocs
}

// parseRespDocLine 解析單行 @respdoc 定義
func parseRespDocLine(line string) *RespDoc {
	// 移除 @respdoc- 前綴
	line = strings.TrimPrefix(line, "@respdoc-")

	// 提取狀態碼
	parts := strings.SplitN(line, " ", 2)
	if len(parts) == 0 {
		return nil
	}

	statusCode, err := strconv.Atoi(strings.TrimSpace(parts[0]))
	if err != nil {
		return nil
	}

	respDoc := &RespDoc{
		StatusCode: statusCode,
	}

	if len(parts) < 2 {
		return respDoc
	}

	rest := strings.TrimSpace(parts[1])

	// 檢查是否為簡單格式: (TypeName) description
	matches := respdocSimpleRegex.FindStringSubmatch("@respdoc-" + line)
	if len(matches) >= 3 {
		respDoc.Schema = matches[2]
		if len(matches) >= 4 {
			respDoc.Description = strings.TrimSpace(matches[3])
		}
		return respDoc
	}

	// 檢查是否為多行格式開始: (
	if strings.HasPrefix(rest, "(") && !strings.Contains(rest, ")") {
		// 多行格式，等待後續行處理
		return respDoc
	}

	return respDoc
}

// parseBizCodeLine 解析業務錯誤碼行
func parseBizCodeLine(line string) *BizCode {
	matches := bizCodeRegex.FindStringSubmatch(line)
	if len(matches) < 3 {
		return nil
	}

	bizCode := &BizCode{
		Code:   matches[1],
		Schema: matches[2],
	}

	if len(matches) >= 4 {
		bizCode.Description = strings.TrimSpace(matches[3])
	}

	return bizCode
}

// findTypeByName 在 API 規範中查找類型定義
func findTypeByName(api *apiSpec.ApiSpec, typeName string) apiSpec.Type {
	if typeName == "" {
		return nil
	}

	for _, tp := range api.Types {
		if defStruct, ok := tp.(apiSpec.DefineStruct); ok {
			if defStruct.Name() == typeName {
				return tp
			}
		}
	}

	return nil
}

// getHTTPStatusText 獲取 HTTP 狀態碼的標準文本
func getHTTPStatusText(code int) string {
	switch code {
	case 200:
		return "OK"
	case 201:
		return "Created"
	case 202:
		return "Accepted"
	case 204:
		return "No Content"
	case 400:
		return "Bad Request"
	case 401:
		return "Unauthorized"
	case 403:
		return "Forbidden"
	case 404:
		return "Not Found"
	case 405:
		return "Method Not Allowed"
	case 409:
		return "Conflict"
	case 422:
		return "Unprocessable Entity"
	case 429:
		return "Too Many Requests"
	case 500:
		return "Internal Server Error"
	case 502:
		return "Bad Gateway"
	case 503:
		return "Service Unavailable"
	case 504:
		return "Gateway Timeout"
	default:
		return fmt.Sprintf("HTTP %d", code)
	}
}
