package meta

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

// BackfillImportResult Z9e 扫库补齐 import/export 的结果。
type BackfillImportResult struct {
	Scanned int      `json:"scanned"`
	Updated int      `json:"updated"`
	Skipped int      `json:"skipped"`
	DryRun  bool     `json:"dry_run"`
	Slugs   []string `json:"updated_slugs,omitempty"`
	Message string   `json:"message,omitempty"`
}

// PublishedLister 列出全部已发布应用（跨租户，供 Z9e 启动扫库）。
type PublishedLister interface {
	ListPublishedApps(ctx context.Context) ([]*AppRecord, error)
}

// BackfillDefaultImportExport 遍历已发布蓝图，对可写 resource 补齐 import/export 并落库（Z9e）。
// dryRun=true 只统计不写库。tenantID>0 时仅处理该租户。
func BackfillDefaultImportExport(ctx context.Context, store Store, dryRun bool) (*BackfillImportResult, error) {
	return BackfillDefaultImportExportForTenant(ctx, store, 0, dryRun)
}

// BackfillDefaultImportExportForTenant 同 BackfillDefaultImportExport；tenantID=0 表示全库。
func BackfillDefaultImportExportForTenant(ctx context.Context, store Store, tenantID int64, dryRun bool) (*BackfillImportResult, error) {
	if store == nil {
		return nil, fmt.Errorf("meta store nil")
	}
	lister, ok := store.(PublishedLister)
	if !ok {
		return nil, fmt.Errorf("meta store does not support ListPublishedApps")
	}
	apps, err := lister.ListPublishedApps(ctx)
	if err != nil {
		return nil, err
	}
	out := &BackfillImportResult{DryRun: dryRun, Slugs: make([]string, 0)}
	for _, app := range apps {
		if app == nil || app.Blueprint == nil {
			continue
		}
		if tenantID > 0 && app.TenantID != tenantID {
			continue
		}
		out.Scanned++
		before, _ := json.Marshal(app.Blueprint)
		app.Blueprint.EnsureDefaultImportExport()
		after, _ := json.Marshal(app.Blueprint)
		if string(before) == string(after) {
			out.Skipped++
			continue
		}
		out.Updated++
		out.Slugs = append(out.Slugs, fmt.Sprintf("%d/%s", app.TenantID, app.Slug))
		if dryRun {
			continue
		}
		if err := store.Save(ctx, app); err != nil {
			return out, fmt.Errorf("save %s: %w", app.Slug, err)
		}
	}
	out.Message = fmt.Sprintf("scanned=%d updated=%d skipped=%d dry_run=%v", out.Scanned, out.Updated, out.Skipped, dryRun)
	return out, nil
}

// RunBackfillDefaultImportExportOnBoot 启动时扫库（失败只打日志，不阻断启动）。
func RunBackfillDefaultImportExportOnBoot(ctx context.Context, store Store) {
	res, err := BackfillDefaultImportExport(ctx, store, false)
	if err != nil {
		log.Printf("Z9e backfill import ops: %v", err)
		return
	}
	if res != nil && res.Updated > 0 {
		log.Printf("Z9e backfill import ops: %s slugs=%v", res.Message, res.Slugs)
	} else if res != nil {
		log.Printf("Z9e backfill import ops: %s", res.Message)
	}
}
