package retribusi

import (
	"api-service/internal/models"
	"encoding/json"
	"time"
)

// Retribusi represents the data structure for the retribusi table
// with proper null handling and optimized JSON marshaling
type Retribusi struct {
	ID             string                `json:"id" db:"id"`
	Status         string                `json:"status" db:"status"`
	Sort           models.NullableInt32  `json:"sort,omitempty" db:"sort"`
	UserCreated    models.NullableString `json:"user_created,omitempty" db:"user_created"`
	DateCreated    models.NullableTime   `json:"date_created,omitempty" db:"date_created"`
	UserUpdated    models.NullableString `json:"user_updated,omitempty" db:"user_updated"`
	DateUpdated    models.NullableTime   `json:"date_updated,omitempty" db:"date_updated"`
	Jenis          models.NullableString `json:"jenis,omitempty" db:"Jenis"`
	Pelayanan      models.NullableString `json:"pelayanan,omitempty" db:"Pelayanan"`
	Dinas          models.NullableString `json:"dinas,omitempty" db:"Dinas"`
	KelompokObyek  models.NullableString `json:"kelompok_obyek,omitempty" db:"Kelompok_obyek"`
	KodeTarif      models.NullableString `json:"kode_tarif,omitempty" db:"Kode_tarif"`
	Tarif          models.NullableString `json:"tarif,omitempty" db:"Tarif"`
	Satuan         models.NullableString `json:"satuan,omitempty" db:"Satuan"`
	TarifOvertime  models.NullableString `json:"tarif_overtime,omitempty" db:"Tarif_overtime"`
	SatuanOvertime models.NullableString `json:"satuan_overtime,omitempty" db:"Satuan_overtime"`
	RekeningPokok  models.NullableString `json:"rekening_pokok,omitempty" db:"Rekening_pokok"`
	RekeningDenda  models.NullableString `json:"rekening_denda,omitempty" db:"Rekening_denda"`
	Uraian1        models.NullableString `json:"uraian_1,omitempty" db:"Uraian_1"`
	Uraian2        models.NullableString `json:"uraian_2,omitempty" db:"Uraian_2"`
	Uraian3        models.NullableString `json:"uraian_3,omitempty" db:"Uraian_3"`
}

// Custom JSON marshaling untuk Retribusi agar NULL values tidak muncul di response
func (r Retribusi) MarshalJSON() ([]byte, error) {
	type Alias Retribusi
	aux := &struct {
		Sort           *int       `json:"sort,omitempty"`
		UserCreated    *string    `json:"user_created,omitempty"`
		DateCreated    *time.Time `json:"date_created,omitempty"`
		UserUpdated    *string    `json:"user_updated,omitempty"`
		DateUpdated    *time.Time `json:"date_updated,omitempty"`
		Jenis          *string    `json:"jenis,omitempty"`
		Pelayanan      *string    `json:"pelayanan,omitempty"`
		Dinas          *string    `json:"dinas,omitempty"`
		KelompokObyek  *string    `json:"kelompok_obyek,omitempty"`
		KodeTarif      *string    `json:"kode_tarif,omitempty"`
		Tarif          *string    `json:"tarif,omitempty"`
		Satuan         *string    `json:"satuan,omitempty"`
		TarifOvertime  *string    `json:"tarif_overtime,omitempty"`
		SatuanOvertime *string    `json:"satuan_overtime,omitempty"`
		RekeningPokok  *string    `json:"rekening_pokok,omitempty"`
		RekeningDenda  *string    `json:"rekening_denda,omitempty"`
		Uraian1        *string    `json:"uraian_1,omitempty"`
		Uraian2        *string    `json:"uraian_2,omitempty"`
		Uraian3        *string    `json:"uraian_3,omitempty"`
		*Alias
	}{
		Alias: (*Alias)(&r),
	}

	// Convert NullableInt32 to pointer
	if r.Sort.Valid {
		sort := int(r.Sort.Int32)
		aux.Sort = &sort
	}
	if r.UserCreated.Valid {
		aux.UserCreated = &r.UserCreated.String
	}
	if r.DateCreated.Valid {
		aux.DateCreated = &r.DateCreated.Time
	}
	if r.UserUpdated.Valid {
		aux.UserUpdated = &r.UserUpdated.String
	}
	if r.DateUpdated.Valid {
		aux.DateUpdated = &r.DateUpdated.Time
	}
	if r.Jenis.Valid {
		aux.Jenis = &r.Jenis.String
	}
	if r.Pelayanan.Valid {
		aux.Pelayanan = &r.Pelayanan.String
	}
	if r.Dinas.Valid {
		aux.Dinas = &r.Dinas.String
	}
	if r.KelompokObyek.Valid {
		aux.KelompokObyek = &r.KelompokObyek.String
	}
	if r.KodeTarif.Valid {
		aux.KodeTarif = &r.KodeTarif.String
	}
	if r.Tarif.Valid {
		aux.Tarif = &r.Tarif.String
	}
	if r.Satuan.Valid {
		aux.Satuan = &r.Satuan.String
	}
	if r.TarifOvertime.Valid {
		aux.TarifOvertime = &r.TarifOvertime.String
	}
	if r.SatuanOvertime.Valid {
		aux.SatuanOvertime = &r.SatuanOvertime.String
	}
	if r.RekeningPokok.Valid {
		aux.RekeningPokok = &r.RekeningPokok.String
	}
	if r.RekeningDenda.Valid {
		aux.RekeningDenda = &r.RekeningDenda.String
	}
	if r.Uraian1.Valid {
		aux.Uraian1 = &r.Uraian1.String
	}
	if r.Uraian2.Valid {
		aux.Uraian2 = &r.Uraian2.String
	}
	if r.Uraian3.Valid {
		aux.Uraian3 = &r.Uraian3.String
	}

	return json.Marshal(aux)
}

// Helper methods untuk mendapatkan nilai yang aman
func (r *Retribusi) GetJenis() string {
	if r.Jenis.Valid {
		return r.Jenis.String
	}
	return ""
}

func (r *Retribusi) GetDinas() string {
	if r.Dinas.Valid {
		return r.Dinas.String
	}
	return ""
}

func (r *Retribusi) GetTarif() string {
	if r.Tarif.Valid {
		return r.Tarif.String
	}
	return ""
}

// Response struct untuk GET by ID - diperbaiki struktur
type RetribusiGetByIDResponse struct {
	Message string     `json:"message"`
	Data    *Retribusi `json:"data"`
}

// Request struct untuk create - dioptimalkan dengan validasi
type RetribusiCreateRequest struct {
	Status         string  `json:"status" validate:"required,oneof=draft active inactive"`
	Jenis          *string `json:"jenis,omitempty" validate:"omitempty,min=1,max=255"`
	Pelayanan      *string `json:"pelayanan,omitempty" validate:"omitempty,min=1,max=255"`
	Dinas          *string `json:"dinas,omitempty" validate:"omitempty,min=1,max=255"`
	KelompokObyek  *string `json:"kelompok_obyek,omitempty" validate:"omitempty,min=1,max=255"`
	KodeTarif      *string `json:"kode_tarif,omitempty" validate:"omitempty,min=1,max=255"`
	Uraian1        *string `json:"uraian_1,omitempty"`
	Uraian2        *string `json:"uraian_2,omitempty"`
	Uraian3        *string `json:"uraian_3,omitempty"`
	Tarif          *string `json:"tarif,omitempty" validate:"omitempty,numeric"`
	Satuan         *string `json:"satuan,omitempty" validate:"omitempty,min=1,max=255"`
	TarifOvertime  *string `json:"tarif_overtime,omitempty" validate:"omitempty,numeric"`
	SatuanOvertime *string `json:"satuan_overtime,omitempty" validate:"omitempty,min=1,max=255"`
	RekeningPokok  *string `json:"rekening_pokok,omitempty" validate:"omitempty,min=1,max=255"`
	RekeningDenda  *string `json:"rekening_denda,omitempty" validate:"omitempty,min=1,max=255"`
}

// Response struct untuk create
type RetribusiCreateResponse struct {
	Message string     `json:"message"`
	Data    *Retribusi `json:"data"`
}

// Update request - sama seperti create tapi dengan ID
type RetribusiUpdateRequest struct {
	ID             string  `json:"-" validate:"required,uuid4"` // ID dari URL path
	Status         string  `json:"status" validate:"required,oneof=draft active inactive"`
	Jenis          *string `json:"jenis,omitempty" validate:"omitempty,min=1,max=255"`
	Pelayanan      *string `json:"pelayanan,omitempty" validate:"omitempty,min=1,max=255"`
	Dinas          *string `json:"dinas,omitempty" validate:"omitempty,min=1,max=255"`
	KelompokObyek  *string `json:"kelompok_obyek,omitempty" validate:"omitempty,min=1,max=255"`
	KodeTarif      *string `json:"kode_tarif,omitempty" validate:"omitempty,min=1,max=255"`
	Uraian1        *string `json:"uraian_1,omitempty"`
	Uraian2        *string `json:"uraian_2,omitempty"`
	Uraian3        *string `json:"uraian_3,omitempty"`
	Tarif          *string `json:"tarif,omitempty" validate:"omitempty,numeric"`
	Satuan         *string `json:"satuan,omitempty" validate:"omitempty,min=1,max=255"`
	TarifOvertime  *string `json:"tarif_overtime,omitempty" validate:"omitempty,numeric"`
	SatuanOvertime *string `json:"satuan_overtime,omitempty" validate:"omitempty,min=1,max=255"`
	RekeningPokok  *string `json:"rekening_pokok,omitempty" validate:"omitempty,min=1,max=255"`
	RekeningDenda  *string `json:"rekening_denda,omitempty" validate:"omitempty,min=1,max=255"`
}

// Response struct untuk update
type RetribusiUpdateResponse struct {
	Message string     `json:"message"`
	Data    *Retribusi `json:"data"`
}

// Response struct untuk delete
type RetribusiDeleteResponse struct {
	Message string `json:"message"`
	ID      string `json:"id"`
}

// Enhanced GET response dengan pagination dan aggregation
type RetribusiGetResponse struct {
	Message string                `json:"message"`
	Data    []Retribusi           `json:"data"`
	Meta    models.MetaResponse   `json:"meta"`
	Summary *models.AggregateData `json:"summary,omitempty"`
}

// Filter struct untuk query parameters
type RetribusiFilter struct {
	Status        *string    `json:"status,omitempty" form:"status"`
	Jenis         *string    `json:"jenis,omitempty" form:"jenis"`
	Dinas         *string    `json:"dinas,omitempty" form:"dinas"`
	KelompokObyek *string    `json:"kelompok_obyek,omitempty" form:"kelompok_obyek"`
	Search        *string    `json:"search,omitempty" form:"search"`
	DateFrom      *time.Time `json:"date_from,omitempty" form:"date_from"`
	DateTo        *time.Time `json:"date_to,omitempty" form:"date_to"`
}
