package dto

import (
	"bytes"
	"encoding/json"
)

// JSON:API Medicine DTOs

type MedicineAttributes struct {
	Name             string                  `json:"name" example:"Paracetamol"`
	SortKey          *int                    `json:"sortkey" example:"1"`
	Note             string                  `json:"note,omitempty" example:"Main stock medicine"`
	Pack             string                  `json:"pack,omitempty" example:"500mg"`
	Unit             string                  `json:"unit,omitempty" example:"tablet"`
	Column           int64                   `json:"column" example:"1"`
	MedicineGroupID  string                  `json:"medicine_group_id,omitempty" example:"018f3a5c-7a6f-7c2a-8d4a-4b5b1f6c8e9d"`
	MotorReactionID  string                  `json:"motor_reaction_id,omitempty" example:"018f3a5c-7a6f-7c2a-8d4a-4b5b1f6c8e9d"`
	MotorReactionIDs []string                `json:"motor_reaction_ids,omitempty" example:"018f3a5c-7a6f-7c2a-8d4a-4b5b1f6c8e9d"`
	MedicineGroup    *MedicineGroupResource  `json:"medicine_group,omitempty"`
	MotorReaction    *MotorReactionResource  `json:"motor_reaction,omitempty"`
	MotorReactions   []MotorReactionResource `json:"motor_reactions,omitempty"`
	IsActive         bool                    `json:"is_active" example:"true"`
	CreatedAt        string                  `json:"created_at,omitempty" example:"2026-03-12T03:04:05Z"`
	CreatedBy        string                  `json:"created_by" example:"018f3a5c-7a6f-7c2a-8d4a-4b5b1f6c8e9d"`
	UpdatedAt        string                  `json:"updated_at,omitempty" example:"2026-03-12T03:04:05Z"`
	UpdatedBy        string                  `json:"updated_by" example:"018f3a5c-7a6f-7c2a-8d4a-4b5b1f6c8e9d"`
	DeletedAt        string                  `json:"deleted_at,omitempty" example:"2026-03-12T03:04:05Z"`
	DeletedBy        string                  `json:"deleted_by,omitempty" example:"018f3a5c-7a6f-7c2a-8d4a-4b5b1f6c8e9d"`
}

type MedicineResource struct {
	Type       string             `json:"type" example:"medicine"`
	ID         string             `json:"id" example:"018f3a5c-7a6f-7c2a-8d4a-4b5b1f6c8e9d"`
	Attributes MedicineAttributes `json:"attributes"`
}

type MedicineResponse struct {
	Data MedicineResource `json:"data"`
}

type MedicineListResponse struct {
	Data []MedicineResource `json:"data"`
	Meta struct {
		PageNumber int   `json:"page_number" example:"1"`
		PageSize   int   `json:"page_size" example:"20"`
		Total      int64 `json:"total" example:"120"`
	} `json:"meta"`
}

type MedicineDataTableResponse struct {
	Data []MedicineResource `json:"data"`
	Meta struct {
		Draw            int   `json:"draw" example:"1"`
		RecordsTotal    int64 `json:"records_total" example:"120"`
		RecordsFiltered int64 `json:"records_filtered" example:"12"`
	} `json:"meta"`
}

type MedicineCreateAttributes struct {
	Name             string   `json:"name" validate:"required" example:"Paracetamol"`
	SortKey          *int     `json:"sortkey" example:"1"`
	Note             *string  `json:"note,omitempty" example:"Main stock medicine"`
	Pack             *string  `json:"pack,omitempty" example:"500mg"`
	Unit             *string  `json:"unit,omitempty" validate:"omitempty,max=50" example:"tablet"`
	Column           *int64   `json:"column,omitempty" example:"1"`
	MedicineGroupID  *string  `json:"medicine_group_id,omitempty" example:"018f3a5c-7a6f-7c2a-8d4a-4b5b1f6c8e9d"`
	MotorReactionID  *string  `json:"motor_reaction_id,omitempty" example:"018f3a5c-7a6f-7c2a-8d4a-4b5b1f6c8e9d"`
	MotorReactionIDs []string `json:"motor_reaction_ids,omitempty" example:"018f3a5c-7a6f-7c2a-8d4a-4b5b1f6c8e9d"`
	IsActive         *bool    `json:"is_active,omitempty" example:"true"`
}

type MedicineCreateData struct {
	Type       string                   `json:"type" validate:"required,oneof=medicine_create medicine" example:"medicine_create"`
	Attributes MedicineCreateAttributes `json:"attributes" validate:"required"`
}

type MedicineCreateRequest struct {
	Data MedicineCreateData `json:"data" validate:"required"`
}

type MedicineUpdateAttributes struct {
	Name             *string    `json:"name,omitempty" example:"Paracetamol"`
	SortKey          NullInt    `json:"sortkey,omitempty" swaggertype:"integer" example:"1"`
	Note             *string    `json:"note,omitempty" example:"Main stock medicine"`
	Pack             *string    `json:"pack,omitempty" example:"500mg"`
	Unit             *string    `json:"unit,omitempty" validate:"omitempty,max=50" example:"tablet"`
	Column           *int64     `json:"column,omitempty" example:"1"`
	MedicineGroupID  NullString `json:"medicine_group_id,omitempty" swaggertype:"string" example:"018f3a5c-7a6f-7c2a-8d4a-4b5b1f6c8e9d"`
	MotorReactionID  NullString `json:"motor_reaction_id,omitempty" swaggertype:"string" example:"018f3a5c-7a6f-7c2a-8d4a-4b5b1f6c8e9d"`
	MotorReactionIDs []string   `json:"motor_reaction_ids,omitempty" example:"018f3a5c-7a6f-7c2a-8d4a-4b5b1f6c8e9d"`
	IsActive         *bool      `json:"is_active,omitempty" example:"true"`
}

type MedicineUpdateData struct {
	Type       string                   `json:"type" validate:"required,oneof=medicine_update medicine" example:"medicine_update"`
	ID         string                   `json:"id" example:"018f3a5c-7a6f-7c2a-8d4a-4b5b1f6c8e9d"`
	Attributes MedicineUpdateAttributes `json:"attributes" validate:"required"`
}

type MedicineUpdateRequest struct {
	Data MedicineUpdateData `json:"data" validate:"required"`
}

type MedicineGroupAttributes struct {
	Name      string `json:"name" example:"Spritze"`
	CreatedAt string `json:"created_at,omitempty" example:"2026-03-12T03:04:05Z"`
	CreatedBy string `json:"created_by" example:"018f3a5c-7a6f-7c2a-8d4a-4b5b1f6c8e9d"`
	UpdatedAt string `json:"updated_at,omitempty" example:"2026-03-12T03:04:05Z"`
	UpdatedBy string `json:"updated_by" example:"018f3a5c-7a6f-7c2a-8d4a-4b5b1f6c8e9d"`
	DeletedAt string `json:"deleted_at,omitempty" example:"2026-03-12T03:04:05Z"`
	DeletedBy string `json:"deleted_by,omitempty" example:"018f3a5c-7a6f-7c2a-8d4a-4b5b1f6c8e9d"`
}

type MedicineGroupResource struct {
	Type       string                  `json:"type" example:"medicine_group"`
	ID         string                  `json:"id" example:"018f3a5c-7a6f-7c2a-8d4a-4b5b1f6c8e9d"`
	Attributes MedicineGroupAttributes `json:"attributes"`
}

type MedicineGroupResponse struct {
	Data MedicineGroupResource `json:"data"`
}

type MedicineGroupListResponse struct {
	Data []MedicineGroupResource `json:"data"`
	Meta struct {
		PageNumber int   `json:"page_number" example:"1"`
		PageSize   int   `json:"page_size" example:"20"`
		Total      int64 `json:"total" example:"120"`
	} `json:"meta"`
}

type MedicineGroupDataTableResponse struct {
	Data []MedicineGroupResource `json:"data"`
	Meta struct {
		Draw            int   `json:"draw" example:"1"`
		RecordsTotal    int64 `json:"records_total" example:"120"`
		RecordsFiltered int64 `json:"records_filtered" example:"12"`
	} `json:"meta"`
}

type MedicineGroupCreateAttributes struct {
	Name string `json:"name" validate:"required" example:"Spritze"`
}

type MedicineGroupCreateData struct {
	Type       string                        `json:"type" validate:"required,oneof=medicine_group_create medicine_group" example:"medicine_group_create"`
	Attributes MedicineGroupCreateAttributes `json:"attributes" validate:"required"`
}

type MedicineGroupCreateRequest struct {
	Data MedicineGroupCreateData `json:"data" validate:"required"`
}

type MedicineGroupUpdateAttributes struct {
	Name *string `json:"name,omitempty" example:"Spritze"`
}

type MedicineGroupUpdateData struct {
	Type       string                        `json:"type" validate:"required,oneof=medicine_group_update medicine_group" example:"medicine_group_update"`
	ID         string                        `json:"id" example:"018f3a5c-7a6f-7c2a-8d4a-4b5b1f6c8e9d"`
	Attributes MedicineGroupUpdateAttributes `json:"attributes" validate:"required"`
}

type MedicineGroupUpdateRequest struct {
	Data MedicineGroupUpdateData `json:"data" validate:"required"`
}

type MotorReactionAttributes struct {
	Name      string `json:"name" example:"gezielt auf Schmerzreiz"`
	Score     *int64 `json:"score" example:"5"`
	CreatedAt string `json:"created_at,omitempty" example:"2026-03-12T03:04:05Z"`
	CreatedBy string `json:"created_by" example:"018f3a5c-7a6f-7c2a-8d4a-4b5b1f6c8e9d"`
	UpdatedAt string `json:"updated_at,omitempty" example:"2026-03-12T03:04:05Z"`
	UpdatedBy string `json:"updated_by" example:"018f3a5c-7a6f-7c2a-8d4a-4b5b1f6c8e9d"`
	DeletedAt string `json:"deleted_at,omitempty" example:"2026-03-12T03:04:05Z"`
	DeletedBy string `json:"deleted_by,omitempty" example:"018f3a5c-7a6f-7c2a-8d4a-4b5b1f6c8e9d"`
}

type MotorReactionResource struct {
	Type       string                  `json:"type" example:"motor_reaction"`
	ID         string                  `json:"id" example:"018f3a5c-7a6f-7c2a-8d4a-4b5b1f6c8e9d"`
	Attributes MotorReactionAttributes `json:"attributes"`
}

type MotorReactionResponse struct {
	Data MotorReactionResource `json:"data"`
}

type MotorReactionListResponse struct {
	Data []MotorReactionResource `json:"data"`
	Meta struct {
		PageNumber int   `json:"page_number" example:"1"`
		PageSize   int   `json:"page_size" example:"20"`
		Total      int64 `json:"total" example:"120"`
	} `json:"meta"`
}

type MotorReactionDataTableResponse struct {
	Data []MotorReactionResource `json:"data"`
	Meta struct {
		Draw            int   `json:"draw" example:"1"`
		RecordsTotal    int64 `json:"records_total" example:"120"`
		RecordsFiltered int64 `json:"records_filtered" example:"12"`
	} `json:"meta"`
}

type MotorReactionCreateAttributes struct {
	Name  string `json:"name" validate:"required" example:"gezielt auf Schmerzreiz"`
	Score *int64 `json:"score,omitempty" example:"5"`
}

type MotorReactionCreateData struct {
	Type       string                        `json:"type" validate:"required,oneof=motor_reaction_create motor_reaction" example:"motor_reaction_create"`
	Attributes MotorReactionCreateAttributes `json:"attributes" validate:"required"`
}

type MotorReactionCreateRequest struct {
	Data MotorReactionCreateData `json:"data" validate:"required"`
}

type MotorReactionUpdateAttributes struct {
	Name  *string   `json:"name,omitempty" example:"gezielt auf Schmerzreiz"`
	Score NullInt64 `json:"score,omitempty" swaggertype:"integer" example:"5"`
}

// NullInt64 allows PATCH semantics:
// - field omitted  => Set=false (no change)
// - value null     => Set=true, Valid=false (set DB NULL)
// - value number   => Set=true, Valid=true, Value=<number>
type NullInt64 struct {
	Set   bool
	Valid bool
	Value int64
}

func (n *NullInt64) UnmarshalJSON(data []byte) error {
	n.Set = true
	trimmed := bytes.TrimSpace(data)
	if bytes.Equal(trimmed, []byte("null")) {
		n.Valid = false
		n.Value = 0
		return nil
	}
	var v int64
	if err := json.Unmarshal(trimmed, &v); err != nil {
		return err
	}
	n.Valid = true
	n.Value = v
	return nil
}

type MotorReactionUpdateData struct {
	Type       string                        `json:"type" validate:"required,oneof=motor_reaction_update motor_reaction" example:"motor_reaction_update"`
	ID         string                        `json:"id" example:"018f3a5c-7a6f-7c2a-8d4a-4b5b1f6c8e9d"`
	Attributes MotorReactionUpdateAttributes `json:"attributes" validate:"required"`
}

type MotorReactionUpdateRequest struct {
	Data MotorReactionUpdateData `json:"data" validate:"required"`
}
