package utils

import (
	"errors"
	"fmt"
	"strconv"
	"strings"

	"github.com/xuri/excelize/v2"
)

// CardInfo 卡信息(ICCID + MSISDN)
type CardInfo struct {
	ICCID  string
	MSISDN string
}

// CSVParseResult Excel/CSV 解析结果
type CSVParseResult struct {
	Cards       []CardInfo
	TotalCount  int
	ParseErrors []CSVParseError
}

// CSVParseError Excel/CSV 解析错误
type CSVParseError struct {
	Line   int
	ICCID  string
	MSISDN string
	Reason string
}

// DeviceRow 设备导入数据行
type DeviceRow struct {
	Line         int
	DeviceNo     string
	DeviceName   string
	DeviceModel  string
	DeviceType   string
	MaxSimSlots  int
	Manufacturer string
	ICCIDs       []string
}

var (
	// ErrExcelNoSheets Excel文件无工作表
	ErrExcelNoSheets = errors.New("Excel文件无工作表")
	// ErrExcelNoData Excel文件无数据行
	ErrExcelNoData = errors.New("Excel文件无数据行(至少需要表头+1行数据)")
)

// ParseCardExcel 解析包含 ICCID 和 MSISDN 两列的 Excel 文件
// filePath: Excel文件路径(.xlsx格式)
// 返回: 解析结果 (与CSV解析器返回相同的数据结构)
func ParseCardExcel(filePath string) (*CSVParseResult, error) {
	// 1. 打开Excel文件
	f, err := excelize.OpenFile(filePath)
	if err != nil {
		return nil, fmt.Errorf("打开Excel失败: %w", err)
	}
	defer func() {
		if err := f.Close(); err != nil {
			// 日志记录关闭错误,但不影响解析结果
		}
	}()

	// 2. 选择sheet (优先"导入数据",否则第一个)
	sheetName := selectSheet(f)
	if sheetName == "" {
		return nil, ErrExcelNoSheets
	}

	// 3. 读取所有行
	rows, err := f.GetRows(sheetName)
	if err != nil {
		return nil, fmt.Errorf("读取sheet失败: %w", err)
	}

	if len(rows) < 2 {
		return nil, ErrExcelNoData
	}

	// 4. 解析表头 + 数据行
	return parseCardRows(rows)
}

// ParseDeviceExcel 解析设备导入 Excel 文件
// filePath: Excel文件路径(.xlsx格式)
// 返回: 设备行数组、总行数、错误
func ParseDeviceExcel(filePath string) ([]DeviceRow, int, error) {
	// 1. 打开Excel文件
	f, err := excelize.OpenFile(filePath)
	if err != nil {
		return nil, 0, fmt.Errorf("打开Excel失败: %w", err)
	}
	defer func() {
		if err := f.Close(); err != nil {
			// 日志记录关闭错误,但不影响解析结果
		}
	}()

	// 2. 选择sheet
	sheetName := selectSheet(f)
	if sheetName == "" {
		return nil, 0, ErrExcelNoSheets
	}

	// 3. 读取所有行
	rows, err := f.GetRows(sheetName)
	if err != nil {
		return nil, 0, fmt.Errorf("读取sheet失败: %w", err)
	}

	if len(rows) < 2 {
		return nil, 0, ErrExcelNoData
	}

	// 4. 解析表头行,构建列索引
	header := rows[0]
	colIndex := buildDeviceColumnIndex(header)

	// 5. 解析数据行
	var deviceRows []DeviceRow
	for i := 1; i < len(rows); i++ {
		record := rows[i]
		lineNum := i + 1 // Excel行号从1开始,数据从第2行开始

		row := DeviceRow{Line: lineNum}

		// 提取各字段
		if idx := colIndex["device_no"]; idx >= 0 && idx < len(record) {
			row.DeviceNo = strings.TrimSpace(record[idx])
		}
		if idx := colIndex["device_name"]; idx >= 0 && idx < len(record) {
			row.DeviceName = strings.TrimSpace(record[idx])
		}
		if idx := colIndex["device_model"]; idx >= 0 && idx < len(record) {
			row.DeviceModel = strings.TrimSpace(record[idx])
		}
		if idx := colIndex["device_type"]; idx >= 0 && idx < len(record) {
			row.DeviceType = strings.TrimSpace(record[idx])
		}
		if idx := colIndex["max_sim_slots"]; idx >= 0 && idx < len(record) {
			if n, err := strconv.Atoi(strings.TrimSpace(record[idx])); err == nil {
				row.MaxSimSlots = n
			}
		}
		if idx := colIndex["manufacturer"]; idx >= 0 && idx < len(record) {
			row.Manufacturer = strings.TrimSpace(record[idx])
		}

		// 提取ICCID (iccid_1 ~ iccid_4)
		row.ICCIDs = make([]string, 0, 4)
		for j := 1; j <= 4; j++ {
			colName := "iccid_" + strconv.Itoa(j)
			if idx := colIndex[colName]; idx >= 0 && idx < len(record) {
				iccid := strings.TrimSpace(record[idx])
				if iccid != "" {
					row.ICCIDs = append(row.ICCIDs, iccid)
				}
			}
		}

		// 跳过设备号为空的行
		if row.DeviceNo == "" {
			continue
		}

		// 默认最大插槽数为4
		if row.MaxSimSlots == 0 {
			row.MaxSimSlots = 4
		}

		deviceRows = append(deviceRows, row)
	}

	return deviceRows, len(deviceRows), nil
}

// selectSheet 选择要读取的sheet
// 优先返回名为"导入数据"的sheet,否则返回第一个sheet
func selectSheet(f *excelize.File) string {
	sheets := f.GetSheetList()
	if len(sheets) == 0 {
		return ""
	}

	// 优先查找"导入数据"sheet
	for _, sheet := range sheets {
		if sheet == "导入数据" {
			return sheet
		}
	}

	// 返回第一个sheet
	return sheets[0]
}

// parseCardRows 解析卡数据行
// 自动检测表头并提取ICCID和MSISDN列
func parseCardRows(rows [][]string) (*CSVParseResult, error) {
	result := &CSVParseResult{
		Cards:       make([]CardInfo, 0),
		ParseErrors: make([]CSVParseError, 0),
	}

	// 检测表头 (第1行)
	headerSkipped := false
	iccidCol, msisdnCol := -1, -1

	if len(rows) > 0 {
		iccidCol, msisdnCol = findCardColumns(rows[0])
		if iccidCol >= 0 && msisdnCol >= 0 {
			headerSkipped = true
		}
	}

	// 确定数据开始行
	startLine := 0
	if headerSkipped {
		startLine = 1
	}

	// 解析数据行
	for i := startLine; i < len(rows); i++ {
		row := rows[i]
		lineNum := i + 1 // Excel行号从1开始

		// 跳过空行
		if len(row) == 0 {
			continue
		}

		// 提取字段
		iccid := ""
		msisdn := ""

		if iccidCol >= 0 {
			// 有表头,使用列索引
			if iccidCol < len(row) {
				iccid = strings.TrimSpace(row[iccidCol])
			}
			if msisdnCol < len(row) {
				msisdn = strings.TrimSpace(row[msisdnCol])
			}
		} else {
			// 无表头,假设第一列ICCID,第二列MSISDN
			if len(row) >= 1 {
				iccid = strings.TrimSpace(row[0])
			}
			if len(row) >= 2 {
				msisdn = strings.TrimSpace(row[1])
			}
		}

		// 验证
		result.TotalCount++

		if iccid == "" && msisdn == "" {
			// 空行,跳过
			continue
		}

		if iccid == "" {
			result.ParseErrors = append(result.ParseErrors, CSVParseError{
				Line:   lineNum,
				MSISDN: msisdn,
				Reason: "ICCID不能为空",
			})
			continue
		}

		if msisdn == "" {
			result.ParseErrors = append(result.ParseErrors, CSVParseError{
				Line:   lineNum,
				ICCID:  iccid,
				Reason: "MSISDN不能为空",
			})
			continue
		}

		result.Cards = append(result.Cards, CardInfo{
			ICCID:  iccid,
			MSISDN: msisdn,
		})
	}

	return result, nil
}

// findCardColumns 查找ICCID和MSISDN列索引
// 支持中英文列名识别
func findCardColumns(header []string) (iccidCol, msisdnCol int) {
	iccidCol, msisdnCol = -1, -1

	for i, col := range header {
		colLower := strings.ToLower(strings.TrimSpace(col))

		// 识别ICCID列
		if colLower == "iccid" || colLower == "卡号" || colLower == "号码" {
			if iccidCol == -1 { // 只取第一个匹配
				iccidCol = i
			}
		}

		// 识别MSISDN列
		if colLower == "msisdn" || colLower == "接入号" || colLower == "手机号" || colLower == "电话" {
			if msisdnCol == -1 { // 只取第一个匹配
				msisdnCol = i
			}
		}
	}

	return iccidCol, msisdnCol
}

// buildDeviceColumnIndex 构建设备导入列索引
// 识别表头中的列名,返回列名到列索引的映射
func buildDeviceColumnIndex(header []string) map[string]int {
	index := map[string]int{
		"device_no":     -1,
		"device_name":   -1,
		"device_model":  -1,
		"device_type":   -1,
		"max_sim_slots": -1,
		"manufacturer":  -1,
		"iccid_1":       -1,
		"iccid_2":       -1,
		"iccid_3":       -1,
		"iccid_4":       -1,
	}

	for i, col := range header {
		col = strings.ToLower(strings.TrimSpace(col))
		if _, exists := index[col]; exists {
			index[col] = i
		}
	}

	return index
}
