package dispute

import (
	"context"
	"time"

	"hfb_sys/backend/internal/model"
	"hfb_sys/backend/internal/modules/notification"

	"gorm.io/gorm"
	"gorm.io/gorm/clause"
)

func (r *Repository) Create(ctx context.Context, userID uint64, orderID uint64, req CreateRequest) (*DisputeDTO, error) {
	var createdID uint64
	err := r.db.WithContext(ctx).Transaction(func(tx *gorm.DB) error {
		var order model.RentalOrder
		if err := tx.Clauses(clause.Locking{Strength: "UPDATE"}).First(&order, orderID).Error; err != nil {
			return err
		}
		if order.RenterID != userID && order.OwnerID != userID {
			return ErrPermissionDenied
		}
		if order.Status == "completed" || order.Status == "cancelled" || order.Status == "closed" {
			return ErrInvalidDispute
		}
		isCheckoutDispute := order.Status == "pending_checkout_confirm" || order.Status == "pending_checkout_accept"
		var count int64
		if err := tx.Model(&model.Dispute{}).
			Where("order_id = ? AND status IN ?", order.ID, []string{"open", "processing"}).
			Count(&count).Error; err != nil {
			return err
		}
		if count > 0 {
			return ErrDisputeExists
		}

		targetID := order.OwnerID
		if userID == order.OwnerID {
			targetID = order.RenterID
		}
		evidence, err := marshalEvidence(req.EvidenceURLS)
		if err != nil {
			return err
		}
		row := model.Dispute{
			OrderID:                  order.ID,
			InitiatorID:              userID,
			TargetUserID:             targetID,
			Type:                     disputeType(req.Type, isCheckoutDispute),
			Status:                   "open",
			Description:              req.Description,
			EvidenceURLS:             evidence,
			PreviousOrderStatus:      order.Status,
			PreviousHandoffStatus:    order.HandoffStatus,
			PreviousSettlementStatus: order.SettlementStatus,
		}
		var checkout model.OrderCheckout
		if isCheckoutDispute {
			if err := tx.Clauses(clause.Locking{Strength: "UPDATE"}).
				Where("order_id = ? AND status IN ?", order.ID, []string{"submitted", "countered"}).
				Order("id DESC").
				First(&checkout).Error; err != nil {
				return err
			}
			row.CheckoutID = &checkout.ID
			row.PreviousCheckoutStatus = checkout.Status
		}
		if err := tx.Create(&row).Error; err != nil {
			return err
		}
		if isCheckoutDispute {
			now := time.Now()
			order.Status = "checkout_disputing"
			order.HandoffStatus = "checkout_disputed"
			order.SettlementStatus = "disputed"
			updates := map[string]any{
				"status":     "disputed",
				"updated_at": now,
			}
			if userID == order.RenterID {
				updates["renter_rejected_at"] = now
			}
			if err := tx.Model(&model.OrderCheckout{}).
				Where("id = ?", checkout.ID).
				Updates(updates).Error; err != nil {
				return err
			}
		} else {
			order.Status = "disputing"
		}
		recordType := "dispute_opened"
		recordContent := "用户发起订单申诉：" + req.Description
		if isCheckoutDispute {
			recordType = "checkout_dispute_opened"
			recordContent = "用户发起结账争议：" + req.Description
		}
		record := model.HandoffRecord{
			OrderID:    order.ID,
			FromUserID: userID,
			ToUserID:   targetID,
			Type:       recordType,
			Content:    recordContent,
		}
		if err := tx.Create(&record).Error; err != nil {
			return err
		}
		if err := tx.Save(&order).Error; err != nil {
			return err
		}
		disputeID := row.ID
		title := "订单进入申诉"
		content := "对方已发起申诉，请等待客服仲裁或补充沟通记录。"
		if isCheckoutDispute {
			title = "订单进入结账争议"
			content = "对方已发起结账争议，请等待客服仲裁或补充结账证据。"
		}
		if err := notification.Append(tx,
			notification.Entry{
				UserID:  targetID,
				Type:    "dispute",
				Title:   title,
				Content: content,
				BizType: "dispute",
				BizID:   &disputeID,
			},
			notification.Entry{
				UserID:  userID,
				Type:    "dispute",
				Title:   "申诉已提交",
				Content: "申诉已进入待处理状态，客服仲裁后会通知双方。",
				BizType: "dispute",
				BizID:   &disputeID,
			},
		); err != nil {
			return err
		}
		createdID = row.ID
		return nil
	})
	if err != nil {
		return nil, err
	}
	return r.FindForUser(ctx, userID, createdID)
}

func disputeType(input string, isCheckoutDispute bool) string {
	if isCheckoutDispute {
		return "checkout_dispute"
	}
	return input
}
