/*
 * Copyright 2026 Oleg Borodin <onborodin@gmail.com>
 *
 * This work is published and licensed under a Creative Commons
 * Attribution-NonCommercial-NoDerivatives 4.0 International License.
 *
 * Distribution of this work is permitted, but commercial use and
 * modifications are strictly prohibited.
 */
package client

import (
	"context"
	"encoding/json"
	"fmt"

	"mstore/app/handler"
	"mstore/app/operator"
	"mstore/pkg/descr"
)

func (cli *Client) CreateGrantByAccountID(ctx context.Context, hosturi string, accountID, right, pattern string) (string, error) {
	var err error
	var res string

	apiuri, err := setApiPath(hosturi, "/v3/api/grant/create")
	if err != nil {
		return res, err
	}
	operParams := operator.CreateGrantParams{
		AccountID: accountID,
		Right:     right,
		Pattern:   pattern,
	}
	paramsJson, err := json.Marshal(operParams)
	if err != nil {
		return res, err
	}
	respBytes, err := doHTTPCall(ctx, cli.skipTLSVerify, apiuri, paramsJson)
	if err != nil {
		return res, err
	}

	operRes := handler.NewResponse[operator.CreateGrantResult]()
	err = json.Unmarshal(respBytes, operRes)
	if err != nil {
		return res, err
	}
	if operRes.Error {
		err = fmt.Errorf("%s", operRes.Message)
		return res, err
	}
	res = operRes.Result.GrantID
	return res, err
}

func (cli *Client) CreateGrantByUsername(ctx context.Context, hosturi, username string, right string, pattern string) (string, error) {
	var err error
	var res string

	apiuri, err := setApiPath(hosturi, "/v3/api/grant/create")
	if err != nil {
		return res, err
	}
	operParams := operator.CreateGrantParams{
		Username: username,
		Right:    right,
		Pattern:  pattern,
	}
	paramsJson, err := json.Marshal(operParams)
	if err != nil {
		return res, err
	}
	respBytes, err := doHTTPCall(ctx, cli.skipTLSVerify, apiuri, paramsJson)
	if err != nil {
		return res, err
	}

	operRes := handler.NewResponse[operator.CreateGrantResult]()
	err = json.Unmarshal(respBytes, operRes)
	if err != nil {
		return res, err
	}
	if operRes.Error {
		err = fmt.Errorf("%s", operRes.Message)
		return res, err
	}
	res = operRes.Result.GrantID
	return res, err
}

func (cli *Client) GetGrant(ctx context.Context, hosturi, grantID string) (*descr.Grant, error) {
	var err error
	res := &descr.Grant{}

	apipath, err := setApiPath(hosturi, "/v3/api/grant/get")
	if err != nil {
		return res, err
	}
	operParams := operator.GetGrantParams{
		GrantID: grantID,
	}
	paramsJson, err := json.Marshal(operParams)
	if err != nil {
		return res, err
	}
	respBytes, err := doHTTPCall(ctx, cli.skipTLSVerify, apipath, paramsJson)
	if err != nil {
		return res, err
	}

	operRes := handler.NewResponse[operator.GetGrantResult]()
	err = json.Unmarshal(respBytes, operRes)
	if err != nil {
		return res, err
	}
	if operRes.Error {
		err = fmt.Errorf("%s", operRes.Message)
		return res, err
	}
	res = operRes.Result.Grant
	return res, err
}

func (cli *Client) UpdateGrant(ctx context.Context, hosturi, grantID, newPattern string) error {
	var err error

	apipath, err := setApiPath(hosturi, "/v3/api/grant/update")
	if err != nil {
		return err
	}
	operParams := operator.UpdateGrantParams{
		GrantID:    grantID,
		NewPattern: newPattern,
	}
	paramsJson, err := json.Marshal(operParams)
	if err != nil {
		return err
	}
	respBytes, err := doHTTPCall(ctx, cli.skipTLSVerify, apipath, paramsJson)
	if err != nil {
		return err
	}
	operRes := handler.NewResponse[operator.UpdateGrantResult]()
	err = json.Unmarshal(respBytes, operRes)
	if err != nil {
		return err
	}
	if operRes.Error {
		err = fmt.Errorf("%s", operRes.Message)
		return err
	}
	return err
}

func (cli *Client) DeleteGrant(ctx context.Context, hosturi, grantID string) error {
	var err error

	apipath, err := setApiPath(hosturi, "/v3/api/grant/delete")
	if err != nil {
		return err
	}
	operParams := operator.DeleteGrantParams{
		GrantID: grantID,
	}
	paramsJson, err := json.Marshal(operParams)
	if err != nil {
		return err
	}
	respBytes, err := doHTTPCall(ctx, cli.skipTLSVerify, apipath, paramsJson)
	if err != nil {
		return err
	}

	operRes := handler.NewResponse[operator.DeleteGrantResult]()
	err = json.Unmarshal(respBytes, operRes)
	if err != nil {
		return err
	}
	if operRes.Error {
		err = fmt.Errorf("%s", operRes.Message)
		return err
	}
	return err
}

func (cli *Client) ListGrantsByAccountID(ctx context.Context, hosturi, accountID string) ([]descr.Grant, error) {
	var err error
	res := make([]descr.Grant, 0)

	apipath, err := setApiPath(hosturi, "/v3/api/grants/list")
	if err != nil {
		return res, err
	}
	operParams := operator.ListGrantsParams{
		AccountID: accountID,
	}
	paramsJson, err := json.Marshal(operParams)
	if err != nil {
		return res, err
	}
	respBytes, err := doHTTPCall(ctx, cli.skipTLSVerify, apipath, paramsJson)
	if err != nil {
		return res, err
	}

	operRes := handler.NewResponse[operator.ListGrantsResult]()
	err = json.Unmarshal(respBytes, operRes)
	if err != nil {
		return res, err
	}
	if operRes.Error {
		err = fmt.Errorf("%s", operRes.Message)
		return res, err
	}
	res = operRes.Result.Grants
	return res, err
}

func (cli *Client) ListGrantsByUsername(ctx context.Context, hosturi, username string) ([]descr.Grant, error) {
	var err error
	res := make([]descr.Grant, 0)

	apipath, err := setApiPath(hosturi, "/v3/api/grants/list")
	if err != nil {
		return res, err
	}
	operParams := operator.ListGrantsParams{
		Username: username,
	}
	paramsJson, err := json.Marshal(operParams)
	if err != nil {
		return res, err
	}
	respBytes, err := doHTTPCall(ctx, cli.skipTLSVerify, apipath, paramsJson)
	if err != nil {
		return res, err
	}

	operRes := handler.NewResponse[operator.ListGrantsResult]()
	err = json.Unmarshal(respBytes, operRes)
	if err != nil {
		return res, err
	}
	if operRes.Error {
		err = fmt.Errorf("%s", operRes.Message)
		return res, err
	}
	res = operRes.Result.Grants
	return res, err
}
