package sqlite

import (
	"context"
	"fmt"
	"strings"
)

type LogicalGroupModel struct {
	ID             int64
	LogicalGroupID string
	PublicModel    string
	Status         string
	CreatedAt      string
	UpdatedAt      string
}

type LogicalGroupModelsRepo struct {
	db execQuerier
}

func newLogicalGroupModelsRepo(db execQuerier) *LogicalGroupModelsRepo {
	return &LogicalGroupModelsRepo{db: db}
}

func (r *LogicalGroupModelsRepo) Create(ctx context.Context, model LogicalGroupModel) (int64, error) {
	model, err := normalizeLogicalGroupModel(model)
	if err != nil {
		return 0, err
	}

	result, err := r.db.ExecContext(
		ctx,
		`INSERT INTO logical_group_models (logical_group_id, public_model, status)
		VALUES (?, ?, ?)`,
		model.LogicalGroupID,
		model.PublicModel,
		model.Status,
	)
	if err != nil {
		return 0, fmt.Errorf("insert logical group model %q/%q: %w", model.LogicalGroupID, model.PublicModel, err)
	}

	id, err := result.LastInsertId()
	if err != nil {
		return 0, fmt.Errorf("read inserted logical group model id for %q/%q: %w", model.LogicalGroupID, model.PublicModel, err)
	}
	return id, nil
}

func (r *LogicalGroupModelsRepo) ListByLogicalGroupID(ctx context.Context, logicalGroupID string) ([]LogicalGroupModel, error) {
	logicalGroupID = strings.TrimSpace(logicalGroupID)
	if logicalGroupID == "" {
		return nil, fmt.Errorf("logical_group_id is required")
	}

	rows, err := r.db.QueryContext(
		ctx,
		`SELECT id, logical_group_id, public_model, status, created_at, updated_at
		FROM logical_group_models
		WHERE logical_group_id = ?
		ORDER BY id ASC`,
		logicalGroupID,
	)
	if err != nil {
		return nil, fmt.Errorf("list logical group models for %q: %w", logicalGroupID, err)
	}
	defer rows.Close()

	models := make([]LogicalGroupModel, 0)
	for rows.Next() {
		var model LogicalGroupModel
		if err := rows.Scan(
			&model.ID,
			&model.LogicalGroupID,
			&model.PublicModel,
			&model.Status,
			&model.CreatedAt,
			&model.UpdatedAt,
		); err != nil {
			return nil, fmt.Errorf("scan logical group model: %w", err)
		}
		models = append(models, model)
	}
	if err := rows.Err(); err != nil {
		return nil, fmt.Errorf("iterate logical group models for %q: %w", logicalGroupID, err)
	}
	return models, nil
}

func (r *LogicalGroupModelsRepo) DeleteByLogicalGroupIDAndModel(ctx context.Context, logicalGroupID string, publicModel string) error {
	logicalGroupID = strings.TrimSpace(logicalGroupID)
	publicModel = strings.TrimSpace(publicModel)
	if logicalGroupID == "" {
		return fmt.Errorf("logical_group_id is required")
	}
	if publicModel == "" {
		return fmt.Errorf("public_model is required")
	}

	result, err := r.db.ExecContext(
		ctx,
		`DELETE FROM logical_group_models
		WHERE logical_group_id = ? AND public_model = ?`,
		logicalGroupID,
		publicModel,
	)
	if err != nil {
		return fmt.Errorf("delete logical group model %q/%q: %w", logicalGroupID, publicModel, err)
	}
	affected, err := result.RowsAffected()
	if err != nil {
		return fmt.Errorf("read deleted logical group model rows for %q/%q: %w", logicalGroupID, publicModel, err)
	}
	if affected == 0 {
		return fmt.Errorf("logical group model %q/%q not found", logicalGroupID, publicModel)
	}
	return nil
}

func normalizeLogicalGroupModel(model LogicalGroupModel) (LogicalGroupModel, error) {
	model.LogicalGroupID = strings.TrimSpace(model.LogicalGroupID)
	model.PublicModel = strings.TrimSpace(model.PublicModel)
	model.Status = strings.TrimSpace(model.Status)

	switch {
	case model.LogicalGroupID == "":
		return LogicalGroupModel{}, fmt.Errorf("logical_group_id is required")
	case model.PublicModel == "":
		return LogicalGroupModel{}, fmt.Errorf("public_model is required")
	}
	if model.Status == "" {
		model.Status = "active"
	}
	return model, nil
}
