package repository

import (
	"context"

	"git.kirlllll.ru/volontery/backend/internal/database"
	"github.com/jackc/pgx/v5/pgtype"
)

// RequestRepository предоставляет методы для работы с заявками
type RequestRepository struct {
	queries *database.Queries
}

// NewRequestRepository создает новый RequestRepository
func NewRequestRepository(queries *database.Queries) *RequestRepository {
	return &RequestRepository{queries: queries}
}

// Create создает новую заявку
func (r *RequestRepository) Create(ctx context.Context, params database.CreateRequestParams) (*database.CreateRequestRow, error) {
	result, err := r.queries.CreateRequest(ctx, params)
	if err != nil {
		return nil, err
	}
	return &result, nil
}

// GetByID получает заявку по ID
func (r *RequestRepository) GetByID(ctx context.Context, id int64) (*database.GetRequestByIDRow, error) {
	result, err := r.queries.GetRequestByID(ctx, id)
	if err != nil {
		return nil, err
	}
	return &result, nil
}

// GetByRequester получает заявки пользователя
func (r *RequestRepository) GetByRequester(ctx context.Context, params database.GetRequestsByRequesterParams) ([]database.GetRequestsByRequesterRow, error) {
	return r.queries.GetRequestsByRequester(ctx, params)
}

// UpdateStatus обновляет статус заявки
func (r *RequestRepository) UpdateStatus(ctx context.Context, params database.UpdateRequestStatusParams) error {
	return r.queries.UpdateRequestStatus(ctx, params)
}

// Delete удаляет заявку (soft delete)
func (r *RequestRepository) Delete(ctx context.Context, params database.DeleteRequestParams) error {
	return r.queries.DeleteRequest(ctx, params)
}

// ListTypes получает список типов заявок
func (r *RequestRepository) ListTypes(ctx context.Context) ([]database.RequestType, error) {
	return r.queries.ListRequestTypes(ctx)
}

// FindNearby ищет заявки рядом с точкой
func (r *RequestRepository) FindNearby(ctx context.Context, params database.FindRequestsNearbyParams) ([]database.FindRequestsNearbyRow, error) {
	return r.queries.FindRequestsNearby(ctx, params)
}

// FindInBounds ищет заявки в прямоугольной области
func (r *RequestRepository) FindInBounds(ctx context.Context, params database.FindRequestsInBoundsParams) ([]database.FindRequestsInBoundsRow, error) {
	return r.queries.FindRequestsInBounds(ctx, params)
}

// CreateVolunteerResponse создает отклик волонтера
func (r *RequestRepository) CreateVolunteerResponse(ctx context.Context, params database.CreateVolunteerResponseParams) (*database.VolunteerResponse, error) {
	result, err := r.queries.CreateVolunteerResponse(ctx, params)
	if err != nil {
		return nil, err
	}
	return &result, nil
}

// GetResponsesByRequest получает отклики на заявку
func (r *RequestRepository) GetResponsesByRequest(ctx context.Context, requestID int64) ([]database.GetResponsesByRequestRow, error) {
	return r.queries.GetResponsesByRequest(ctx, requestID)
}

// GetPendingModerationRequests получает заявки на модерации
func (r *RequestRepository) GetPendingModerationRequests(ctx context.Context, limit, offset int32) ([]database.GetPendingModerationRequestsRow, error) {
	return r.queries.GetPendingModerationRequests(ctx, database.GetPendingModerationRequestsParams{
		Limit:  limit,
		Offset: offset,
	})
}

// ApproveRequest одобряет заявку
func (r *RequestRepository) ApproveRequest(ctx context.Context, params database.ApproveRequestParams) error {
	return r.queries.ApproveRequest(ctx, params)
}

// int64ToPgInt8 конвертирует int64 в pgtype.Int8
func int64ToPgInt8(i int64) pgtype.Int8 {
	if i == 0 {
		return pgtype.Int8{Valid: false}
	}
	return pgtype.Int8{Int64: i, Valid: true}
}

// RejectRequest отклоняет заявку
func (r *RequestRepository) RejectRequest(ctx context.Context, params database.RejectRequestParams) error {
	return r.queries.RejectRequest(ctx, params)
}

// GetModeratedRequests получает заявки, модерированные указанным модератором
func (r *RequestRepository) GetModeratedRequests(ctx context.Context, moderatorID int64, limit, offset int32) ([]database.GetModeratedRequestsRow, error) {
	return r.queries.GetModeratedRequests(ctx, database.GetModeratedRequestsParams{
		ModeratedBy: int64ToPgInt8(moderatorID),
		Limit:       limit,
		Offset:      offset,
	})
}

// AcceptVolunteerResponse вызывает хранимую процедуру для принятия отклика
func (r *RequestRepository) AcceptVolunteerResponse(ctx context.Context, responseID, requesterID int64) (*database.CallAcceptVolunteerResponseRow, error) {
	result, err := r.queries.CallAcceptVolunteerResponse(ctx, database.CallAcceptVolunteerResponseParams{
		PResponseID:  responseID,
		PRequesterID: requesterID,
	})
	if err != nil {
		return nil, err
	}
	return &result, nil
}

// CompleteRequestWithRating вызывает хранимую процедуру для завершения заявки с рейтингом
func (r *RequestRepository) CompleteRequestWithRating(ctx context.Context, requestID, requesterID int64, rating int32, comment *string) (*database.CallCompleteRequestWithRatingRow, error) {
	params := database.CallCompleteRequestWithRatingParams{
		PRequestID:   requestID,
		PRequesterID: requesterID,
		PRating:      rating,
	}

	if comment != nil {
		params.Comment = pgtype.Text{String: *comment, Valid: true}
	}

	result, err := r.queries.CallCompleteRequestWithRating(ctx, params)
	if err != nil {
		return nil, err
	}
	return &result, nil
}

// ModerateRequestProcedure вызывает хранимую процедуру для модерации заявки
func (r *RequestRepository) ModerateRequestProcedure(ctx context.Context, requestID, moderatorID int64, action string, comment *string) (*database.CallModerateRequestRow, error) {
	params := database.CallModerateRequestParams{
		PRequestID:   requestID,
		PModeratorID: moderatorID,
		PAction:      action,
	}

	if comment != nil {
		params.Comment = pgtype.Text{String: *comment, Valid: true}
	}

	result, err := r.queries.CallModerateRequest(ctx, params)
	if err != nil {
		return nil, err
	}
	return &result, nil
}
