package sync

import "log"

type LocatorSource string

const (
	LocatorSourceKOReader LocatorSource = "koreader"
	LocatorSourceKobo     LocatorSource = "kobo"
	LocatorSourceWeb      LocatorSource = "web"
)

type CanonicalLocator struct {
	CFI        string
	Precision  string
	Percentage float64
}

type DeviceLocator struct {
	Position   string
	Precision  string
	Percentage float64
}

func isConvertible(formatGroup string) bool {
	return formatGroup == string(FormatGroupReflowable)
}

func ConvertToCanonical(
	source LocatorSource,
	devicePos string,
	percentage float64,
	contextText string,
	formatGroup string,
	epubPath string,
	kepubPath string,
) CanonicalLocator {
	if !isConvertible(formatGroup) || epubPath == "" {
		return CanonicalLocator{
			CFI:        devicePos,
			Precision:  "passthrough",
			Percentage: percentage,
		}
	}

	switch source {
	case LocatorSourceKOReader:
		if !IsCREXPointer(devicePos) {
			return CanonicalLocator{CFI: devicePos, Precision: "already-standard", Percentage: percentage}
		}
		converter := NewCFIConverter(epubPath)
		result, err := converter.ConvertCREToStandard(devicePos, percentage, contextText)
		if err != nil || result == nil {
			log.Printf("Bookhoard: locator CRE→CFI conversion failed: %v", err)
			return CanonicalLocator{CFI: devicePos, Precision: "fallback", Percentage: percentage}
		}
		if result.EPUBCFI != "" {
			return CanonicalLocator{CFI: result.EPUBCFI, Precision: result.Precision, Percentage: result.Percentage}
		}
		if result.Href != "" {
			return CanonicalLocator{CFI: result.Href, Precision: result.Precision, Percentage: result.Percentage}
		}
		return CanonicalLocator{CFI: devicePos, Precision: result.Precision, Percentage: percentage}

	case LocatorSourceKobo:
		if kepubPath == "" {
			return CanonicalLocator{CFI: devicePos, Precision: "no-kepub", Percentage: percentage}
		}
		converter := NewKEPUBCFIConverter(epubPath, kepubPath)
		result, err := converter.ConvertKEPUBCFIToStandard(devicePos, percentage, contextText)
		if err != nil || result == nil {
			log.Printf("Bookhoard: locator KEPUB→CFI conversion failed: %v", err)
			return CanonicalLocator{CFI: devicePos, Precision: "fallback", Percentage: percentage}
		}
		if result.CFI != "" {
			return CanonicalLocator{CFI: result.CFI, Precision: result.Precision, Percentage: result.Percentage}
		}
		return CanonicalLocator{CFI: devicePos, Precision: result.Precision, Percentage: percentage}

	default:
		return CanonicalLocator{CFI: devicePos, Precision: "passthrough", Percentage: percentage}
	}
}

func ConvertFromCanonical(
	source LocatorSource,
	canonicalCFI string,
	percentage float64,
	contextText string,
	formatGroup string,
	epubPath string,
	kepubPath string,
) DeviceLocator {
	if !isConvertible(formatGroup) || epubPath == "" || canonicalCFI == "" {
		return DeviceLocator{
			Position:   canonicalCFI,
			Precision:  "passthrough",
			Percentage: percentage,
		}
	}

	switch source {
	case LocatorSourceKOReader:
		converter := NewCFIConverter(epubPath)
		result, err := converter.ConvertStandardToCRE(canonicalCFI, percentage, contextText)
		if err != nil || result == nil {
			log.Printf("Bookhoard: locator CFI→CRE conversion failed: %v", err)
			return DeviceLocator{Position: canonicalCFI, Precision: "fallback", Percentage: percentage}
		}
		if result.XPointer != "" {
			return DeviceLocator{Position: result.XPointer, Precision: result.Precision, Percentage: result.Percentage}
		}
		return DeviceLocator{Position: canonicalCFI, Precision: result.Precision, Percentage: percentage}

	case LocatorSourceKobo:
		if kepubPath == "" {
			return DeviceLocator{Position: canonicalCFI, Precision: "no-kepub", Percentage: percentage}
		}
		converter := NewKEPUBCFIConverter(epubPath, kepubPath)
		result, err := converter.ConvertStandardCFIToKEPUB(canonicalCFI, percentage, contextText)
		if err != nil || result == nil {
			log.Printf("Bookhoard: locator CFI→KEPUB conversion failed: %v", err)
			return DeviceLocator{Position: canonicalCFI, Precision: "fallback", Percentage: percentage}
		}
		if result.CFI != "" {
			return DeviceLocator{Position: result.CFI, Precision: result.Precision, Percentage: result.Percentage}
		}
		return DeviceLocator{Position: canonicalCFI, Precision: result.Precision, Percentage: percentage}

	default:
		return DeviceLocator{Position: canonicalCFI, Precision: "passthrough", Percentage: percentage}
	}
}
