package services

import (
	"context"
	"fmt"

	"api-service/internal/models/reference"
)

// VClaimAdapter adapts the generic VClaimService to implement the reference.VClaimService interface
type VClaimAdapter struct {
	service VClaimService
}

// NewVClaimAdapter creates a new VClaimAdapter
func NewVClaimAdapter(service VClaimService) *VClaimAdapter {
	return &VClaimAdapter{
		service: service,
	}
}

// Get implements VClaimService.Get
func (a *VClaimAdapter) Get(ctx context.Context, endpoint string, result interface{}) error {
	return a.service.Get(ctx, endpoint, result)
}

// Post implements VClaimService.Post
func (a *VClaimAdapter) Post(ctx context.Context, endpoint string, payload interface{}, result interface{}) error {
	return a.service.Post(ctx, endpoint, payload, result)
}

// Put implements VClaimService.Put
func (a *VClaimAdapter) Put(ctx context.Context, endpoint string, payload interface{}, result interface{}) error {
	return a.service.Put(ctx, endpoint, payload, result)
}

// Delete implements VClaimService.Delete
func (a *VClaimAdapter) Delete(ctx context.Context, endpoint string, result interface{}) error {
	return a.service.Delete(ctx, endpoint, result)
}

// GetRawResponse implements VClaimService.GetRawResponse
func (a *VClaimAdapter) GetRawResponse(ctx context.Context, endpoint string) (*ResponDTOVclaim, error) {
	return a.service.GetRawResponse(ctx, endpoint)
}

// PostRawResponse implements VClaimService.PostRawResponse
func (a *VClaimAdapter) PostRawResponse(ctx context.Context, endpoint string, payload interface{}) (*ResponDTOVclaim, error) {
	return a.service.PostRawResponse(ctx, endpoint, payload)
}

// GetPeserta implements reference.VClaimService.GetPeserta
func (a *VClaimAdapter) GetPeserta(ctx context.Context, noKartu string) (*reference.PesertaData, error) {
	var response struct {
		MetaData struct {
			Code    string `json:"code"`
			Message string `json:"message"`
		} `json:"metaData"`
		Response reference.PesertaData `json:"response"`
	}

	endpoint := fmt.Sprintf("/Peserta/%s", noKartu)
	err := a.service.Get(ctx, endpoint, &response)
	if err != nil {
		return nil, err
	}

	if response.MetaData.Code != "200" {
		return nil, fmt.Errorf("BPJS API error: %s - %s", response.MetaData.Code, response.MetaData.Message)
	}

	return &response.Response, nil
}

// GetSEP implements reference.VClaimService.GetSEP
func (a *VClaimAdapter) GetSEP(ctx context.Context, noSep string) (*reference.SEPData, error) {
	var response struct {
		MetaData struct {
			Code    string `json:"code"`
			Message string `json:"message"`
		} `json:"metaData"`
		Response reference.SEPData `json:"response"`
	}

	endpoint := fmt.Sprintf("/SEP/%s", noSep)
	err := a.service.Get(ctx, endpoint, &response)
	if err != nil {
		return nil, err
	}

	if response.MetaData.Code != "200" {
		return nil, fmt.Errorf("BPJS API error: %s - %s", response.MetaData.Code, response.MetaData.Message)
	}

	return &response.Response, nil
}

// CreateSEP implements reference.VClaimService.CreateSEP
func (a *VClaimAdapter) CreateSEP(ctx context.Context, req *reference.SEPRequest) (*reference.SEPData, error) {
	var response struct {
		MetaData struct {
			Code    string `json:"code"`
			Message string `json:"message"`
		} `json:"metaData"`
		Response reference.SEPData `json:"response"`
	}

	endpoint := "/SEP/2.0/insert"
	err := a.service.Post(ctx, endpoint, req, &response)
	if err != nil {
		return nil, err
	}

	if response.MetaData.Code != "200" {
		return nil, fmt.Errorf("BPJS API error: %s - %s", response.MetaData.Code, response.MetaData.Message)
	}

	return &response.Response, nil
}

// UpdateSEP implements reference.VClaimService.UpdateSEP
func (a *VClaimAdapter) UpdateSEP(ctx context.Context, noSep string, req *reference.SEPRequest) (*reference.SEPData, error) {
	var response struct {
		MetaData struct {
			Code    string `json:"code"`
			Message string `json:"message"`
		} `json:"metaData"`
		Response reference.SEPData `json:"response"`
	}

	endpoint := fmt.Sprintf("/SEP/%s", noSep)
	err := a.service.Put(ctx, endpoint, req, &response)
	if err != nil {
		return nil, err
	}

	if response.MetaData.Code != "200" {
		return nil, fmt.Errorf("BPJS API error: %s - %s", response.MetaData.Code, response.MetaData.Message)
	}

	return &response.Response, nil
}

// DeleteSEP implements reference.VClaimService.DeleteSEP
func (a *VClaimAdapter) DeleteSEP(ctx context.Context, noSep string) error {
	var response struct {
		MetaData struct {
			Code    string `json:"code"`
			Message string `json:"message"`
		} `json:"metaData"`
	}

	endpoint := fmt.Sprintf("/SEP/%s", noSep)
	err := a.service.Delete(ctx, endpoint, &response)
	if err != nil {
		return err
	}

	if response.MetaData.Code != "200" {
		return fmt.Errorf("BPJS API error: %s - %s", response.MetaData.Code, response.MetaData.Message)
	}

	return nil
}

// GetRujukan implements reference.VClaimService.GetRujukan
func (a *VClaimAdapter) GetRujukan(ctx context.Context, noRujukan string) (*reference.RujukanData, error) {
	var response struct {
		MetaData struct {
			Code    string `json:"code"`
			Message string `json:"message"`
		} `json:"metaData"`
		Response reference.RujukanData `json:"response"`
	}

	endpoint := fmt.Sprintf("/Rujukan/%s", noRujukan)
	err := a.service.Get(ctx, endpoint, &response)
	if err != nil {
		return nil, err
	}

	if response.MetaData.Code != "200" {
		return nil, fmt.Errorf("BPJS API error: %s - %s", response.MetaData.Code, response.MetaData.Message)
	}

	return &response.Response, nil
}
