package queries

import (
	"context"
	"database/sql"
	"fmt"
	"strings"
)

// LookupTbStokExistsByCodes checks if tbStok contains records matching the given codes.
// Match rules are aligned with costing usage:
// - exact sKodu (ignoring spaces)
// - exact sModel
//
// Returns a map[code]exists.
func LookupTbStokExistsByCodes(ctx context.Context, mssqlDB *sql.DB, codes []string) (map[string]bool, error) {
	if mssqlDB == nil {
		return nil, fmt.Errorf("mssql db is nil")
	}
	norm := make([]string, 0, len(codes))
	seen := map[string]struct{}{}
	for _, c := range codes {
		c = strings.TrimSpace(c)
		if c == "" {
			continue
		}
		if _, ok := seen[c]; ok {
			continue
		}
		seen[c] = struct{}{}
		norm = append(norm, c)
	}
	out := map[string]bool{}
	for _, c := range norm {
		out[c] = false
	}
	if len(norm) == 0 {
		return out, nil
	}

	valParts := make([]string, 0, len(norm))
	args := make([]any, 0, len(norm))
	for i, code := range norm {
		valParts = append(valParts, fmt.Sprintf("(@p%d)", i+1))
		args = append(args, code)
	}

	// NOTE: This endpoint is a UX validation helper and must be fast.
	// Keep predicates sargable: no function wrapping on tbStok columns.
	//
	// For "ignore spaces" behavior, we send both the original code and its no-space variant from input,
	// and match via exact equality against tbStok.sKodu.
	//
	// IMPORTANT: We intentionally do not filter by IsBlocked here because IsBlocked is nullable and
	// filtering requires OR logic, which can prevent index seeks and cause timeouts. This is a best-effort
	// existence check for UX highlighting.
	sqlText := fmt.Sprintf(`
WITH C AS (
  SELECT
    LTRIM(RTRIM(V.code)) AS code,
    REPLACE(LTRIM(RTRIM(V.code)), ' ', '') AS code_nospace
  FROM (VALUES %s) AS V(code)
),
HIT AS (
  SELECT DISTINCT C.code
  FROM C
  JOIN dbo.tbStok S
    ON S.sKodu = C.code
     OR S.sKodu = C.code_nospace
  UNION
  SELECT DISTINCT C.code
  FROM C
  JOIN dbo.tbStok S
    ON S.sModel = C.code
)
SELECT
  C.code,
  CASE WHEN H.code IS NULL THEN 0 ELSE 1 END AS existsFlag
FROM C
LEFT JOIN HIT H
  ON H.code = C.code
`, strings.Join(valParts, ","))

	rows, err := mssqlDB.QueryContext(ctx, sqlText, args...)
	if err != nil {
		return nil, err
	}
	defer rows.Close()

	for rows.Next() {
		var code string
		var existsFlag int
		if err := rows.Scan(&code, &existsFlag); err != nil {
			return nil, err
		}
		code = strings.TrimSpace(code)
		if code == "" {
			continue
		}
		out[code] = existsFlag == 1
	}
	if err := rows.Err(); err != nil {
		return nil, err
	}
	return out, nil
}
