package model

import (
	"crawler/config"
	"crawler/service"
	"encoding/json"
	"fmt"

	"github.com/google/go-querystring/query"
)

type Kobis struct {
	Rest service.Rest
}

// KOBIS 오류 응답 (HTTP 200으로 반환되므로 body 검사 필수)
type KobisFault struct {
	FaultInfo *struct {
		Message   string `json:"message"`
		ErrorCode string `json:"errorCode"`
	} `json:"faultInfo"`
}

// KOBIS faultInfo 응답 확인 (무효 키, 쿼터 초과 등)
func (this *Kobis) checkFault(data []byte) error {
	var fault KobisFault
	if json.Unmarshal(data, &fault) == nil && fault.FaultInfo != nil {
		err := fmt.Errorf("KOBIS fault %s: %s", fault.FaultInfo.ErrorCode, fault.FaultInfo.Message)
		this.Rest.Check(err)
		return err
	}
	return nil
}

func (this *Kobis) MovieDailyBoxOfficeListAPI(req SearchDailyBoxOfficeParams) (SearchDailyBoxOfficeList, error) {
	var (
		url      = config.MOVIE_DAILY_BOX_OFFICE_LIST
		query, _ = query.Values(req)
		result   SearchDailyBoxOfficeList
	)

	if query.Encode() != "" {
		url += "?" + query.Encode()
	}

	data, err := this.Rest.CallRestGetAPI(url)
	if this.Rest.Check(err) {
		return result, err
	}

	if err := this.checkFault(data); err != nil {
		return result, err
	}

	err = json.Unmarshal(data, &result)
	if this.Rest.Check(err) {
		return result, err
	}

	return result, nil
}

func (this *Kobis) MovieWeeklyBoxOfficeListAPI(req SearchWeeklyBoxOfficeParams) (SearchWeeklyBoxOfficeList, error) {
	var (
		url      = config.MOVIE_WEEK_BOX_OFFICE_LIST
		query, _ = query.Values(req)
		result   SearchWeeklyBoxOfficeList
	)

	if query.Encode() != "" {
		url += "?" + query.Encode()
	}

	data, err := this.Rest.CallRestGetAPI(url)
	if this.Rest.Check(err) {
		return result, err
	}

	if err := this.checkFault(data); err != nil {
		return result, err
	}

	err = json.Unmarshal(data, &result)
	if this.Rest.Check(err) {
		return result, err
	}

	return result, nil
}

func (this *Kobis) MovieListAPI(req SearchMovieListParams) (SearchMovieList, error) {
	var (
		url      = config.MOVIE_LIST
		query, _ = query.Values(req)
		result   SearchMovieList
	)

	if query.Encode() != "" {
		url += "?" + query.Encode()
	}

	data, err := this.Rest.CallRestGetAPI(url)
	if this.Rest.Check(err) {
		return result, err
	}

	if err := this.checkFault(data); err != nil {
		return result, err
	}

	err = json.Unmarshal(data, &result)
	if this.Rest.Check(err) {
		return result, err
	}

	return result, nil
}

func (this *Kobis) MovieInfoAPI(req SearchMovieInfoParams) (SearchMovieInfo, error) {
	var (
		url      = config.MOVIE_INFO
		query, _ = query.Values(req)
		result   SearchMovieInfo
	)

	if query.Encode() != "" {
		url += "?" + query.Encode()
	}

	data, err := this.Rest.CallRestGetAPI(url)
	if this.Rest.Check(err) {
		return result, err
	}

	if err := this.checkFault(data); err != nil {
		return result, err
	}

	err = json.Unmarshal(data, &result)
	if this.Rest.Check(err) {
		return result, err
	}

	return result, nil
}

func (this *Kobis) CompanyListAPI(req SearchCompanyListParams) (SearchCompanyList, error) {
	var (
		url      = config.COMPANY_LIST
		query, _ = query.Values(req)
		result   SearchCompanyList
	)

	if query.Encode() != "" {
		url += "?" + query.Encode()
	}

	data, err := this.Rest.CallRestGetAPI(url)
	if this.Rest.Check(err) {
		return result, err
	}

	if err := this.checkFault(data); err != nil {
		return result, err
	}

	err = json.Unmarshal(data, &result)
	if this.Rest.Check(err) {
		return result, err
	}

	return result, nil
}

func (this *Kobis) CompanyInfoAPI(req SearchCompanyInfoParams) (SearchCompanyInfo, error) {
	var (
		url      = config.COMPANY_INFO
		query, _ = query.Values(req)
		result   SearchCompanyInfo
	)

	if query.Encode() != "" {
		url += "?" + query.Encode()
	}

	data, err := this.Rest.CallRestGetAPI(url)
	if this.Rest.Check(err) {
		return result, err
	}

	if err := this.checkFault(data); err != nil {
		return result, err
	}

	err = json.Unmarshal(data, &result)
	if this.Rest.Check(err) {
		return result, err
	}

	return result, nil
}

func (this *Kobis) MovieBoxOfficeAPI(req SearchBoxOfficeParams) (SearchBoxOfficeList, error) {
	var (
		url      = config.MOVIE_BOX_OFFICE_STATS
		query, _ = query.Values(req)
		result   SearchBoxOfficeList
	)

	if query.Encode() != "" {
		url += "?" + query.Encode()
	}

	data, err := this.Rest.CallRestGetAPI(url)
	if this.Rest.Check(err) {
		return result, err
	}

	if err := this.checkFault(data); err != nil {
		return result, err
	}

	err = json.Unmarshal(data, &result)
	if this.Rest.Check(err) {
		return result, err
	}

	return result, nil
}
