package service

import (
	"bytes"
	"context"
	"encoding/csv"
	"finance-portal/model"
	"finance-portal/pkg/log"
	"fmt"
	"go.uber.org/zap"
	"reflect"
)

func (c *cloudService) HandleDownload(ctx context.Context, req model.SfReqBody) (*bytes.Buffer, error) {
	log.L(ctx).Info("start HandleDownload", zap.String("type", req.Types), zap.String("bill_month", req.BillMonth))

	var records interface{}
	var err error

	// 根据类型获取不同的数据
	switch req.Types {
	case "order":
		records, err = c.store.CloudOrder().ListByMonth(ctx, req.BillMonth, -1)
	case "revrec":
		records, err = c.store.CloudRevrec().ListByMonth(ctx, req.BillMonth, -1)
	case "collection":
		records, err = c.store.CloudCollection().ListByMonth(ctx, req.BillMonth, -1)
	case "ar":
		records, err = c.store.ARTable().ListByMonth(ctx, req.BillMonth)
	case "mk_collection":
		records, err = c.store.MarketplaceCollection().ListByCloudCondition(ctx, req.CollectionMonth, req.CollectionStatus)
	case "pb_collection":
		records, err = c.store.PublicCollection().ListByCloudCondition(ctx, req.StartDate, req.CollectionStatus)
	case "ns_revrec":
		records, err = c.store.NSRevRec().ListByCloudCondition(ctx, req.StartDate)
	case "invoice":
		records, err = c.store.InvoiceRewrite().ListByCloudCondition(ctx, req.StartDate)
	case "exam":
		records, err = c.store.ExamService().ListByCloudCondition(ctx, req.StartDate)
	default:
		return nil, fmt.Errorf("unsupported download type: %s", req.Types)
	}

	if err != nil {
		log.L(ctx).Info("failed to get records",
			zap.String("type", req.Types),
			zap.Error(err))
		return nil, nil
	}

	// 检查是否有数据
	s := reflect.ValueOf(records)
	if s.IsNil() || s.Len() == 0 {
		log.L(ctx).Info("no records found",
			zap.String("type", req.Types))
		return nil, fmt.Errorf("no %s records found", req.Types)
	}

	buf := &bytes.Buffer{}
	writer := csv.NewWriter(buf)
	defer writer.Flush()

	// 获取结构体的字段作为CSV头
	var firstElem reflect.Value
	if s.Index(0).Kind() == reflect.Ptr {
		firstElem = s.Index(0).Elem()
	} else {
		firstElem = s.Index(0)
	}

	t := firstElem.Type()
	headers := make([]string, 0)
	for i := 0; i < t.NumField(); i++ {
		if csvTag := t.Field(i).Tag.Get("csv"); csvTag != "" {
			headers = append(headers, csvTag)
		}
	}

	// 写入CSV头
	if err := writer.Write(headers); err != nil {
		log.L(ctx).Error("failed to write CSV headers", zap.Error(err))
		return nil, fmt.Errorf("failed to write CSV headers: %w", err)
	}

	// 写入记录
	for i := 0; i < s.Len(); i++ {
		record := make([]string, 0)
		var item reflect.Value
		if s.Index(i).Kind() == reflect.Ptr {
			item = s.Index(i).Elem()
		} else {
			item = s.Index(i)
		}

		for j := 0; j < t.NumField(); j++ {
			if csvTag := t.Field(j).Tag.Get("csv"); csvTag != "" {
				field := item.Field(j)
				var value string
				if field.Kind() == reflect.Ptr && !field.IsNil() {
					value = fmt.Sprintf("%v", field.Elem().Interface())
				} else if field.Kind() != reflect.Ptr {
					value = fmt.Sprintf("%v", field.Interface())
				}
				record = append(record, value)
			}
		}
		if err := writer.Write(record); err != nil {
			log.L(ctx).Error("failed to write CSV record", zap.Error(err))
			return nil, fmt.Errorf("failed to write CSV record: %w", err)
		}
	}

	log.L(ctx).Info("successfully created CSV file",
		zap.String("type", req.Types),
		zap.String("bill_month", req.BillMonth))

	return buf, nil
}
