package grafanabackuper

import (
	"context"
	"fmt"
	"io"

	"git.ar21.de/yolokube/grafana-backuper/internal/config"
	"git.ar21.de/yolokube/grafana-backuper/pkg/grafana"
)

type RestoreClient struct {
	client *Client
}

func (r *RestoreClient) Start(ctx context.Context, cfg *config.Config) error {
	files, err := r.client.git.ListJSONFiles("./")
	if err != nil {
		return err
	}
	r.client.logger.Debug().Int("files", len(files)).Msg("Collected all files")

	for _, filename := range files {
		r.client.logger.Debug().Str("file", filename).Msg("Reading data")
		var data []byte
		data, err = r.client.git.ReadFile(filename)
		if err != nil {
			return err
		}

		r.client.logger.Debug().Msg("Parsing raw dashboard data")
		var dashboard *grafana.Dashboard
		dashboard, err = r.client.grafana.Dashboard.ParseRaw(data)
		if err != nil {
			return err
		}

		content, ok := dashboard.Dashboard.(map[string]any)
		if !ok {
			continue
		}

		uid := fmt.Sprint(content["uid"])
		title := fmt.Sprint(content["title"])

		r.client.logger.Debug().
			Str("dashboard-uid", uid).
			Str("title", title).
			Msg("Fetching current dashboard version from Grafana")
		var current *grafana.Dashboard
		current, _, err = r.client.grafana.Dashboard.Get(ctx, uid)
		if err != nil {
			return err
		}

		if current.Version == dashboard.Version && !cfg.ForceCommits {
			r.client.logger.Info().
				Any("dashboard-uid", uid).
				Str("folder", dashboard.FolderTitle).
				Str("dashboard", title).
				Msg("Dashboard already up to date")
			continue
		}

		r.client.logger.Debug().Str("dashboard-uid", uid).Str("title", title).Msg("Syncing dashboard with Grafana")
		var createResp *grafana.DashboardCreateResponse
		createResp, err = r.syncDashboard(ctx, dashboard, cfg.ForceCommits)
		if err != nil {
			return err
		}

		r.client.logger.Info().Any("resp", createResp).Msg("Created / Updated dashboard successfully")
	}

	return nil
}

func (r *RestoreClient) syncDashboard(
	ctx context.Context,
	d *grafana.Dashboard,
	force bool,
) (*grafana.DashboardCreateResponse, error) {
	createOpts := grafana.DashboardCreateOpts{
		Dashboard: d.Dashboard,
		FolderUID: d.FolderUID,
		Message:   "sync git repository to grafana",
		Overwrite: force,
	}

	r.client.logger.Debug().Msg("Validating create options")
	if err := createOpts.Validate(); err != nil {
		return nil, err
	}

	createResp, resp, err := r.client.grafana.Dashboard.Create(ctx, createOpts)
	if err != nil {
		body, _ := io.ReadAll(resp.Body)
		r.client.logger.Debug().Str("resp", string(body)).Msg("Got error during dashboard creation / update")
		return nil, err
	}

	return createResp, nil
}