package order

import (
	"context"
	"time"

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

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

func (r *Repository) SubmitCheckout(ctx context.Context, userID uint64, orderID uint64, req SubmitCheckoutRequest) (*HandoffRecordDTO, error) {
	var recordID 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 {
			return ErrPermissionDenied
		}
		if (order.Status != orderStatusRenting && order.Status != orderStatusOverdue) || (order.HandoffStatus != handoffStatusReceived && order.HandoffStatus != handoffStatusReturnOverdue) {
			return ErrCheckoutCannotSubmit
		}
		hasOpen, err := hasOpenCheckout(tx, order.ID)
		if err != nil {
			return err
		}
		if hasOpen {
			return ErrCheckoutCannotSubmit
		}
		record := model.HandoffRecord{
			OrderID:    order.ID,
			FromUserID: order.RenterID,
			ToUserID:   order.OwnerID,
			Type:       "renter_checkout",
			Content:    req.Content,
		}
		if err := tx.Create(&record).Error; err != nil {
			return err
		}
		checkout, err := buildCheckout(order, order.RenterID, checkoutStatusSubmitted, req.Content, req.EvidenceURLS, req.ConsumableAmountCent, req.CoinConsumedM, req.OtherAmountCent, 0, false)
		if err != nil {
			return err
		}
		if err := tx.Create(&checkout).Error; err != nil {
			return err
		}
		order.Status = orderStatusPendingCheckoutConfirm
		order.HandoffStatus = handoffStatusPendingOwnerCheckout
		order.SettlementStatus = settlementStatusPending
		now := time.Now()
		order.HandoffStartedAt = &now
		orderID := order.ID
		if err := notification.Append(tx, notification.Entry{
			UserID:  order.OwnerID,
			Type:    "checkout",
			Title:   "租客已发起结账",
			Content: "请检查账号状态和消耗明细，确认无误后完成结算。",
			BizType: "order",
			BizID:   &orderID,
		}); err != nil {
			return err
		}
		if err := tx.Save(&order).Error; err != nil {
			return err
		}
		recordID = record.ID
		return nil
	})
	if err != nil {
		return nil, err
	}
	return r.findHandoffRecord(ctx, recordID)
}

func (r *Repository) ConfirmReturn(ctx context.Context, userID uint64, orderID uint64) error {
	return r.ConfirmCheckout(ctx, userID, orderID)
}

func (r *Repository) ConfirmCheckout(ctx context.Context, userID uint64, orderID uint64) error {
	var refund *refundAction
	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.OwnerID != userID {
			return ErrPermissionDenied
		}
		if order.Status != orderStatusPendingCheckoutConfirm || order.HandoffStatus != handoffStatusPendingOwnerCheckout {
			return ErrCheckoutCannotConfirm
		}
		var checkout model.OrderCheckout
		if err := tx.Clauses(clause.Locking{Strength: "UPDATE"}).
			Where("order_id = ? AND status = ?", order.ID, checkoutStatusSubmitted).
			Order("id DESC").
			First(&checkout).Error; err != nil {
			return err
		}
		now := time.Now()
		if err := tx.Model(&model.HandoffRecord{}).
			Where("order_id = ? AND type = ?", order.ID, "renter_checkout").
			Update("confirmed_by_owner_at", now).Error; err != nil {
			return err
		}
		checkout.Status = checkoutStatusAccepted
		checkout.OwnerAdjustedAt = &now
		action, err := r.finalizeCheckout(tx, &order, &checkout, "号主已确认结账，订单完成。")
		refund = action
		return err
	})
	if err != nil {
		return err
	}
	r.startRefundBestEffort(ctx, refund)
	return nil
}

func (r *Repository) CounterCheckout(ctx context.Context, userID uint64, orderID uint64, req CounterCheckoutRequest) (*CheckoutDTO, error) {
	var checkoutID 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.OwnerID != userID {
			return ErrPermissionDenied
		}
		if order.Status != orderStatusPendingCheckoutConfirm || order.HandoffStatus != handoffStatusPendingOwnerCheckout {
			return ErrCheckoutCannotCounter
		}
		var checkout model.OrderCheckout
		if err := tx.Clauses(clause.Locking{Strength: "UPDATE"}).
			Where("order_id = ? AND status = ?", order.ID, checkoutStatusSubmitted).
			Order("id DESC").
			First(&checkout).Error; err != nil {
			return err
		}
		next, err := buildCheckout(order, checkout.InitiatedBy, checkoutStatusCountered, checkout.Content, req.EvidenceURLS, req.ConsumableAmountCent, req.CoinConsumedM, req.OtherAmountCent, req.DepositDeductAmountCent, true)
		if err != nil {
			return err
		}
		now := time.Now()
		checkout.Status = checkoutStatusCountered
		checkout.RentAmountCent = next.RentAmountCent
		checkout.OwnerRentAmountCent = next.OwnerRentAmountCent
		checkout.PlatformFeeCent = next.PlatformFeeCent
		checkout.DepositAmountCent = next.DepositAmountCent
		checkout.ConsumableAmountCent = next.ConsumableAmountCent
		checkout.CoinConsumedM = next.CoinConsumedM
		checkout.OtherAmountCent = next.OtherAmountCent
		checkout.DepositDeductAmountCent = next.DepositDeductAmountCent
		checkout.RenterRefundAmountCent = next.RenterRefundAmountCent
		checkout.OwnerIncomeAmountCent = next.OwnerIncomeAmountCent
		checkout.OwnerAdjustmentReason = req.Reason
		checkout.OwnerAdjustedAt = &now
		checkout.EvidenceURLS = next.EvidenceURLS
		order.Status = orderStatusPendingCheckoutAccept
		order.HandoffStatus = handoffStatusPendingRenterCheckout
		order.SettlementStatus = settlementStatusPending
		orderID := order.ID
		if err := notification.Append(tx, notification.Entry{
			UserID:  order.RenterID,
			Type:    "checkout",
			Title:   "号主已修改结账金额",
			Content: "请核对号主修正的消耗和结算金额。同意后订单完成；不同意可发起争议。",
			BizType: "order",
			BizID:   &orderID,
		}); err != nil {
			return err
		}
		if err := tx.Save(&order).Error; err != nil {
			return err
		}
		if err := tx.Save(&checkout).Error; err != nil {
			return err
		}
		checkoutID = checkout.ID
		return nil
	})
	if err != nil {
		return nil, err
	}
	checkout, err := r.findCheckout(ctx, checkoutID)
	if err != nil {
		return nil, err
	}
	dto := toCheckoutDTOForUser(*checkout, userID, model.RentalOrder{
		OwnerID:             userID,
		RentAmountCent:      checkout.RentAmountCent,
		OwnerRentAmountCent: checkout.OwnerRentAmountCent,
		DepositAmountCent:   checkout.DepositAmountCent,
	})
	return &dto, nil
}

func (r *Repository) AcceptCheckout(ctx context.Context, userID uint64, orderID uint64) error {
	var refund *refundAction
	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 {
			return ErrPermissionDenied
		}
		if order.Status != orderStatusPendingCheckoutAccept || order.HandoffStatus != handoffStatusPendingRenterCheckout {
			return ErrCheckoutCannotConfirm
		}
		var checkout model.OrderCheckout
		if err := tx.Clauses(clause.Locking{Strength: "UPDATE"}).
			Where("order_id = ? AND status = ?", order.ID, checkoutStatusCountered).
			Order("id DESC").
			First(&checkout).Error; err != nil {
			return err
		}
		now := time.Now()
		checkout.Status = checkoutStatusAccepted
		checkout.RenterConfirmedAt = &now
		action, err := r.finalizeCheckout(tx, &order, &checkout, "租客已确认修正结账，订单完成。")
		refund = action
		return err
	})
	if err != nil {
		return err
	}
	r.startRefundBestEffort(ctx, refund)
	return nil
}
