package service

import (
	"baron-sso-backend/internal/domain"
	"context"
	"errors"

	"gorm.io/gorm"
)

type DeveloperService struct {
	db *gorm.DB
}

func NewDeveloperService(db *gorm.DB) *DeveloperService {
	return &DeveloperService{db: db}
}

func (s *DeveloperService) RequestAccess(ctx context.Context, req domain.DeveloperRequest) error {
	// Check if there is already a pending request
	var existing domain.DeveloperRequest
	err := s.db.WithContext(ctx).Where("user_id = ? AND tenant_id = ? AND status = ?", req.UserID, req.TenantID, domain.DeveloperRequestStatusPending).First(&existing).Error
	if err == nil {
		return nil
	}
	if !errors.Is(err, gorm.ErrRecordNotFound) {
		return err
	}

	return s.db.WithContext(ctx).Create(&req).Error
}

func (s *DeveloperService) GetRequestStatus(ctx context.Context, userID, tenantID string) (*domain.DeveloperRequest, error) {
	var req domain.DeveloperRequest
	err := s.db.WithContext(ctx).Where("user_id = ? AND tenant_id = ?", userID, tenantID).Order("created_at DESC").First(&req).Error
	if err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return nil, nil
		}
		return nil, err
	}
	return &req, nil
}

func (s *DeveloperService) GetRequestByID(ctx context.Context, id uint) (*domain.DeveloperRequest, error) {
	var req domain.DeveloperRequest
	err := s.db.WithContext(ctx).First(&req, id).Error
	if err != nil {
		return nil, err
	}
	return &req, nil
}

func (s *DeveloperService) ListRequests(ctx context.Context, userID, status string) ([]domain.DeveloperRequest, error) {
	var requests []domain.DeveloperRequest
	query := s.db.WithContext(ctx)
	if userID != "" {
		query = query.Where("user_id = ?", userID)
	}
	if status != "" {
		query = query.Where("status = ?", status)
	}
	err := query.Order("created_at DESC").Find(&requests).Error
	return requests, err
}

func (s *DeveloperService) ApproveRequest(ctx context.Context, id uint, adminNotes string) error {
	return s.db.WithContext(ctx).Model(&domain.DeveloperRequest{}).Where("id = ?", id).Updates(map[string]any{
		"status":      domain.DeveloperRequestStatusApproved,
		"admin_notes": adminNotes,
	}).Error
}

func (s *DeveloperService) RejectRequest(ctx context.Context, id uint, adminNotes string) error {
	return s.db.WithContext(ctx).Model(&domain.DeveloperRequest{}).Where("id = ?", id).Updates(map[string]any{
		"status":      domain.DeveloperRequestStatusRejected,
		"admin_notes": adminNotes,
	}).Error
}

func (s *DeveloperService) CancelApprovedRequest(ctx context.Context, id uint, adminNotes string) error {
	return s.db.WithContext(ctx).Model(&domain.DeveloperRequest{}).Where("id = ?", id).Updates(map[string]any{
		"status":      domain.DeveloperRequestStatusCancelled,
		"admin_notes": adminNotes,
	}).Error
}
