package tmi

import (
	"bytes"
	"encoding/json"
	"errors"
	"fmt"
	"net/http"
	"strconv"

	"context"

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

func (c *clientImpl) GetAutoModRejectedMessage(ctx context.Context, msgID string, reqOpts *twitchclient.ReqOpts) (AutoModRejectedMessage, bool, error) {
	path := fmt.Sprintf("/automod/v1/rejected_messages/%s", msgID)
	req, err := c.NewRequest("GET", path, nil)
	if err != nil {
		return AutoModRejectedMessage{}, false, err
	}

	combinedReqOpts := twitchclient.MergeReqOpts(reqOpts, twitchclient.ReqOpts{
		StatName:       "service.clue.automod_rejected_message",
		StatSampleRate: defaultStatSampleRate,
	})

	resp, err := c.Do(ctx, req, combinedReqOpts)
	if err != nil {
		return AutoModRejectedMessage{}, false, err
	}

	defer closeBody(resp)

	if resp.StatusCode == http.StatusNotFound {
		return AutoModRejectedMessage{}, false, nil
	} else if resp.StatusCode != http.StatusOK {
		return AutoModRejectedMessage{}, false, fmt.Errorf("unexpected response code %d during call to GetAutoModRejectedMessage", resp.StatusCode)
	}

	var decoded AutoModRejectedMessage
	if err := json.NewDecoder(resp.Body).Decode(&decoded); err != nil {
		return AutoModRejectedMessage{}, false, err
	}
	return decoded, true, nil
}

var ErrMessageNotFound = errors.New("message not found")
var ErrMessageAlreadyProcessed = errors.New("message already processed")
var ErrAutoModRejectedForbidden = errors.New("requesting user must be moderator of room")

func (c *clientImpl) ApproveAutoModRejected(ctx context.Context, msgID, requesterUserID string, reqOpts *twitchclient.ReqOpts) error {
	url := "/automod/v1/approve"

	numericalRequesterUserID, err := strconv.Atoi(requesterUserID)
	if err != nil {
		return fmt.Errorf("user id must be an integer. had %s", requesterUserID)
	}

	params := ApproveAutoModRejectedParams{
		MsgID:           msgID,
		RequesterUserID: numericalRequesterUserID,
	}

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

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

	combinedReqOpts := twitchclient.MergeReqOpts(reqOpts, twitchclient.ReqOpts{
		StatName:       "service.clue.approve_automod_rejected",
		StatSampleRate: defaultStatSampleRate,
	})

	resp, err := c.Do(ctx, req, combinedReqOpts)
	if err != nil {
		return err
	}

	defer closeBody(resp)

	if resp.StatusCode == http.StatusNotFound {
		return ErrMessageNotFound
	} else if resp.StatusCode == http.StatusForbidden {
		return ErrAutoModRejectedForbidden
	} else if resp.StatusCode == http.StatusBadRequest {
		return ErrMessageAlreadyProcessed
	} else if resp.StatusCode != http.StatusOK {
		return fmt.Errorf("unexpected response code %d during call to ApproveAutoModRejected", resp.StatusCode)
	}

	var decoded SendMessageResponse
	return json.NewDecoder(resp.Body).Decode(&decoded)
}

func (c *clientImpl) DenyAutoModRejected(ctx context.Context, msgID, requesterUserID string, reqOpts *twitchclient.ReqOpts) error {
	url := "/automod/v1/deny"

	numericalRequesterUserID, err := strconv.Atoi(requesterUserID)
	if err != nil {
		return fmt.Errorf("user id must be an integer. had %s", requesterUserID)
	}

	params := ApproveAutoModRejectedParams{
		MsgID:           msgID,
		RequesterUserID: numericalRequesterUserID,
	}

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

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

	combinedReqOpts := twitchclient.MergeReqOpts(reqOpts, twitchclient.ReqOpts{
		StatName:       "service.clue.deny_automod_rejected",
		StatSampleRate: defaultStatSampleRate,
	})

	resp, err := c.Do(ctx, req, combinedReqOpts)
	if err != nil {
		return err
	}

	defer closeBody(resp)

	if resp.StatusCode == http.StatusNotFound {
		return ErrMessageNotFound
	} else if resp.StatusCode == http.StatusForbidden {
		return ErrAutoModRejectedForbidden
	} else if resp.StatusCode == http.StatusBadRequest {
		return ErrMessageAlreadyProcessed
	} else if resp.StatusCode != http.StatusOK {
		return fmt.Errorf("unexpected response code %d during call to DenyAutoModRejected", resp.StatusCode)
	}

	var decoded SendMessageResponse
	return json.NewDecoder(resp.Body).Decode(&decoded)
}
