package services

import (
	"errors"

	"gauth-central/internal/database"
	"gauth-central/internal/models"

	"gorm.io/gorm"
)

type ResumeService struct{}

func NewResumeService() *ResumeService {
	return &ResumeService{}
}

// CreateResume creates a new resume configuration.
func (s *ResumeService) CreateResume(title, titleSub, education, experience, codingSkills, knowledge string, isActive bool) (*models.Resume, error) {
	item := models.Resume{
		Title:        title,
		TitleSub:     titleSub,
		Education:    education,
		Experience:   experience,
		CodingSkills: codingSkills,
		Knowledge:    knowledge,
		IsActive:     isActive,
	}

	err := database.DB.Transaction(func(tx *gorm.DB) error {
		if isActive {
			// Deactivate all other resumes
			if err := tx.Model(&models.Resume{}).Where("is_active = ?", true).Update("is_active", false).Error; err != nil {
				return err
			}
		}
		if err := tx.Create(&item).Error; err != nil {
			return err
		}
		return nil
	})

	if err != nil {
		return nil, err
	}

	return s.GetResumeByID(item.ID.String())
}

// GetAllResumes retrieves all resumes. Use onlyActive to filter public data.
// For admin (onlyActive=false), it returns basic info.
// For public (onlyActive=true), it preloads all related data (Educations, Experiences, etc.)
func (s *ResumeService) GetAllResumes(onlyActive bool) ([]models.Resume, error) {
	var items []models.Resume
	query := database.DB.Order("created_at desc")

	if onlyActive {
		query = query.Where("is_active = ?", true).
			Preload("Educations", func(db *gorm.DB) *gorm.DB {
				return db.Where("is_active = ?", true).Order("created_at desc")
			}).
			Preload("Experiences", func(db *gorm.DB) *gorm.DB {
				return db.Where("is_active = ?", true).Order("created_at desc")
			}).
			Preload("Skills", func(db *gorm.DB) *gorm.DB {
				return db.Where("is_active = ?", true).Order("degree desc")
			}).
			Preload("Knowledges", func(db *gorm.DB) *gorm.DB {
				return db.Where("is_active = ?", true).Order("created_at desc")
			})
	}

	if err := query.Find(&items).Error; err != nil {
		return nil, err
	}

	return items, nil
}

// GetFirstActiveResume returns the single active resume with all relations preloaded.
func (s *ResumeService) GetFirstActiveResume() (*models.Resume, error) {
	var item models.Resume
	query := database.DB.Where("is_active = ?", true).Order("created_at desc").
		Preload("Educations", func(db *gorm.DB) *gorm.DB {
			return db.Where("is_active = ?", true).Order("created_at desc")
		}).
		Preload("Experiences", func(db *gorm.DB) *gorm.DB {
			return db.Where("is_active = ?", true).Order("created_at desc")
		}).
		Preload("Skills", func(db *gorm.DB) *gorm.DB {
			return db.Where("is_active = ?", true).Order("degree desc")
		}).
		Preload("Knowledges", func(db *gorm.DB) *gorm.DB {
			return db.Where("is_active = ?", true).Order("created_at desc")
		})

	if err := query.First(&item).Error; err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return nil, errors.New("resume not found")
		}
		return nil, err
	}
	return &item, nil
}

// GetResumeByID retrieves a resume by ID.
func (s *ResumeService) GetResumeByID(id string) (*models.Resume, error) {
	var item models.Resume
	if err := database.DB.Where("id = ?", id).
		Preload("Educations").
		Preload("Experiences").
		Preload("Skills").
		Preload("Knowledges").
		First(&item).Error; err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return nil, errors.New("resume not found")
		}
		return nil, err
	}
	return &item, nil
}

// UpdateResume updates an existing resume entry.
func (s *ResumeService) UpdateResume(id string, title, titleSub, education, experience, codingSkills, knowledge *string, isActive *bool) (*models.Resume, error) {
	item, err := s.GetResumeByID(id)
	if err != nil {
		return nil, err
	}

	updates := map[string]interface{}{}
	if title != nil {
		updates["title"] = *title
	}
	if titleSub != nil {
		updates["title_sub"] = *titleSub
	}
	if education != nil {
		updates["education"] = *education
	}
	if experience != nil {
		updates["experience"] = *experience
	}
	if codingSkills != nil {
		updates["coding_skills"] = *codingSkills
	}
	if knowledge != nil {
		updates["knowledge"] = *knowledge
	}
	if isActive != nil {
		updates["is_active"] = *isActive
	}

	if len(updates) > 0 {
		err := database.DB.Transaction(func(tx *gorm.DB) error {
			if isActive != nil && *isActive {
				// Deactivate all other resumes except the current one
				if err := tx.Model(&models.Resume{}).Where("id != ? AND is_active = ?", id, true).Update("is_active", false).Error; err != nil {
					return err
				}
			}
			if err := tx.Model(item).Updates(updates).Error; err != nil {
				return err
			}
			return nil
		})
		if err != nil {
			return nil, err
		}
	}

	return s.GetResumeByID(id)
}

// DeleteResume deletes a resume by ID.
func (s *ResumeService) DeleteResume(id string) error {
	result := database.DB.Delete(&models.Resume{}, "id = ?", id)
	if result.Error != nil {
		return result.Error
	}
	if result.RowsAffected == 0 {
		return errors.New("resume not found")
	}
	return nil
}
