package mock

import (
	"context"
	"time"

	"github.com/example/storage-appliance/internal/domain"
	"github.com/example/storage-appliance/internal/service"
	"github.com/google/uuid"
)

var (
	_ service.DiskService   = (*MockDiskService)(nil)
	_ service.ZFSService    = (*MockZFSService)(nil)
	_ service.JobRunner     = (*MockJobRunner)(nil)
	_ service.SharesService = (*MockSharesService)(nil)
	_ service.ISCSIService  = (*MockISCSIService)(nil)
)

type MockDiskService struct{}

func (m *MockDiskService) List(ctx context.Context) ([]domain.Disk, error) {
	return []domain.Disk{{ID: domain.UUID(uuid.New().String()), Path: "/dev/sda", Serial: "XYZ123", Model: "ACME 1TB", Size: 1 << 40, Health: "ONLINE"}}, nil
}

func (m *MockDiskService) Inspect(ctx context.Context, path string) (domain.Disk, error) {
	return domain.Disk{ID: domain.UUID(uuid.New().String()), Path: path, Serial: "XYZ123", Model: "ACME 1TB", Size: 1 << 40, Health: "ONLINE"}, nil
}

type MockZFSService struct{}

func (m *MockZFSService) ListPools(ctx context.Context) ([]domain.Pool, error) {
	return []domain.Pool{{Name: "tank", GUID: "g-uuid-1", Health: "ONLINE", Capacity: "1TiB"}}, nil
}

func (m *MockZFSService) CreatePool(ctx context.Context, name string, vdevs []string) (string, error) {
	// not implemented on adapter-level mock
	return "", nil
}

func (m *MockZFSService) GetPoolStatus(ctx context.Context, pool string) (domain.PoolHealth, error) {
	return domain.PoolHealth{Pool: pool, Status: "ONLINE", Detail: "mocked"}, nil
}

func (m *MockZFSService) ListDatasets(ctx context.Context, pool string) ([]domain.Dataset, error) {
	return []domain.Dataset{{Name: pool + "/dataset1", Pool: pool, Type: "filesystem"}}, nil
}

func (m *MockZFSService) CreateDataset(ctx context.Context, name string, props map[string]string) error {
	return nil
}

func (m *MockZFSService) Snapshot(ctx context.Context, dataset, snapName string) error {
	return nil
}

func (m *MockZFSService) ScrubStart(ctx context.Context, pool string) error {
	return nil
}

func (m *MockZFSService) ScrubStatus(ctx context.Context, pool string) (string, error) {
	return "none", nil
}

type MockJobRunner struct{}

func (m *MockJobRunner) Enqueue(ctx context.Context, j domain.Job) (string, error) {
	// simulate queueing job and running immediately
	go func() {
		time.Sleep(100 * time.Millisecond)
	}()
	return uuid.New().String(), nil
}

type MockSharesService struct{}

func (m *MockSharesService) ListNFS(ctx context.Context) ([]domain.Share, error) {
	return []domain.Share{{ID: domain.UUID(uuid.New().String()), Name: "data", Path: "tank/ds", Type: "nfs"}}, nil
}

func (m *MockSharesService) CreateNFS(ctx context.Context, user, role, name, path string, opts map[string]string) (string, error) {
	return "share-" + uuid.New().String(), nil
}

func (m *MockSharesService) DeleteNFS(ctx context.Context, user, role, id string) error {
	return nil
}
func (m *MockSharesService) NFSStatus(ctx context.Context) (string, error) {
	return "active", nil
}
func (m *MockSharesService) ListSMB(ctx context.Context) ([]domain.Share, error) {
	return []domain.Share{{ID: domain.UUID(uuid.New().String()), Name: "smb1", Path: "tank/ds", Type: "smb", Config: map[string]string{"read_only": "false"}}}, nil
}
func (m *MockSharesService) CreateSMB(ctx context.Context, user, role, name, path string, readOnly bool, allowedUsers []string) (string, error) {
	return "smb-" + uuid.New().String(), nil
}
func (m *MockSharesService) DeleteSMB(ctx context.Context, user, role, id string) error {
	return nil
}

type MockISCSIService struct{}

func (m *MockISCSIService) ListTargets(ctx context.Context) ([]map[string]any, error) {
	return []map[string]any{{"id": "t-1", "iqn": "iqn.2025-12.org.example:target1", "name": "test"}}, nil
}

func (m *MockISCSIService) CreateTarget(ctx context.Context, user, role, name, iqn string) (string, error) {
	return "t-" + uuid.New().String(), nil
}

func (m *MockISCSIService) CreateLUN(ctx context.Context, user, role, targetID, lunName string, size string, blocksize int) (string, error) {
	return "lun-" + uuid.New().String(), nil
}

func (m *MockISCSIService) DeleteLUN(ctx context.Context, user, role, id string, force bool) error {
	return nil
}

func (m *MockISCSIService) ListLUNs(ctx context.Context, targetID string) ([]map[string]any, error) {
	return []map[string]any{{"id": "lun-1", "lun_id": 0, "zvol": "tank/ds/vol1", "size": 10737418240}}, nil
}

func (m *MockISCSIService) UnmapLUN(ctx context.Context, user, role, id string) error {
	return nil
}

func (m *MockISCSIService) AddPortal(ctx context.Context, user, role, targetID, address string, port int) (string, error) {
	return "portal-" + uuid.New().String(), nil
}

func (m *MockISCSIService) AddInitiator(ctx context.Context, user, role, targetID, initiatorIQN string) (string, error) {
	return "init-" + uuid.New().String(), nil
}

func (m *MockISCSIService) GetTargetInfo(ctx context.Context, targetID string) (map[string]any, error) {
	return map[string]any{"iqn": "iqn.2025-12.org.example:target1", "portals": []map[string]any{{"id": "p-1", "address": "10.0.0.1", "port": 3260}}, "initiators": []map[string]any{{"id": "i-1", "iqn": "iqn.1993-08.org.debian:01"}}}, nil
}
