package models

import (
	"database/sql"
	"database/sql/driver"
	"net/http"
	"strconv"
	"time"
)

// NullableInt32 - your existing implementation
type NullableInt32 struct {
	Int32 int32 `json:"int32,omitempty"`
	Valid bool  `json:"valid"`
}

// Scan implements the sql.Scanner interface for NullableInt32
func (n *NullableInt32) Scan(value interface{}) error {
	var ni sql.NullInt32
	if err := ni.Scan(value); err != nil {
		return err
	}
	n.Int32 = ni.Int32
	n.Valid = ni.Valid
	return nil
}

// Value implements the driver.Valuer interface for NullableInt32
func (n NullableInt32) Value() (driver.Value, error) {
	if !n.Valid {
		return nil, nil
	}
	return n.Int32, nil
}

// NullableString provides consistent nullable string handling
type NullableString struct {
	String string `json:"string,omitempty"`
	Valid  bool   `json:"valid"`
}

// Scan implements the sql.Scanner interface for NullableString
func (n *NullableString) Scan(value interface{}) error {
	var ns sql.NullString
	if err := ns.Scan(value); err != nil {
		return err
	}
	n.String = ns.String
	n.Valid = ns.Valid
	return nil
}

// Value implements the driver.Valuer interface for NullableString
func (n NullableString) Value() (driver.Value, error) {
	if !n.Valid {
		return nil, nil
	}
	return n.String, nil
}

// NullableTime provides consistent nullable time handling
type NullableTime struct {
	Time  time.Time `json:"time,omitempty"`
	Valid bool      `json:"valid"`
}

// Scan implements the sql.Scanner interface for NullableTime
func (n *NullableTime) Scan(value interface{}) error {
	var nt sql.NullTime
	if err := nt.Scan(value); err != nil {
		return err
	}
	n.Time = nt.Time
	n.Valid = nt.Valid
	return nil
}

// Value implements the driver.Valuer interface for NullableTime
func (n NullableTime) Value() (driver.Value, error) {
	if !n.Valid {
		return nil, nil
	}
	return n.Time, nil
}

// Metadata untuk pagination - dioptimalkan
type MetaResponse struct {
	Limit       int  `json:"limit"`
	Offset      int  `json:"offset"`
	Total       int  `json:"total"`
	TotalPages  int  `json:"total_pages"`
	CurrentPage int  `json:"current_page"`
	HasNext     bool `json:"has_next"`
	HasPrev     bool `json:"has_prev"`
}

// Aggregate data untuk summary
type AggregateData struct {
	TotalActive   int            `json:"total_active"`
	TotalDraft    int            `json:"total_draft"`
	TotalInactive int            `json:"total_inactive"`
	ByStatus      map[string]int `json:"by_status"`
	ByDinas       map[string]int `json:"by_dinas,omitempty"`
	ByJenis       map[string]int `json:"by_jenis,omitempty"`
	LastUpdated   *time.Time     `json:"last_updated,omitempty"`
	CreatedToday  int            `json:"created_today"`
	UpdatedToday  int            `json:"updated_today"`
}

// Error response yang konsisten
type ErrorResponse struct {
	Error     string    `json:"error"`
	Code      int       `json:"code"`
	Message   string    `json:"message"`
	Timestamp time.Time `json:"timestamp"`
}

// BaseRequest contains common fields for all BPJS requests
type BaseRequest struct {
	RequestID string    `json:"request_id,omitempty"`
	Timestamp time.Time `json:"timestamp,omitempty"`
}

// BaseResponse contains common response fields
type BaseResponse struct {
	Status    string `json:"status"`
	Message   string `json:"message,omitempty"`
	RequestID string `json:"request_id,omitempty"`
	Timestamp string `json:"timestamp,omitempty"`
}

// ErrorResponse represents error response structure
type ErrorResponseBpjs struct {
	Status    string                 `json:"status"`
	Message   string                 `json:"message"`
	RequestID string                 `json:"request_id,omitempty"`
	Errors    map[string]interface{} `json:"errors,omitempty"`
	Code      string                 `json:"code,omitempty"`
}

// PaginationRequest contains pagination parameters
type PaginationRequest struct {
	Page    int    `json:"page" validate:"min=1"`
	Limit   int    `json:"limit" validate:"min=1,max=100"`
	SortBy  string `json:"sort_by,omitempty"`
	SortDir string `json:"sort_dir,omitempty" validate:"omitempty,oneof=asc desc"`
}

// PaginationResponse contains pagination metadata
type PaginationResponse struct {
	CurrentPage  int   `json:"current_page"`
	TotalPages   int   `json:"total_pages"`
	TotalItems   int64 `json:"total_items"`
	ItemsPerPage int   `json:"items_per_page"`
	HasNext      bool  `json:"has_next"`
	HasPrev      bool  `json:"has_previous"`
}

// MetaInfo contains additional metadata
type MetaInfo struct {
	Version     string `json:"version"`
	Environment string `json:"environment"`
	ServerTime  string `json:"server_time"`
}

func GetStatusCodeFromMeta(metaCode interface{}) int {
	statusCode := http.StatusOK

	if metaCode != nil {
		switch v := metaCode.(type) {
		case string:
			if code, err := strconv.Atoi(v); err == nil {
				if code >= 100 && code <= 599 {
					statusCode = code
				} else {
					statusCode = http.StatusInternalServerError
				}
			} else {
				statusCode = http.StatusInternalServerError
			}
		case int:
			if v >= 100 && v <= 599 {
				statusCode = v
			} else {
				statusCode = http.StatusInternalServerError
			}
		case float64:
			code := int(v)
			if code >= 100 && code <= 599 {
				statusCode = code
			} else {
				statusCode = http.StatusInternalServerError
			}
		default:
			statusCode = http.StatusInternalServerError
		}
	}

	return statusCode
}

// Validation constants
const (
	StatusDraft    = "draft"
	StatusActive   = "active"
	StatusInactive = "inactive"
	StatusDeleted  = "deleted"
)

// ValidStatuses untuk validasi
var ValidStatuses = []string{StatusDraft, StatusActive, StatusInactive}

// IsValidStatus helper function
func IsValidStatus(status string) bool {
	for _, validStatus := range ValidStatuses {
		if status == validStatus {
			return true
		}
	}
	return false
}
