package cmd

import (
	"fmt"

	"git.wntrmute.dev/kyle/arca/internal/config"
	"git.wntrmute.dev/kyle/arca/internal/cryptsetup"
	"git.wntrmute.dev/kyle/arca/internal/udisks"
	"github.com/spf13/cobra"
)

var unmountCmd = &cobra.Command{
	Use:               "unmount <device|alias>",
	Aliases:           []string{"umount"},
	Short:             "Unmount and lock a LUKS volume",
	Args:              cobra.ExactArgs(1),
	RunE:              runUnmount,
	ValidArgsFunction: completeDeviceOrAlias,
}

func init() {
	rootCmd.AddCommand(unmountCmd)
}

func runUnmount(cmd *cobra.Command, args []string) error {
	cfg := config.Load()
	target := args[0]

	client, err := udisks.NewClient()
	if err != nil {
		return fmt.Errorf("connecting to udisks2: %w", err)
	}
	defer client.Close()

	devCfg := cfg.ResolveDevice(target)

	dev, err := client.FindDevice(devCfg.UUID, target)
	if err != nil {
		return err
	}

	// Check if already locked.
	cleartext, err := client.CleartextDevice(dev)
	if err != nil {
		fmt.Fprintf(cmd.ErrOrStderr(), "%s is already locked\n", target)
		return nil
	}

	// Unmount if mounted.
	if mp, mounted := client.IsMounted(cleartext); mounted {
		if err := client.Unmount(cleartext); err != nil {
			// udisks2 unmount failed — try privileged umount.
			if err := cryptsetup.Unmount(mp); err != nil {
				return fmt.Errorf("unmounting: %w", err)
			}
		}
	}

	// Lock: try udisks2 first, fall back to cryptsetup close.
	if err := client.Lock(dev); err != nil {
		mapperName := cryptsetup.MapperName(dev.DevicePath)
		if err := cryptsetup.Close(mapperName); err != nil {
			return fmt.Errorf("locking: %w", err)
		}
	}

	fmt.Printf("Unmounted and locked %s\n", target)
	return nil
}
