package queries

import (
	"context"
	"database/sql"
	"sort"
	"strings"

	"github.com/lib/pq"
)

type BrandSyncResult struct {
	Upserted int `json:"upserted"`
	Deleted  int `json:"deleted"`
	Total    int `json:"total"`
}

// SyncBrandsFromMSSQL pulls brand attributes from MSSQL BAGGI_V3 and upserts them into Postgres mk_brands.
// Source: dbo.cdItemAttribute WHERE ItemTypeCode=1 AND AttributeTypeCode=10
func SyncBrandsFromMSSQL(ctx context.Context, mssql *sql.DB, pg *sql.DB) (BrandSyncResult, error) {
	out := BrandSyncResult{Upserted: 0, Deleted: 0, Total: 0}
	if mssql == nil || pg == nil {
		return out, sql.ErrConnDone
	}

	if err := EnsureBrandClassificationTables(pg); err != nil {
		return out, err
	}

	q := `
SELECT DISTINCT
  LTRIM(RTRIM(a.AttributeCode)) AS BrandCode,
  COALESCE(NULLIF(LTRIM(RTRIM(d.AttributeDescription)), ''), LTRIM(RTRIM(a.AttributeCode))) AS BrandName,
  ISNULL(a.IsBlocked, 0) AS IsBlocked
FROM dbo.cdItemAttribute a
LEFT JOIN dbo.cdItemAttributeDesc d
  ON d.ItemTypeCode = a.ItemTypeCode
 AND d.AttributeTypeCode = a.AttributeTypeCode
 AND d.AttributeCode = a.AttributeCode
 AND d.LangCode = 'TR'
WHERE a.ItemTypeCode = 1
  AND a.AttributeTypeCode = 10
  AND ISNULL(a.IsBlocked, 0) = 0
  AND LEN(LTRIM(RTRIM(a.AttributeCode))) > 0;
`
	rows, err := mssql.QueryContext(ctx, q)
	if err != nil {
		return out, err
	}
	defer rows.Close()

	type srcBrand struct {
		Code      string
		Name      string
		IsBlocked bool
	}
	src := make([]srcBrand, 0, 1024)
	keepCodes := make([]string, 0, 1024)
	seen := make(map[string]struct{}, 2048)

	for rows.Next() {
		var b srcBrand
		if err := rows.Scan(&b.Code, &b.Name, &b.IsBlocked); err != nil {
			return out, err
		}
		b.Code = strings.TrimSpace(b.Code)
		if b.Code == "" {
			continue
		}
		if _, ok := seen[b.Code]; ok {
			continue
		}
		seen[b.Code] = struct{}{}
		b.Name = strings.TrimSpace(b.Name)
		src = append(src, b)
		keepCodes = append(keepCodes, b.Code)
	}
	if err := rows.Err(); err != nil {
		return out, err
	}

	sort.Strings(keepCodes)
	out.Total = len(keepCodes)

	tx, err := pg.BeginTx(ctx, nil)
	if err != nil {
		return out, err
	}
	defer tx.Rollback()

	for _, b := range src {
		active := !b.IsBlocked
		if err := UpsertBrand(ctx, tx, b.Code, b.Name, active); err != nil {
			return out, err
		}
		out.Upserted++
	}

	if len(keepCodes) > 0 {
		res, err := tx.ExecContext(ctx, `
DELETE FROM mk_brands
WHERE brand_code NOT IN (SELECT UNNEST($1::text[]))
`, pq.Array(keepCodes))
		if err != nil {
			return out, err
		}
		if n, _ := res.RowsAffected(); n > 0 {
			out.Deleted = int(n)
		}
	}

	if err := tx.Commit(); err != nil {
		return out, err
	}

	return out, nil
}
