package repositories_astrologer

import (
	config "astrology-api/configs"
	"astrology-api/dto_astrologer"
	dto "astrology-api/dto_astrologer"
	models "astrology-api/models/astrologermodel"
	"errors"

	"fmt"

	"time"

	"gorm.io/gorm"
)

type astrologerRepository struct {
	db *gorm.DB
}

func NewAstrologerRepository() AstrologerRepository {
	fmt.Println("config.DB =", config.DB)
	return &astrologerRepository{
		db: config.DB,
	}
}

func (r *astrologerRepository) GetUserTableByID(userID uint) (*models.User, error) {

	fmt.Println("Searching user id =", userID)

	var user models.User

	err := r.db.
		Debug().
		Where("id = ?", userID).
		First(&user).Error

	if err != nil {
		fmt.Println("User not found:", err)
		return nil, err
	}

	fmt.Printf("User Found: %+v\n", user)

	return &user, nil
}

func (r *astrologerRepository) GetByUserID(userID uint) (*models.Astrologer, error) {

	var astrologer models.Astrologer

	err := r.db.
		Where("userId = ?", userID).
		First(&astrologer).Error

	if err != nil {
		return nil, err
	}

	return &astrologer, nil
}

func (r *astrologerRepository) GetByID(id uint) (*models.Astrologer, error) {

	var astrologer models.Astrologer

	err := r.db.First(&astrologer, id).Error

	if err != nil {
		return nil, err
	}

	return &astrologer, nil
}

func (r *astrologerRepository) Create(astrologer *models.Astrologer) error {

	return r.db.Create(astrologer).Error
}

func (r *astrologerRepository) Update(astrologer *models.Astrologer) error {

	return r.db.Save(astrologer).Error
}

func (r *astrologerRepository) UpdateUser(user *models.User) error {
	return r.db.Save(user).Error
}

func (r *astrologerRepository) SaveLanguages(astrologerID uint, languageIDs []uint) error {

	tx := r.db.Begin()

	if err := tx.Where("astrologer_id=?", astrologerID).
		Delete(&models.AstrologerLanguage{}).Error; err != nil {

		tx.Rollback()
		return err
	}

	for _, id := range languageIDs {

		language := models.AstrologerLanguage{
			AstrologerID: astrologerID,
			LanguageID:   id,
		}

		if err := tx.Create(&language).Error; err != nil {

			tx.Rollback()
			return err
		}
	}

	return tx.Commit().Error
}

func (r *astrologerRepository) SaveSkills(skills []models.AstrologerSkill) error {

	tx := r.db.Begin()

	if len(skills) == 0 {

		return nil
	}

	astrologerID := skills[0].AstrologerID

	tx.Where("astrologer_id=?", astrologerID).
		Delete(&models.AstrologerSkill{})

	for _, skill := range skills {

		if err := tx.Create(&skill).Error; err != nil {

			tx.Rollback()

			return err
		}
	}

	return tx.Commit().Error
}

func (r *astrologerRepository) SaveEducation(education *models.AstrologerEducation) error {

	return r.db.Create(education).Error

}

func (r *astrologerRepository) UpdateEducation(education *models.AstrologerEducation) error {

	return r.db.Save(education).Error

}

func (r *astrologerRepository) SaveProfessional(professional *models.AstrologerProfessional) error {

	return r.db.Create(professional).Error

}

func (r *astrologerRepository) SaveExperience(exp *models.AstrologerExperience) error {

	return r.db.Create(exp).Error

}

func (r *astrologerRepository) SaveBankAccount(bank *models.AstrologerBank,
) error {

	return r.db.Save(bank).Error

}

func (r *astrologerRepository) SaveDocument(document *models.AstrologerDocument) error {

	return r.db.
		Model(&models.AstrologerDocument{}).
		Create(document).Error
}

func (r *astrologerRepository) UpdateProfileProgress(progress *models.AstrologerProfileProgress) error {

	var existing models.AstrologerProfileProgress

	err := r.db.
		Where("astrologer_id = ?", progress.AstrologerID).
		First(&existing).Error

	if err == nil {

		existing.UserID = progress.UserID
		existing.CurrentStep = progress.CurrentStep
		existing.CompletionPercentage = progress.CompletionPercentage
		existing.ProfileCompleted = progress.ProfileCompleted
		existing.Submitted = progress.Submitted
		existing.AdminStatus = progress.AdminStatus
		existing.ProfileCompleted = progress.ProfileCompleted

		return r.db.Save(&existing).Error
	}

	if errors.Is(err, gorm.ErrRecordNotFound) {

		return r.db.Create(progress).Error
	}

	return err
}

func (r *astrologerRepository) SaveProgress(tx *gorm.DB, progress *models.AstrologerProfileProgress) error {
	return tx.Create(progress).Error
}

func (r *astrologerRepository) SubmitProfile(astrologerID uint) error {

	return r.db.Model(&models.Astrologer{}).
		Where("id=?", astrologerID).
		Updates(map[string]interface{}{
			"profile_status":        "SUBMITTED",
			"is_profile_completed":  true,
			"completion_percentage": 100,
		}).Error
}

func (r *astrologerRepository) CreateVerificationLog(tx *gorm.DB, log *models.AstrologerVerificationLog) error {

	return tx.Create(log).Error
}

func (r *astrologerRepository) CreateInterview(interview *models.AstrologerInterview) error {

	return config.DB.Create(interview).Error
}

func (r *astrologerRepository) GetInterviewByUserID(userID uint) (*models.AstrologerInterview, error) {

	var interview models.AstrologerInterview

	err := config.DB.
		Where("user_id = ?", userID).
		Order("round_no ASC").
		First(&interview).Error

	if err != nil {
		return nil, err
	}

	return &interview, nil
}

func (r *astrologerRepository) GetLanguagesByAstrologerID(
	astrologerID uint,
) ([]string, error) {

	var languages []string

	err := r.db.
		Table("astrologer_languages al").
		Select("l.languageName").
		Joins("JOIN languages l ON l.id = al.language_id").
		Where("al.astrologer_id = ?", astrologerID).
		Pluck("l.languageName", &languages).Error

	return languages, err
}

func (r *astrologerRepository) GetSkillsByAstrologerID(
	astrologerID uint,
) ([]string, error) {

	var skills []string

	err := r.db.
		Table("astrologer_skills ast").
		Select("s.name").
		Joins("JOIN skills s ON s.id = ast.skill_id").
		Where("ast.astrologer_id = ?", astrologerID).
		Pluck("s.name", &skills).Error

	return skills, err
}

func (r *astrologerRepository) GetProfileDetails(astrologerID uint) (*models.Astrologer, error) {

	var astrologer models.Astrologer

	err := r.db.
		Preload("Languages").
		Preload("Skills").
		Preload("Educations").
		Preload("Professionals").
		Preload("Experiences").
		Preload("BankAccounts").
		Preload("Documents").
		Preload("Progress").
		Preload("VerificationLogs").
		First(&astrologer, astrologerID).Error

	if err != nil {
		return nil, err
	}

	return &astrologer, nil
}

func (r *astrologerRepository) GetProfileProgress(userID uint) (*models.Astrologer, error) {

	var astrologer models.Astrologer

	err := r.db.
		Preload("Progress").
		Where("userid = ?", userID).
		First(&astrologer).Error

	if err != nil {
		return nil, err
	}

	return &astrologer, nil
}

func (r *astrologerRepository) ChangeStatus(userID uint, status string) error {

	return r.db.Model(&models.Astrologer{}).
		Where("user_id = ?", userID).
		Update("status", status).Error
}

func (r *astrologerRepository) DeleteAccount(userID uint) error {

	tx := r.db.Begin()

	if tx.Error != nil {
		return tx.Error
	}

	if err := tx.Model(&models.User{}).
		Where("id = ?", userID).
		Updates(map[string]interface{}{
			"deleted_at": time.Now(),
			"is_active":  false,
		}).Error; err != nil {

		tx.Rollback()
		return err
	}

	if err := tx.Model(&models.Astrologer{}).
		Where("user_id = ?", userID).
		Updates(map[string]interface{}{
			"deleted_at": time.Now(),
			"status":     "DELETED",
		}).Error; err != nil {

		tx.Rollback()
		return err
	}

	return tx.Commit().Error
}

// GetMasterLanguages lists the languages, flagging the ones this astrologer has
// already picked.
//
// A missing astrologer row is normal — the row does not exist until profile step
// 1 is saved, and the app opens this list to *choose* languages, before that.
// Returning the raw record-not-found made the master list 400 for exactly the
// account that needs it. GetMasterSkills already tolerates it the same way.
func (r *astrologerRepository) GetMasterLanguages(userID uint) ([]dto_astrologer.LanguageMasterResponse, error) {

	var astrologer models.Astrologer

	err := r.db.
		Where("userId = ?", userID).
		First(&astrologer).Error

	if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
		return nil, err
	}

	var list []dto.LanguageMasterResponse

	err = r.db.Table("languages l").
		Select(`l.id,
			l.languageName as language_name,
			l.languageCode as language_code,
			l.language_sign,
			CASE
				WHEN al.language_id IS NULL THEN false
				ELSE true
			END as is_selected
		`).
		Joins(`
			LEFT JOIN astrologer_languages al
			ON al.language_id=l.id
			AND al.astrologer_id=?
		`, astrologer.ID).
		Order("l.languageName ASC").
		Scan(&list).Error

	if err != nil {
		return nil, err
	}

	return list, nil
}

func (r *astrologerRepository) GetMasterSkills(userID uint) ([]dto_astrologer.SkillMasterResponse, error) {

	var astrologer models.Astrologer

	err := r.db.
		Where("userid = ?", userID).
		First(&astrologer).Error

	var astrologerID uint = 0

	if err == nil {
		astrologerID = astrologer.ID
	}

	// Not nil: an empty master list has to serialise as [] rather than the
	// null a nil slice produces, which reads to the app as a failed fetch.
	skills := []dto_astrologer.SkillMasterResponse{}

	err = r.db.Table("skills s").
		Select(`
			s.id,
			s.name as skill_name,
			CASE
				WHEN ast.skill_id IS NULL THEN false
				ELSE true
			END as is_selected
		`).
		Joins(`
			LEFT JOIN astrologer_skills ast
			ON ast.skill_id=s.id
			AND ast.astrologer_id=?
		`, astrologerID).
		// isActive/isDelete are the flags this schema actually maintains, the
		// same pair every other table here uses. skills.status is a legacy
		// column left NULL by whatever inserts skills now, so filtering on it
		// hid every newly added skill — and hid all of them, returning null,
		// wherever no row was ever given a status. It also let a soft-deleted
		// or deactivated skill through, since those rows still carry status=1.
		Where("s.isActive = ?", true).
		Where("s.isDelete = ?", false).
		Order("s.name ASC").
		Scan(&skills).Error

	if err != nil {
		return nil, err
	}

	return skills, nil
}

func (r *astrologerRepository) GetMasterDocumentTypes() ([]models.MasterDocumentType, error) {

	var documents []models.MasterDocumentType

	err := config.DB.
		Where("is_active = ?", true).
		Order("type ASC,id ASC").
		Find(&documents).Error

	if err != nil {
		return nil, err
	}

	return documents, nil
}

func (r *astrologerRepository) GetMasterDocumentType(
	masterType string,
	documentType string,
) (*models.MasterDocumentType, error) {

	var master models.MasterDocumentType

	err := r.db.
		Model(&models.MasterDocumentType{}).
		Where("type = ?", masterType).
		Where("code = ?", documentType).
		Where("is_active = ?", true).
		First(&master).Error

	if err != nil {
		return nil, err
	}

	return &master, nil
}

func (r *astrologerRepository) GetDocumentByAstrologerAndType(
	astrologerID uint,
	documentType string,
) (*models.AstrologerDocument, error) {

	var document models.AstrologerDocument

	err := r.db.
		Model(&models.AstrologerDocument{}).
		Where("astrologer_id = ?", astrologerID).
		Where("document_type = ?", documentType).
		First(&document).Error

	if err != nil {
		return nil, err
	}

	return &document, nil
}

func (r *astrologerRepository) UpdateDocument(
	document *models.AstrologerDocument,
) error {

	return r.db.Save(document).Error
}

// GetUploadedDocumentTypes lists the document_type codes the astrologer has an
// active row for. It backs the KYC completeness check on step 9, which asks
// "is this code on file at all", not "which row is it".
func (r *astrologerRepository) GetUploadedDocumentTypes(
	astrologerID uint,
) ([]string, error) {

	var types []string

	err := r.db.
		Model(&models.AstrologerDocument{}).
		Where("astrologer_id = ?", astrologerID).
		Where("is_active = ?", true).
		Where("document_type <> ''").
		Distinct().
		Pluck("document_type", &types).Error

	if err != nil {
		return nil, err
	}

	return types, nil
}

// UpdateBankAccountRow saves a bank row outside a caller's transaction, so the
// document upload can mirror a CHEQUE/PASSBOOK file path onto
// astrologer_bank_accounts. UpdateBankAccount is the transactional form.
func (r *astrologerRepository) UpdateBankAccountRow(
	bank *models.AstrologerBankAccount,
) error {

	return r.db.Save(bank).Error
}

func (r *astrologerRepository) ValidateDocumentType(
	masterType string,
	documentType string,
) error {

	var count int64

	err := r.db.
		Model(&models.MasterDocumentType{}).
		Where("type = ?", masterType).
		Where("code = ?", documentType).
		Where("is_active = ?", true).
		Count(&count).Error

	if err != nil {
		return err
	}

	if count == 0 {
		return errors.New("invalid master type or document type")
	}

	return nil
}

func (r *astrologerRepository) DeleteLanguages(astrologerID uint) error {

	return config.DB.
		Where("astrologer_id=?", astrologerID).
		Delete(&models.AstrologerLanguage{}).Error
}

func (r *astrologerRepository) CreateLanguage(
	language *models.AstrologerLanguage,
) error {

	return config.DB.Create(language).Error
}

// CreateLanguageTx inserts on the caller's transaction. See CreateSkillTx.
func (r *astrologerRepository) CreateLanguageTx(
	tx *gorm.DB,
	language *models.AstrologerLanguage,
) error {

	return tx.Create(language).Error
}

func (r *astrologerRepository) DeleteSkills(astrologerID uint) error {

	return config.DB.
		Where("astrologer_id=?", astrologerID).
		Delete(&models.AstrologerSkill{}).Error
}

func (r *astrologerRepository) CreateSkill(
	language *models.AstrologerSkill,
) error {

	return config.DB.Create(language).Error
}

// CreateSkillTx inserts on the caller's transaction.
//
// UpdateSkills deletes the astrologer's rows on its transaction and then
// re-inserted them through CreateSkill, which runs on the base pool — a second
// connection, blocking on the row locks the uncommitted DELETE still holds.
// Every call sat there until InnoDB's lock_wait_timeout fired and came back
// "Error 1205: Lock wait timeout exceeded", so the endpoint never worked.
//
// Sharing the transaction also makes the delete-then-insert atomic: on the base
// pool the inserts committed immediately while a later failure rolled the
// delete back, leaving the rows duplicated.
func (r *astrologerRepository) CreateSkillTx(
	tx *gorm.DB,
	skill *models.AstrologerSkill,
) error {

	return tx.Create(skill).Error
}

func (r *astrologerRepository) DeleteEducations(astrologerID uint) error {

	return config.DB.
		Where("astrologer_id = ?", astrologerID).
		Delete(&models.AstrologerEducation{}).Error
}

func (r *astrologerRepository) CreateEducation(
	education *models.AstrologerEducation,
) error {

	return config.DB.Create(education).Error
}

func (r *astrologerRepository) DeleteProfessionalByAstrologerID(
	tx *gorm.DB,
	astrologerID uint,
) error {

	return tx.
		Where("astrologer_id = ?", astrologerID).
		Delete(&models.AstrologerProfessional{}).Error
}

func (r *astrologerRepository) CreateProfessional(
	tx *gorm.DB,
	professional *models.AstrologerProfessional,
) error {

	return tx.Create(professional).Error
}

func (r *astrologerRepository) DeleteExperienceByAstrologerID(
	tx *gorm.DB,
	astrologerID uint,
) error {

	return tx.
		Where("astrologer_id = ?", astrologerID).
		Delete(&models.AstrologerExperience{}).Error
}

func (r *astrologerRepository) CreateExperience(
	tx *gorm.DB,
	exp *models.AstrologerExperience,
) error {

	fmt.Printf("Saving to DB : %+v\n", exp)

	return tx.Create(exp).Error
}

func (r *astrologerRepository) DeleteBankAccountByAstrologerID(
	tx *gorm.DB,
	astrologerID uint,
) error {

	return tx.
		Where("astrologer_id = ?", astrologerID).
		Delete(&models.AstrologerBankAccount{}).Error
}

func (r *astrologerRepository) CreateBankAccount(
	tx *gorm.DB,
	bank *models.AstrologerBankAccount,
) error {

	return tx.Create(bank).Error
}

func (r *astrologerRepository) GetDeviceTypes() ([]models.DeviceType, error) {

	var data []models.DeviceType

	err := config.DB.
		Where("is_active=?", true).
		Order("id ASC").
		Find(&data).Error

	return data, err
}

func (r *astrologerRepository) GetWorkingHours() ([]models.WorkingHourMaster, error) {

	var data []models.WorkingHourMaster

	err := config.DB.
		Where("is_active=?", true).
		Order("hours ASC").
		Find(&data).Error

	return data, err
}

func (r *astrologerRepository) GetAvailabilityByAstrologerID(
	astrologerID uint,
) ([]models.AstrologerAvailability, error) {

	var list []models.AstrologerAvailability

	err := config.DB.
		Where("astrologer_id=? AND isDelete=?", astrologerID, false).
		Order("id ASC").
		Find(&list).Error

	return list, err
}

func (r *astrologerRepository) CreateAvailability(
	tx *gorm.DB,
	availability *models.AstrologerAvailability,
) error {

	return tx.Create(availability).Error
}

func (r *astrologerRepository) DeleteAvailabilityByAstrologerID(
	tx *gorm.DB,
	astrologerID uint,
) error {

	return tx.
		Where("astrologer_id = ?", astrologerID).
		Delete(&models.AstrologerAvailability{}).Error

}

func (r *astrologerRepository) GetSocialLinksByAstrologerID(astrologerID uint) (*models.AstrologerSocialLink, error) {

	var social models.AstrologerSocialLink

	err := config.DB.
		Where("astrologer_id=?", astrologerID).
		First(&social).Error

	if err != nil {

		return nil, err

	}

	return &social, nil

}

func (r *astrologerRepository) CreateSocialLinks(
	tx *gorm.DB,
	social *models.AstrologerSocialLink,
) error {

	return tx.Create(social).Error

}

func (r *astrologerRepository) UpdateSocialLinks(
	tx *gorm.DB,
	social *models.AstrologerSocialLink,
) error {

	return tx.Save(social).Error

}

func (r *astrologerRepository) UpdateAstrologer(tx *gorm.DB, astrologer *models.Astrologer) error {

	stmt := tx.Session(&gorm.Session{DryRun: true}).Save(astrologer).Statement

	fmt.Println("===================================")
	fmt.Println(stmt.SQL.String())
	fmt.Printf("%#v\n", stmt.Vars)
	fmt.Println("===================================")

	return tx.Save(astrologer).Error
}

func (r *astrologerRepository) UpdateAstrologerAvailablity(
	tx *gorm.DB,
	astrologer *models.Astrologer,
) error {

	return tx.Model(&models.Astrologer{}).
		Where("id = ?", astrologer.ID).
		Updates(map[string]interface{}{
			"deviceType":                 astrologer.DeviceType,
			"dailyContribution":          astrologer.DailyHours,
			"chatRate":                   astrologer.ChatRate,
			"audioCallRate":              astrologer.AudioCallRate,
			"videoCallRate":              astrologer.VideoCallRate,
			"charge":                     astrologer.Charge,
			"isWorkingOnAnotherPlatform": astrologer.WorkingPlatform,
			"nameofplateform":            astrologer.WorkingPlatformName,
			"freeChat":                   astrologer.FreeChat,
			"freeCall":                   astrologer.FreeCall,
			"chatStatus":                 astrologer.ChatStatus,
			"chatWaitTime":               astrologer.ChatWaitTime,
			"callStatus":                 astrologer.CallStatus,
			"callWaitTime":               astrologer.CallWaitTime,
			"instaProfileLink":           astrologer.InstaProfileLink,
			"facebookProfileLink":        astrologer.FacebookProfileLink,
			"youtubeChannelLink":         astrologer.YoutubeProfileLink,
			"linkedInProfileLink":        astrologer.LinkedinProfileLink,
			"websiteProfileLink":         astrologer.WebsiteProfileLink,
			"current_step":               astrologer.CurrentStep,
			"completion_percentage":      astrologer.CompletionPercentage,
			"profile_status":             astrologer.ProfileStatus,
			"is_profile_completed":       astrologer.IsProfileCompleted,
		}).Error
}

func (r *astrologerRepository) GetAvailableScheduleByAstrologerID(
	astrologerID uint,
) ([]models.AstrologerAvailability, error) {

	var schedules []models.AstrologerAvailability

	err := config.DB.
		Where("astrologer_id = ? AND isDelete = ?", astrologerID, false).
		Order("FIELD(day,'Monday','Tuesday','Wednesday','Thursday','Friday','Saturday','Sunday')").
		Find(&schedules).Error

	if err != nil {
		return nil, err
	}

	return schedules, nil
}

func (r *astrologerRepository) GetProfileCompletionByAstrologerID(astrologerID uint) (*models.AstrologerProfileCompletion, error) {

	var completion models.AstrologerProfileCompletion

	err := config.DB.
		Where("astrologer_id = ?", astrologerID).
		First(&completion).Error

	if err != nil {
		return nil, err
	}

	return &completion, nil
}

func (r *astrologerRepository) CreateProfileCompletion(completion *models.AstrologerProfileCompletion) error {
	return config.DB.Create(completion).Error
}

func (r *astrologerRepository) UpdateProfileCompletion(completion *models.AstrologerProfileCompletion) error {
	return config.DB.Save(completion).Error
}

func (r *astrologerRepository) GetProgressByAstrologerID(astrologerID uint) (*models.AstrologerProgress, error) {

	var progress models.AstrologerProgress

	err := config.DB.
		Where("astrologer_id = ?", astrologerID).
		First(&progress).Error

	if err != nil {
		return nil, err
	}

	return &progress, nil
}

func (r *astrologerRepository) CreateProgress(progress *models.AstrologerProgress) error {

	return config.DB.Create(progress).Error
}

func (r *astrologerRepository) UpdateProgress(progress *models.AstrologerProgress) error {
	return config.DB.Save(progress).Error
}

func (r *astrologerRepository) GetProfileProgressByAstrologerID(astrologerID uint) (*models.AstrologerProfileProgress, error) {

	var progress models.AstrologerProfileProgress

	err := config.DB.
		Where("astrologer_id = ?", astrologerID).
		First(&progress).Error

	if err != nil {
		return nil, err
	}

	return &progress, nil
}

func (r *astrologerRepository) UpdateBasicProfile(tx *gorm.DB, user *models.User, astrologer *models.Astrologer) error {

	if err := tx.Save(user).Error; err != nil {
		return err
	}
	if err := tx.Save(astrologer).Error; err != nil {
		return err
	}
	return nil
}

func (r *astrologerRepository) UpdateProfileImage(
	tx *gorm.DB,
	astrologerID uint,
	image string,
) error {

	return tx.Model(&models.Astrologer{}).
		Where("id = ?", astrologerID).
		Update("profileImage", image).Error
}

func (r *astrologerRepository) DeleteProfileImage(
	tx *gorm.DB,
	userID uint,
	astrologerID uint,
) error {
	const DefaultProfileImage = "uploads/default/profile.png"
	if err := tx.Model(&models.User{}).
		Where("id = ?", userID).
		Update("profile", DefaultProfileImage).Error; err != nil {

		return err
	}

	if err := tx.Model(&models.Astrologer{}).
		Where("id = ?", astrologerID).
		Update("profileImage", DefaultProfileImage).Error; err != nil {

		return err
	}

	return nil
}

func (r *astrologerRepository) UpdateBankAccount(tx *gorm.DB, bank *models.AstrologerBankAccount) error {

	return tx.Save(bank).Error
}

func (r *astrologerRepository) GetBankAccountByAstrologerID(
	astrologerID uint,
) (*models.AstrologerBankAccount, error) {

	var bank models.AstrologerBankAccount

	err := r.db.
		Where("astrologer_id = ?", astrologerID).
		First(&bank).Error

	if err != nil {
		return nil, err
	}

	return &bank, nil
}

func (r *astrologerRepository) DeleteSkillsByAstrologerID(tx *gorm.DB, astrologerID uint) error {
	return tx.Where("astrologer_id = ?", astrologerID).Delete(&models.AstrologerSkill{}).Error
}

func (r *astrologerRepository) GetSkillByID(id uint) (*models.SkillMaster, error) {

	var skill models.SkillMaster

	err := r.db.
		Where("id = ?", id).
		First(&skill).Error

	if err != nil {
		return nil, err
	}

	return &skill, nil
}

func (r *astrologerRepository) DeleteLanguagesByAstrologerID(tx *gorm.DB, astrologerID uint) error {
	return tx.Where("astrologer_id = ?", astrologerID).
		Delete(&models.AstrologerLanguage{}).Error
}

func (r *astrologerRepository) GetLanguageByID(id uint) (*models.Language, error) {
	var language models.Language
	err := r.db.
		Where("id = ?", id).
		First(&language).Error
	if err != nil {
		return nil, err
	}
	return &language, nil
}

// FindExistingLanguageIDs returns the ids from the given set that exist in the
// languages master. One query, so the whole selection can be validated before
// anything is inserted — the alternative was letting the insert hit
// fk_language_master and surfacing MySQL's error 1452 to the app.
func (r *astrologerRepository) FindExistingLanguageIDs(ids []uint) ([]uint, error) {

	existing := []uint{}

	if len(ids) == 0 {
		return existing, nil
	}

	err := r.db.
		Model(&models.Language{}).
		Where("id IN ?", ids).
		Pluck("id", &existing).Error

	if err != nil {
		return nil, err
	}

	return existing, nil
}

func (r *astrologerRepository) DeleteEducationsByAstrologerID(tx *gorm.DB, astrologerID uint) error {

	return tx.Where("astrologer_id = ?", astrologerID).Delete(&models.AstrologerEducation{}).Error
}
