package table

import (
	
	
	
	

	
)

var (
	metadataRegexp = regexp.MustCompile(`v[0-9]+\.metadata.json`)
	dataRegexp     = regexp.MustCompile(`[0-9A-Z]{26}.parquet`)
	snapshotRegexp = regexp.MustCompile(`snap-[0-9]{19}-[0-9A-Z]{26}\.avro`)
	manifestRegexp = regexp.MustCompile(`[0-9A-Z]{26}\.avro`)
	deletableFile  = []*regexp.Regexp{metadataRegexp, dataRegexp, snapshotRegexp, manifestRegexp}
)

// DeleteOrphanFiles will delete all files in the table's bucket that are not pointed to by any snapshot in the table.
// NOTE: https://iceberg.apache.org/docs/latest/maintenance/#delete-orphan-files
// "It is dangerous to remove orphan files with a retention interval shorter than the time expected for any write to complete because it might corrupt
// the table if in-progress files are considered orphaned and are deleted. The default interval is 3 days."
func ( context.Context,  Table,  time.Duration) error {
	 := map[string]struct{}{
		filepath.Base(.MetadataLocation()): {},
	}

	for ,  := range .Metadata().GetMetadataLog() {
		[filepath.Base(.MetadataFile)] = struct{}{} // Record the metadata files that are still referenced
	}

	for ,  := range .Metadata().Snapshots() {
		[filepath.Base(.ManifestList)] = struct{}{} // Record the manifest list file from each snapshot
		,  := .Manifests(.Bucket())
		if  != nil {
			return 
		}

		// Record the manifest file from each list
		for ,  := range  {
			[filepath.Base(.FilePath())] = struct{}{}

			// Record the data files from each manifest
			, ,  := .FetchEntries(.Bucket(), false)
			if  != nil {
				return 
			}

			for ,  := range  {
				[filepath.Base(.DataFile().FilePath())] = struct{}{}
			}
		}
	}

	return .Bucket().Iter(, .Location(), func( string) error {
		if ,  := [filepath.Base()]; ! {
			// If the file is not found in the list of referenced files and it's old enough AND it's a deletable file, delete it
			if !isDeletable() {
				return nil
			}
			,  := .Bucket().Attributes(, )
			if  != nil {
				return 
			}

			if time.Since(.LastModified) <  {
				return nil
			}

			return .Bucket().Delete(, )
		}
		return nil
	}, objstore.WithRecursiveIter)
}

func isDeletable( string) bool {
	for ,  := range deletableFile {
		if .MatchString() {
			return true
		}
	}
	return false
}