package models

import (
	"regexp"
	"strings"
	"time"

	"github.com/go-playground/validator/v10"
)

// CustomValidator wraps the validator
type CustomValidator struct {
	Validator *validator.Validate
}

// Validate validates struct
func (cv *CustomValidator) Validate(i interface{}) error {
	return cv.Validator.Struct(i)
}

// RegisterCustomValidations registers custom validation rules
func RegisterCustomValidations(v *validator.Validate) {
	// Validate Indonesian phone number
	v.RegisterValidation("indonesian_phone", validateIndonesianPhone)

	// Validate BPJS card number format
	v.RegisterValidation("bpjs_card", validateBPJSCard)

	// Validate Indonesian NIK
	v.RegisterValidation("indonesian_nik", validateIndonesianNIK)

	// Validate date format YYYY-MM-DD
	v.RegisterValidation("date_format", validateDateFormat)

	// Validate ICD-10 code format
	v.RegisterValidation("icd10", validateICD10)

	// Validate ICD-9-CM procedure code
	v.RegisterValidation("icd9cm", validateICD9CM)
}

func validateIndonesianPhone(fl validator.FieldLevel) bool {
	phone := fl.Field().String()
	if phone == "" {
		return true // Optional field
	}

	// Indonesian phone number pattern: +62, 62, 08, or 8
	pattern := `^(\+?62|0?8)[1-9][0-9]{7,11}$`
	matched, _ := regexp.MatchString(pattern, phone)
	return matched
}

func validateBPJSCard(fl validator.FieldLevel) bool {
	card := fl.Field().String()
	if len(card) != 13 {
		return false
	}

	// BPJS card should be numeric
	pattern := `^\d{13}$`
	matched, _ := regexp.MatchString(pattern, card)
	return matched
}

func validateIndonesianNIK(fl validator.FieldLevel) bool {
	nik := fl.Field().String()
	if len(nik) != 16 {
		return false
	}

	// NIK should be numeric
	pattern := `^\d{16}$`
	matched, _ := regexp.MatchString(pattern, nik)
	return matched
}

func validateDateFormat(fl validator.FieldLevel) bool {
	dateStr := fl.Field().String()
	_, err := time.Parse("2006-01-02", dateStr)
	return err == nil
}

func validateICD10(fl validator.FieldLevel) bool {
	code := fl.Field().String()
	if code == "" {
		return true
	}

	// Basic ICD-10 pattern: Letter followed by 2 digits, optional dot and more digits
	pattern := `^[A-Z]\d{2}(\.\d+)?$`
	matched, _ := regexp.MatchString(pattern, strings.ToUpper(code))
	return matched
}

func validateICD9CM(fl validator.FieldLevel) bool {
	code := fl.Field().String()
	if code == "" {
		return true
	}

	// Basic ICD-9-CM procedure pattern: 2-4 digits with optional decimal
	pattern := `^\d{2,4}(\.\d+)?$`
	matched, _ := regexp.MatchString(pattern, code)
	return matched
}
