package dto

import (
	"bytes"
	"encoding/json"
)

// JSON:API User DTOs

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

type UserListResponse struct {
	Data []UserResource `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 UserDataTableResponse struct {
	Data []UserResource `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"`
}

// Create

type UserCreateAttributes struct {
	Email       string   `json:"email" validate:"required,email" example:"user@example.com"`
	Username    string   `json:"username" validate:"required,min=3,max=100" example:"john.doe"`
	FirstName   string   `json:"first_name" validate:"required" example:"John"`
	LastName    string   `json:"last_name" validate:"required" example:"Doe"`
	MobilePhone string   `json:"mobile_phone,omitempty" example:"+628123456789"`
	Timezone    *string  `json:"timezone,omitempty" example:"Asia/Jakarta"`
	ImageUUID   *string  `json:"image_uuid,omitempty" example:"018f3a5c-7a6f-7c2a-8d4a-4b5b1f6c8e90"`
	RoleID      string   `json:"role_id" validate:"required" example:"018f3a5c-7a6f-7c2a-8d4a-4b5b1f6c8e9d"`
	RoleIDs     []string `json:"role_ids,omitempty" example:"[\"018f3a5c-7a6f-7c2a-8d4a-4b5b1f6c8e9d\",\"018f3a5c-7a6f-7c2a-8d4a-4b5b1f6c8e9e\"]"`
}

type UserCreateData struct {
	Type       string               `json:"type" validate:"required,oneof=user_create user" example:"user_create"`
	Attributes UserCreateAttributes `json:"attributes" validate:"required"`
}

type UserCreateRequest struct {
	Data UserCreateData `json:"data" validate:"required"`
}

// Update

type UserUpdateAttributes struct {
	Email       *string    `json:"email,omitempty" validate:"omitempty,email" example:"user@example.com"`
	FirstName   *string    `json:"first_name,omitempty" example:"John"`
	LastName    *string    `json:"last_name,omitempty" example:"Doe"`
	MobilePhone *string    `json:"mobile_phone,omitempty" example:"+628123456789"`
	Timezone    *string    `json:"timezone,omitempty" example:"Asia/Jakarta"`
	ImageUUID   NullString `json:"image_uuid,omitempty" swaggertype:"string" example:"018f3a5c-7a6f-7c2a-8d4a-4b5b1f6c8e90"`
}

// NullString allows PATCH semantics:
// - field omitted => Set=false (no change)
// - value null    => Set=true, Valid=false (clear value)
// - value string  => Set=true, Valid=true, Value=<string>
type NullString struct {
	Set   bool
	Valid bool
	Value string
}

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

type UserUpdateData struct {
	Type       string               `json:"type" validate:"required,oneof=user_update user" example:"user_update"`
	ID         string               `json:"id" example:"018f3a5c-7a6f-7c2a-8d4a-4b5b1f6c8e9d"`
	Attributes UserUpdateAttributes `json:"attributes" validate:"required"`
}

type UserUpdateRequest struct {
	Data UserUpdateData `json:"data" validate:"required"`
}
