package sr

import (
	"strings"
	"system-altrak/internal/domain"
	"system-altrak/internal/repository"

	"gorm.io/gorm"
)

type SRRepository interface {
	Create(sr *domain.ServiceRequisition) error
	Update(sr *domain.ServiceRequisition, branchID uint, role string) error
	GetByID(id uint, branchID uint, role string) (*domain.ServiceRequisition, error)
	List(branchID uint, role string) ([]domain.ServiceRequisition, error)
	GetNextSequence(docType string, year, month int) (int, error)
	Delete(id uint, branchID uint, role string) error
}

type repositoryImpl struct {
	base *repository.Repository
}

func NewRepository(base *repository.Repository) SRRepository {
	return &repositoryImpl{base: base}
}

func (r *repositoryImpl) Create(sr *domain.ServiceRequisition) error {
	return r.base.CreateServiceRequisition(sr)
}

func (r *repositoryImpl) Update(sr *domain.ServiceRequisition, branchID uint, role string) error {
	return r.base.GetDB().Transaction(func(tx *gorm.DB) error {
		var existing domain.ServiceRequisition
		query := tx.Where("id = ?", sr.ID)
		if role != "superadmin" && branchID > 0 {
			query = query.Where("branch_id = ?", branchID)
		}
		if err := query.First(&existing).Error; err != nil {
			return err
		}

		status := existing.Status
		if strings.TrimSpace(sr.Status) != "" {
			status = sr.Status
		}

		if err := tx.Model(&existing).Updates(map[string]interface{}{
			"charge_to":          sr.ChargeTo,
			"cc":                 sr.CC,
			"customer":           sr.Customer,
			"equipment_location": sr.EquipmentLocation,
			"sales_agreement_no": sr.SalesAgreementNo,
			"description":        sr.Description,
			"status":             status,
		}).Error; err != nil {
			return err
		}

		if err := tx.Unscoped().Where("service_requisition_id = ?", existing.ID).Delete(&domain.ServiceRequisitionChecklist{}).Error; err != nil {
			return err
		}
		if sr.Checklist != nil {
			sr.Checklist.ID = 0
			sr.Checklist.ServiceRequisitionID = existing.ID
			if err := tx.Omit("ID").Create(sr.Checklist).Error; err != nil {
				return err
			}
		}

		if err := tx.Unscoped().Where("service_requisition_id = ?", existing.ID).Delete(&domain.ServiceRequisitionEquipment{}).Error; err != nil {
			return err
		}
		for i := range sr.Equipments {
			sr.Equipments[i].ID = 0
			sr.Equipments[i].ServiceRequisitionID = existing.ID
			if err := tx.Omit("ID").Create(&sr.Equipments[i]).Error; err != nil {
				return err
			}
		}
		return nil
	})
}

func (r *repositoryImpl) GetByID(id uint, branchID uint, role string) (*domain.ServiceRequisition, error) {
	return r.base.GetServiceRequisitionByID(id, branchID, role)
}

func (r *repositoryImpl) List(branchID uint, role string) ([]domain.ServiceRequisition, error) {
	return r.base.ListServiceRequisitions(branchID, role)
}

func (r *repositoryImpl) GetNextSequence(docType string, year, month int) (int, error) {
	return r.base.GetNextSequence(docType, year, month)
}

func (r *repositoryImpl) Delete(id uint, branchID uint, role string) error {
	q := r.base.GetDB().Where("id = ?", id)
	if role != "superadmin" && branchID > 0 {
		q = q.Where("branch_id = ?", branchID)
	}
	return q.Delete(&domain.ServiceRequisition{}).Error
}
