package persistence

import (
	"context"
	"database/sql"

	apperrors "github.com/nexuscrm/kernel/pkg/errors"
	"github.com/nexuscrm/kernel/pkg/query"
	"github.com/nexuscrm/shared/pkg/constants"
	"github.com/nexuscrm/shared/pkg/models"
)

// GetActiveTheme returns the currently active theme
func (r *MetadataRepository) GetActiveTheme(ctx context.Context) (*models.Theme, error) {
	qr := query.From(constants.TableTheme).
		Select([]string{
			constants.FieldID, constants.FieldSysTheme_Name, constants.FieldSysTheme_IsActive,
			constants.FieldSysTheme_Colors, constants.FieldSysTheme_Density, constants.FieldSysTheme_LogoURL,
			constants.FieldCreatedDate, constants.FieldLastModifiedDate,
		}).
		Where(constants.FieldSysTheme_IsActive, true).
		Limit(1).
		Build()

	row := r.db.QueryRowContext(ctx, qr.SQL, qr.Params...)
	theme, err := r.scanTheme(row)
	if err != nil {
		if err == sql.ErrNoRows {
			return nil, nil // Return nil if no active theme found
		}
		return nil, err
	}
	return theme, nil
}

// GetThemeByName returns a theme by name
func (r *MetadataRepository) GetThemeByName(ctx context.Context, name string) (*models.Theme, error) {
	qr := query.From(constants.TableTheme).
		Select([]string{
			constants.FieldID, constants.FieldSysTheme_Name, constants.FieldSysTheme_IsActive,
			constants.FieldSysTheme_Colors, constants.FieldSysTheme_Density, constants.FieldSysTheme_LogoURL,
			constants.FieldCreatedDate, constants.FieldLastModifiedDate,
		}).
		Where(constants.FieldSysTheme_Name, name).
		Build()

	row := r.db.QueryRowContext(ctx, qr.SQL, qr.Params...)
	theme, err := r.scanTheme(row)
	if err != nil {
		if err == sql.ErrNoRows {
			return nil, nil
		}
		return nil, err
	}
	return theme, nil
}

// CreateTheme creates a new theme
func (r *MetadataRepository) CreateTheme(ctx context.Context, theme *models.Theme) error {
	colorsJSON, err := r.marshalJSON(theme.Colors)
	if err != nil {
		return apperrors.NewInternalError("failed to marshal colors", err)
	}

	qr := query.Insert(constants.TableTheme, map[string]interface{}{
		constants.FieldID:                theme.ID,
		constants.FieldSysTheme_Name:     theme.Name,
		constants.FieldSysTheme_IsActive: theme.IsActive,
		constants.FieldSysTheme_Colors:   colorsJSON,
		constants.FieldSysTheme_Density:  theme.Density,
		constants.FieldSysTheme_LogoURL:  theme.LogoURL,
		constants.FieldCreatedDate:       theme.CreatedDate,
		constants.FieldLastModifiedDate:  theme.LastModifiedDate,
	}).Build()

	_, err = r.db.ExecContext(ctx, qr.SQL, qr.Params...)
	return err
}

// UpdateTheme updates an existing theme
func (r *MetadataRepository) UpdateTheme(ctx context.Context, theme *models.Theme) error {
	colorsJSON, err := r.marshalJSON(theme.Colors)
	if err != nil {
		return apperrors.NewInternalError("failed to marshal colors", err)
	}

	qr := query.Update(constants.TableTheme).
		Set(map[string]interface{}{
			constants.FieldSysTheme_IsActive: theme.IsActive,
			constants.FieldSysTheme_Colors:   colorsJSON,
			constants.FieldSysTheme_Density:  theme.Density,
			constants.FieldSysTheme_LogoURL:  theme.LogoURL,
			constants.FieldLastModifiedDate:  theme.LastModifiedDate,
		}).
		Where(constants.FieldID, theme.ID).
		Build()

	_, err = r.db.ExecContext(ctx, qr.SQL, qr.Params...)
	return err
}

// ActivateTheme sets a specific theme as active and deactivates all others
func (r *MetadataRepository) ActivateTheme(ctx context.Context, themeID string) error {
	tx, err := r.db.BeginTx(ctx, nil)
	if err != nil {
		return err
	}
	defer func() { _ = tx.Rollback() }()

	// 1. Deactivate all
	qrDeactivate := query.Update(constants.TableTheme).
		Set(map[string]interface{}{
			constants.FieldSysTheme_IsActive: false,
		}).Build()

	_, err = tx.ExecContext(ctx, qrDeactivate.SQL, qrDeactivate.Params...)
	if err != nil {
		return apperrors.NewInternalError("failed to deactivate themes", err)
	}

	// 2. Activate target
	qrActivate := query.Update(constants.TableTheme).
		Set(map[string]interface{}{
			constants.FieldSysTheme_IsActive: true,
		}).
		Where(constants.FieldID, themeID).
		Build()

	result, err := tx.ExecContext(ctx, qrActivate.SQL, qrActivate.Params...)
	if err != nil {
		return apperrors.NewInternalError("failed to activate theme", err)
	}

	rows, _ := result.RowsAffected()
	if rows == 0 {
		return apperrors.NewNotFoundError("theme", themeID)
	}

	return tx.Commit()
}
