package tmi

import (
	"bytes"
	"encoding/json"
	"fmt"
	"net/http"
	"net/url"

	"context"

	"code.justin.tv/foundation/twitchclient"
)

// UpdateInternalRoomPropertiesRequest is the request params for UpdateInternalRoomProperties.
type UpdateInternalRoomPropertiesRequest struct {
	RequesterID                *string                   `json:"requesting_user_id"`
	ChatDelayDuration          *int                      `json:"chat_delay_duration"`
	ChatEmoteOnly              *bool                     `json:"chat_emote_only"`
	ChatFastsubs               *bool                     `json:"chat_fastsubs"`
	ChatRequireVerifiedAccount *bool                     `json:"chat_require_verified_account"`
	ChatRules                  []string                  `json:"chat_rules"`
	HideChatLinks              *bool                     `json:"hide_chat_links"`
	R9kOnlyChat                *bool                     `json:"r9k_only_chat"`
	RitualsEnabled             *bool                     `json:"rituals_enabled"`
	SubscribersOnlyChat        *bool                     `json:"subscribers_only_chat"`
	SubOnlyModeMinTier         *string                   `json:"sub_only_mode_min_tier"`
	WatchPartyOnlyChat         *bool                     `json:"watch_party_only_chat"`
	AutoModProperties          *ChannelAutoModProperties `json:"automod_properties"`
	SlowModeDuration           *int                      `json:"slow_mode_duration"`
	FollowersOnlyDuration      *int                      `json:"followers_only_duration"` // this value is in minutes
}

func (c *clientImpl) UpdateInternalRoomProperties(ctx context.Context, channelID string, params UpdateInternalRoomPropertiesRequest, reqOpts *twitchclient.ReqOpts) error {
	path := fmt.Sprintf("/rooms/%s", url.QueryEscape(channelID))

	bodyBytes, err := json.Marshal(params)
	if err != nil {
		return err
	}

	req, err := c.NewRequest("PUT", path, bytes.NewReader(bodyBytes))
	if err != nil {
		return err
	}

	combinedReqOpts := twitchclient.MergeReqOpts(reqOpts, twitchclient.ReqOpts{
		StatName:       "service.clue.update_internal_room_properties",
		StatSampleRate: defaultStatSampleRate,
	})
	resp, err := c.Do(ctx, req, combinedReqOpts)
	if err != nil {
		return err
	}

	defer closeBody(resp)

	if resp.StatusCode != http.StatusOK {
		return NewHTTPError(nil, resp.StatusCode)
	}
	return nil
}

func (c *clientImpl) UpdateInternalRoomPropertiesAuthed(ctx context.Context, channelID, requesterID string, params UpdateInternalRoomPropertiesRequest, reqOpts *twitchclient.ReqOpts) error {
	path := fmt.Sprintf("/rooms/%s/%s", url.QueryEscape(channelID), url.QueryEscape(requesterID))

	bodyBytes, err := json.Marshal(params)
	if err != nil {
		return err
	}

	req, err := c.NewRequest("PUT", path, bytes.NewReader(bodyBytes))
	if err != nil {
		return err
	}

	combinedReqOpts := twitchclient.MergeReqOpts(reqOpts, twitchclient.ReqOpts{
		StatName:       "service.clue.update_internal_room_properties_authed",
		StatSampleRate: defaultStatSampleRate,
	})
	resp, err := c.Do(ctx, req, combinedReqOpts)
	if err != nil {
		return err
	}

	defer closeBody(resp)

	if resp.StatusCode != http.StatusOK {
		return NewHTTPError(nil, resp.StatusCode)
	}
	return nil
}
