package dispute

import (
	"context"
	"strconv"
	"strings"

	"hfb_sys/backend/internal/model"

	"gorm.io/gorm"
)

func (r *Repository) ListForUser(ctx context.Context, userID uint64, page, pageSize int) (*PaginatedResult, error) {
	db := r.db.WithContext(ctx)
	conditions := db.Model(&model.Dispute{}).Where("initiator_id = ? OR target_user_id = ?", userID, userID)
	var total int64
	if err := conditions.Count(&total).Error; err != nil {
		return nil, err
	}
	offset := (page - 1) * pageSize
	var rows []disputeRow
	err := r.baseQuery(ctx).
		Where("d.initiator_id = ? OR d.target_user_id = ?", userID, userID).
		Order("d.id DESC").
		Offset(offset).Limit(pageSize).
		Scan(&rows).Error
	if err != nil {
		return nil, err
	}
	return &PaginatedResult{Items: toDTOs(rows), Total: total, Page: page, PageSize: pageSize}, nil
}

func (r *Repository) FindForUser(ctx context.Context, userID uint64, id uint64) (*DisputeDTO, error) {
	var row disputeRow
	if err := r.baseQuery(ctx).
		Where("d.id = ? AND (d.initiator_id = ? OR d.target_user_id = ?)", id, userID, userID).
		First(&row).Error; err != nil {
		return nil, err
	}
	dto := row.toDTO()
	return &dto, nil
}

func (r *Repository) ListAdmin(ctx context.Context, query AdminListQuery) (*PaginatedResult, error) {
	var total int64
	countDB := applyAdminListFilters(r.adminFilterQuery(ctx), query)
	if err := countDB.Count(&total).Error; err != nil {
		return nil, err
	}
	page := query.Page
	pageSize := query.PageSize
	if page < 1 {
		page = 1
	}
	if pageSize < 1 {
		pageSize = 20
	}
	offset := (page - 1) * pageSize
	var rows []disputeRow
	err := applyAdminListFilters(r.baseQuery(ctx), query).
		Order("d.id DESC").
		Offset(offset).
		Limit(pageSize).
		Scan(&rows).Error
	if err != nil {
		return nil, err
	}
	return &PaginatedResult{Items: toDTOs(rows), Total: total, Page: page, PageSize: pageSize}, nil
}

func (r *Repository) baseQuery(ctx context.Context) *gorm.DB {
	return r.adminFilterQuery(ctx).
		Select(`d.*, o.order_no, o.status AS order_status, o.handoff_status, o.settlement_status,
			o.owner_id, o.renter_id, owner.phone AS owner_phone, renter.phone AS renter_phone,
			l.listing_no, a.title`)
}

func (r *Repository) adminFilterQuery(ctx context.Context) *gorm.DB {
	return r.db.WithContext(ctx).Table("disputes AS d").
		Joins("JOIN rental_orders AS o ON o.id = d.order_id").
		Joins("JOIN rental_listings AS l ON l.id = o.listing_id").
		Joins("JOIN game_accounts AS a ON a.id = o.account_id").
		Joins("JOIN users AS owner ON owner.id = o.owner_id").
		Joins("JOIN users AS renter ON renter.id = o.renter_id")
}

func applyAdminListFilters(db *gorm.DB, query AdminListQuery) *gorm.DB {
	if query.Status != "" {
		db = db.Where("d.status = ?", query.Status)
	}
	if query.Type != "" {
		db = db.Where("d.type = ?", query.Type)
	}
	if keyword := strings.TrimSpace(query.Keyword); keyword != "" {
		like := "%" + keyword + "%"
		if id, err := strconv.ParseUint(keyword, 10, 64); err == nil {
			db = db.Where(
				`(o.order_no LIKE ? OR l.listing_no LIKE ? OR a.title LIKE ? OR owner.phone LIKE ? OR renter.phone LIKE ? OR d.id = ? OR d.order_id = ? OR o.listing_id = ? OR o.owner_id = ? OR o.renter_id = ?)`,
				like,
				like,
				like,
				like,
				like,
				id,
				id,
				id,
				id,
				id,
			)
		} else {
			db = db.Where(
				`(o.order_no LIKE ? OR l.listing_no LIKE ? OR a.title LIKE ? OR owner.phone LIKE ? OR renter.phone LIKE ?)`,
				like,
				like,
				like,
				like,
				like,
			)
		}
	}
	return db
}
