package diskinfo

import (
	"errors"
	"os"

	"imuslab.com/bokofs/bokofsd/mod/diskinfo/blkid"
	"imuslab.com/bokofs/bokofsd/mod/diskinfo/lsblk"
)

// Disk represents a disk device with its attributes.
type Disk struct {
	UUID       string `json:"uuid"`
	Name       string `json:"name"`
	Path       string `json:"path"`
	Size       int64  `json:"size"`
	BlockSize  int    `json:"blocksize"`
	BlockType  string `json:"blocktype"`
	FsType     string `json:"fstype"`
	MountPoint string `json:"mountpoint,omitempty"`
}

// Get a disk by its device path
func NewDiskFromDevicePath(devpath string) (*Disk, error) {
	if _, err := os.Stat(devpath); errors.Is(err, os.ErrNotExist) {
		return nil, errors.New("device path does not exist")
	}

	//Create a new disk object
	thisDisk := &Disk{
		Path: devpath,
	}

	//Try to get the block device info
	err := thisDisk.UpdateProperties()
	if err != nil {
		return nil, err
	}

	return thisDisk, nil
}

// UpdateProperties updates the properties of the disk.
func (d *Disk) UpdateProperties() error {
	//Try to get the block device info
	blockDeviceInfo, err := lsblk.GetBlockDeviceInfoFromDevicePath(d.Path)
	if err != nil {
		return err
	}

	// Update the disk properties
	d.Name = blockDeviceInfo.Name
	d.Size = blockDeviceInfo.Size
	d.BlockType = blockDeviceInfo.Type
	d.MountPoint = blockDeviceInfo.MountPoint

	if d.BlockType == "disk" {
		//This block is a disk not a partition. There is no partition ID info
		//So we can skip the blkid call
		return nil
	}

	// Get the partition ID
	diskIdInfo, err := blkid.GetPartitionIDFromDevicePath(d.Path)
	if err != nil {
		return err
	}

	// Update the disk properties with ID info
	d.UUID = diskIdInfo.UUID
	d.FsType = diskIdInfo.Type
	d.BlockSize = diskIdInfo.BlockSize
	return nil
}
