package samba

import (
    "context"
    "fmt"
    "os"
    "path/filepath"
    "strings"

    "github.com/example/storage-appliance/internal/domain"
    "github.com/example/storage-appliance/internal/infra/osexec"
)

type Adapter struct {
    Runner       osexec.Runner
    IncludePath  string
}

func NewAdapter(runner osexec.Runner, includePath string) *Adapter {
    if includePath == "" {
        includePath = "/etc/samba/smb.conf.d/appliance.conf"
    }
    return &Adapter{Runner: runner, IncludePath: includePath}
}

// RenderConf writes the Samba include file for appliance-managed shares
func (a *Adapter) RenderConf(ctx context.Context, shares []domain.Share) error {
    var lines []string
    lines = append(lines, "# Appliance-managed SMB share configuration")
    for _, s := range shares {
        if s.Type != "smb" {
            continue
        }
        opts := []string{"path = " + s.Path}
        // parse options if stored in s.Name or s.Config; fallback to broad default
        // s.Config may have read-only or allowed users
        if ro, ok := s.Config["read_only"]; ok && ro == "true" {
            opts = append(opts, "read only = yes")
        } else {
            opts = append(opts, "read only = no")
        }
        if users, ok := s.Config["allowed_users"]; ok {
            opts = append(opts, "valid users = "+users)
        }
        // write section
        lines = append(lines, fmt.Sprintf("[%s]", s.Name))
        for _, l := range opts {
            lines = append(lines, l)
        }
        lines = append(lines, "")
    }
    content := strings.Join(lines, "\n") + "\n"
    dir := filepath.Dir(a.IncludePath)
    tmp := filepath.Join(dir, ".appliance.smb.tmp")
    if err := os.WriteFile(tmp, []byte(content), 0644); err != nil {
        return err
    }
    if err := os.Rename(tmp, a.IncludePath); err != nil {
        return err
    }
    return nil
}

// Reload reloads or restarts samba to apply config
func (a *Adapter) Reload(ctx context.Context) error {
    // try to reload first
    _, stderr, _, err := osexec.ExecWithRunner(a.Runner, ctx, "systemctl", "reload", "smbd")
    if err == nil {
        return nil
    }
    // fallback to restart
    _, stderr, _, err = osexec.ExecWithRunner(a.Runner, ctx, "systemctl", "restart", "smbd")
    if err != nil {
        return fmt.Errorf("samba reload/restart failed: %s", stderr)
    }
    return nil
}

// CreateSambaUser optional: stub for creating a local samba user mapped to appliance user
func (a *Adapter) CreateSambaUser(ctx context.Context, user, password string) error {
    // This is optional - we use smbpasswd command in production; stub for now
    _, stderr, _, err := osexec.ExecWithRunner(a.Runner, ctx, "smbpasswd", "-a", user)
    if err != nil {
        return fmt.Errorf("smbpasswd failed: %s", stderr)
    }
    return nil
}
