package pocketbase

import (
	"encoding/json"

	"clio/internal/fetcher_router"

	"github.com/pocketbase/pocketbase/core"
	"github.com/pocketbase/pocketbase/tools/types"
)

// Store manages FetcherRouter records in PocketBase.
type Store struct {
	app core.App
}

// New creates a new PocketBase store for fetcher_router.
func New(app core.App) *Store {
	return &Store{app: app}
}

// Get retrieves a fetcher_router by ID from PocketBase.
func (s *Store) Get(id string) (*fetcher_router.FetcherRouter, error) {
	record, err := s.app.FindRecordById("fetcher_router", id)
	if err != nil {
		return nil, err
	}

	created := record.GetDateTime("created")
	updated := record.GetDateTime("updated")

	fr := &fetcher_router.FetcherRouter{
		ID:      record.Id,
		Domain:  record.GetString("domain"),
		Fetcher: record.GetString("fetcher"),
		Created: created.Time(),
		Updated: updated.Time(),
	}

	// Unmarshal fetcher_config JSON
	if configRaw := record.Get("fetcher_config"); configRaw != nil {
		switch v := configRaw.(type) {
		case types.JSONRaw:
			json.Unmarshal(v, &fr.FetcherConfig)
		case string:
			if v != "" {
				json.Unmarshal([]byte(v), &fr.FetcherConfig)
			}
		}
	}

	return fr, nil
}

// GetByDomain retrieves a fetcher_router by domain from PocketBase.
// Falls back to "*" catch-all domain if no exact match is found.
func (s *Store) GetByDomain(domain string) (*fetcher_router.FetcherRouter, error) {
	// Try exact match first
	record, err := s.app.FindFirstRecordByFilter(
		"fetcher_router",
		"domain = {:domain}",
		map[string]any{"domain": domain},
	)

	// If not found, try catch-all
	if err != nil {
		record, err = s.app.FindFirstRecordByFilter(
			"fetcher_router",
			"domain = {:domain}",
			map[string]any{"domain": "*"},
		)
		if err != nil {
			return nil, err
		}
	}

	created := record.GetDateTime("created")
	updated := record.GetDateTime("updated")

	fr := &fetcher_router.FetcherRouter{
		ID:      record.Id,
		Domain:  record.GetString("domain"),
		Fetcher: record.GetString("fetcher"),
		Created: created.Time(),
		Updated: updated.Time(),
	}

	// Unmarshal fetcher_config JSON
	if configRaw := record.Get("fetcher_config"); configRaw != nil {
		switch v := configRaw.(type) {
		case types.JSONRaw:
			json.Unmarshal(v, &fr.FetcherConfig)
		case string:
			if v != "" {
				json.Unmarshal([]byte(v), &fr.FetcherConfig)
			}
		}
	}

	return fr, nil
}

// Save persists a fetcher_router to PocketBase.
func (s *Store) Save(fr *fetcher_router.FetcherRouter) error {
	var pbRecord *core.Record
	var err error

	if fr.ID != "" {
		pbRecord, err = s.app.FindRecordById("fetcher_router", fr.ID)
		if err != nil {
			// Create new record with provided ID
			collection, err := s.app.FindCollectionByNameOrId("fetcher_router")
			if err != nil {
				return err
			}
			pbRecord = core.NewRecord(collection)
			pbRecord.Set("id", fr.ID)
		}
	} else {
		// Create new record with auto-generated ID
		collection, err := s.app.FindCollectionByNameOrId("fetcher_router")
		if err != nil {
			return err
		}
		pbRecord = core.NewRecord(collection)
	}

	pbRecord.Set("domain", fr.Domain)
	pbRecord.Set("fetcher", fr.Fetcher)

	configJSON, _ := json.Marshal(fr.FetcherConfig)
	pbRecord.Set("fetcher_config", string(configJSON))

	return s.app.Save(pbRecord)
}

// Delete removes a fetcher_router from PocketBase.
func (s *Store) Delete(id string) error {
	record, err := s.app.FindRecordById("fetcher_router", id)
	if err != nil {
		return err
	}

	return s.app.Delete(record)
}
