package oauth2

import (
	"errors"
	"strconv"
)

type DeviceAuthorizationRequest struct {
	ClientID string `form:"client_id" json:"client_id"`
}

func (r *DeviceAuthorizationRequest) Validate() error {
	if r.ClientID == "" {
		return errors.New("client_id is required")
	}
	return nil
}

// https://datatracker.ietf.org/doc/html/rfc8628#section-3.2
type DeviceAuthorizationResponse struct {
	DeviceCode              string `json:"device_code"`
	UserCode                string `json:"user_code"`
	VerificationURI         string `json:"verification_uri"`
	VerificationURIComplete string `json:"verification_uri_complete"`
	ExpiresIn               int    `json:"expires_in"`
	Interval                int    `json:"interval"`
}

type InnerDeviceCheckRequest struct {
	UserCode string `json:"user_code"`
}

func (r *InnerDeviceCheckRequest) Validate() error {
	if r.UserCode == "" {
		return errors.New("user_code is required")
	}
	return nil
}

type InnerDeviceCheckResponse struct {
	InnerBasicResponse
	Data struct {
		IP        string `json:"ip"`
		UserAgent string `json:"user_agent"`
		CreatedAt string `json:"created_at"`
	} `json:"data"`
}

type Action string

const (
	ActionApprove Action = "approve"
	ActionDeny    Action = "deny"
)

type InnerDeviceConfirmRequest struct {
	UserCode string `json:"user_code"`
	Action   Action `json:"action"`
	// Accept OrgId as a string to prevent overflow in the frontend.
	OrgId string `json:"org_id"`

	parsedOrgId uint64
}

func (r *InnerDeviceConfirmRequest) Validate() error {
	if r.UserCode == "" {
		return errors.New("user_code is required")
	}
	if r.Action == "" {
		return errors.New("action is required")
	}
	if r.Action != ActionApprove && r.Action != ActionDeny {
		return errors.New("action must be approve or deny")
	}
	if r.Action == ActionApprove && r.OrgId == "" {
		return errors.New("org_id is required when action is approve")
	}

	parseOrgId, err := strconv.ParseUint(r.OrgId, 10, 64)
	if err != nil {
		return errors.New("org_id is invalid")
	}
	r.parsedOrgId = parseOrgId
	return nil
}

func (r *InnerDeviceConfirmRequest) GetParsedOrgId() uint64 {
	return r.parsedOrgId
}
