package control

import (
	"context"
	"database/sql"
	"encoding/json"
	"time"
)

type OperationTaskView struct {
	OperationTask
	Collection   CollectionState `json:"collection"`
	LatestRun    *ProviderRun    `json:"latest_run,omitempty"`
	LatestJobRun *ProviderRun    `json:"latest_job_run,omitempty"`
	CRMTables    []CRMTableView  `json:"crm_tables,omitempty"`
}

func taskProvider(key string) string {
	switch key {
	case "ar_sync":
		return "fivetran"
	case "dbt_billing":
		return "dbt"
	case "crm_extract":
		return "crm_extract"
	case "crm_load":
		return "crm_load"
	case "salesforce_org", "salesforce_account", "salesforce_order":
		return "finance"
	default:
		return "finance_runtime"
	}
}

func (o *Operations) TaskViews(ctx context.Context, now time.Time) ([]OperationTaskView, error) {
	items := []OperationTaskView{}
	for _, task := range OperationCatalog() {
		provider := taskProvider(task.Key)
		state := CollectionState{Provider: provider, Status: "unconfigured", Message: "尚无已采集的来源状态"}
		var payload string
		err := o.db.QueryRowContext(ctx, "SELECT payload FROM checkpoints WHERE provider=?", provider).Scan(&payload)
		if err != nil && err != sql.ErrNoRows {
			return nil, err
		}
		if err == nil {
			if err = json.Unmarshal([]byte(payload), &state); err != nil {
				return nil, err
			}
			if state.ObservedAt.IsZero() || now.Sub(state.ObservedAt) > 3*time.Minute {
				state.Status = "unknown"
				state.Message = "采集状态已过期；下方保留历史执行，不代表当前运行状态"
			}
		}
		task.Coverage = state.Status
		state.Cursor = ""
		view := OperationTaskView{OperationTask: task, Collection: state}
		runs, err := o.Runs(ctx, RunFilter{Task: task.Key, Provider: provider, Limit: 1})
		if err != nil {
			return nil, err
		}
		if len(runs) > 0 {
			view.LatestRun = &runs[0]
		}
		separateCRMExtractDiagnostic(&view)
		if task.Key == "crm_load" {
			view.CRMTables, err = o.crmTableViews(ctx)
			if err != nil {
				return nil, err
			}
			runs, err := o.Runs(ctx, RunFilter{Task: task.Key, Provider: "crm_load_job", Limit: 1})
			if err != nil {
				return nil, err
			}
			if len(runs) > 0 {
				view.LatestJobRun = &runs[0]
			}
		}
		items = append(items, view)
	}
	return items, nil
}
