// Code generated by sqlc. DO NOT EDIT.
// versions:
//   sqlc v1.31.1
// source: partners.sql

package db

import (
	"context"

	"github.com/jackc/pgx/v5/pgtype"
	"github.com/shopspring/decimal"
)

const countCustomers = `-- name: CountCustomers :one
SELECT count(*) FROM customers
WHERE deleted_at IS NULL
  AND ($1::text IS NULL OR (name ILIKE '%' || $1 || '%' OR code ILIKE '%' || $1 || '%'))
  AND ($2::bool IS NULL OR is_active = $2)
  AND ($3::text IS NULL OR customer_type = $3)
`

type CountCustomersParams struct {
	Search       pgtype.Text `json:"search"`
	IsActive     pgtype.Bool `json:"is_active"`
	CustomerType pgtype.Text `json:"customer_type"`
}

func (q *Queries) CountCustomers(ctx context.Context, arg CountCustomersParams) (int64, error) {
	row := q.db.QueryRow(ctx, countCustomers, arg.Search, arg.IsActive, arg.CustomerType)
	var count int64
	err := row.Scan(&count)
	return count, err
}

const countSuppliers = `-- name: CountSuppliers :one
SELECT count(*) FROM suppliers
WHERE deleted_at IS NULL
  AND ($1::text IS NULL OR (name ILIKE '%' || $1 || '%' OR code ILIKE '%' || $1 || '%'))
  AND ($2::bool IS NULL OR is_active = $2)
`

type CountSuppliersParams struct {
	Search   pgtype.Text `json:"search"`
	IsActive pgtype.Bool `json:"is_active"`
}

func (q *Queries) CountSuppliers(ctx context.Context, arg CountSuppliersParams) (int64, error) {
	row := q.db.QueryRow(ctx, countSuppliers, arg.Search, arg.IsActive)
	var count int64
	err := row.Scan(&count)
	return count, err
}

const createCustomer = `-- name: CreateCustomer :one
INSERT INTO customers (code, name, contact_person, phone, email, address, city,
       kecamatan, kelurahan, desa,
       tax_number, credit_limit, payment_terms, customer_type, assigned_sales_id, is_active)
VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16)
RETURNING id
`

type CreateCustomerParams struct {
	Code            string          `json:"code"`
	Name            string          `json:"name"`
	ContactPerson   pgtype.Text     `json:"contact_person"`
	Phone           pgtype.Text     `json:"phone"`
	Email           pgtype.Text     `json:"email"`
	Address         pgtype.Text     `json:"address"`
	City            pgtype.Text     `json:"city"`
	Kecamatan       pgtype.Text     `json:"kecamatan"`
	Kelurahan       pgtype.Text     `json:"kelurahan"`
	Desa            pgtype.Text     `json:"desa"`
	TaxNumber       pgtype.Text     `json:"tax_number"`
	CreditLimit     decimal.Decimal `json:"credit_limit"`
	PaymentTerms    int32           `json:"payment_terms"`
	CustomerType    string          `json:"customer_type"`
	AssignedSalesID pgtype.Int8     `json:"assigned_sales_id"`
	IsActive        bool            `json:"is_active"`
}

func (q *Queries) CreateCustomer(ctx context.Context, arg CreateCustomerParams) (int64, error) {
	row := q.db.QueryRow(ctx, createCustomer,
		arg.Code,
		arg.Name,
		arg.ContactPerson,
		arg.Phone,
		arg.Email,
		arg.Address,
		arg.City,
		arg.Kecamatan,
		arg.Kelurahan,
		arg.Desa,
		arg.TaxNumber,
		arg.CreditLimit,
		arg.PaymentTerms,
		arg.CustomerType,
		arg.AssignedSalesID,
		arg.IsActive,
	)
	var id int64
	err := row.Scan(&id)
	return id, err
}

const createSupplier = `-- name: CreateSupplier :one
INSERT INTO suppliers (code, name, contact_person, phone, email, address, city,
       tax_number, bank_name, bank_account, credit_limit, payment_terms, is_active)
VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13)
RETURNING id
`

type CreateSupplierParams struct {
	Code          string          `json:"code"`
	Name          string          `json:"name"`
	ContactPerson pgtype.Text     `json:"contact_person"`
	Phone         pgtype.Text     `json:"phone"`
	Email         pgtype.Text     `json:"email"`
	Address       pgtype.Text     `json:"address"`
	City          pgtype.Text     `json:"city"`
	TaxNumber     pgtype.Text     `json:"tax_number"`
	BankName      pgtype.Text     `json:"bank_name"`
	BankAccount   pgtype.Text     `json:"bank_account"`
	CreditLimit   decimal.Decimal `json:"credit_limit"`
	PaymentTerms  int32           `json:"payment_terms"`
	IsActive      bool            `json:"is_active"`
}

func (q *Queries) CreateSupplier(ctx context.Context, arg CreateSupplierParams) (int64, error) {
	row := q.db.QueryRow(ctx, createSupplier,
		arg.Code,
		arg.Name,
		arg.ContactPerson,
		arg.Phone,
		arg.Email,
		arg.Address,
		arg.City,
		arg.TaxNumber,
		arg.BankName,
		arg.BankAccount,
		arg.CreditLimit,
		arg.PaymentTerms,
		arg.IsActive,
	)
	var id int64
	err := row.Scan(&id)
	return id, err
}

const customerIsEcomAdminByUserID = `-- name: CustomerIsEcomAdminByUserID :one
SELECT is_ecommerce_admin FROM customers WHERE user_id=$1 AND deleted_at IS NULL
`

func (q *Queries) CustomerIsEcomAdminByUserID(ctx context.Context, userID pgtype.Int8) (bool, error) {
	row := q.db.QueryRow(ctx, customerIsEcomAdminByUserID, userID)
	var is_ecommerce_admin bool
	err := row.Scan(&is_ecommerce_admin)
	return is_ecommerce_admin, err
}

const customerProfileForUser = `-- name: CustomerProfileForUser :one
SELECT id, code, name, contact_person, phone, email, address, city,
       kecamatan, kelurahan, desa, tax_number, website,
       billing_address_id, shipping_address_id
FROM customers WHERE user_id = $1 AND deleted_at IS NULL
`

type CustomerProfileForUserRow struct {
	ID                int64       `json:"id"`
	Code              string      `json:"code"`
	Name              string      `json:"name"`
	ContactPerson     pgtype.Text `json:"contact_person"`
	Phone             pgtype.Text `json:"phone"`
	Email             pgtype.Text `json:"email"`
	Address           pgtype.Text `json:"address"`
	City              pgtype.Text `json:"city"`
	Kecamatan         pgtype.Text `json:"kecamatan"`
	Kelurahan         pgtype.Text `json:"kelurahan"`
	Desa              pgtype.Text `json:"desa"`
	TaxNumber         pgtype.Text `json:"tax_number"`
	Website           pgtype.Text `json:"website"`
	BillingAddressID  pgtype.Int8 `json:"billing_address_id"`
	ShippingAddressID pgtype.Int8 `json:"shipping_address_id"`
}

// The signed-in caller's OWN customer record, for the B2B account profile
// page. Scoped by customers.user_id, NOT by an id in the path: a storefront
// buyer must never be able to read or edit the company directory by guessing
// an id, and /customers/{id} stays behind the internal PII gate.
func (q *Queries) CustomerProfileForUser(ctx context.Context, userID pgtype.Int8) (CustomerProfileForUserRow, error) {
	row := q.db.QueryRow(ctx, customerProfileForUser, userID)
	var i CustomerProfileForUserRow
	err := row.Scan(
		&i.ID,
		&i.Code,
		&i.Name,
		&i.ContactPerson,
		&i.Phone,
		&i.Email,
		&i.Address,
		&i.City,
		&i.Kecamatan,
		&i.Kelurahan,
		&i.Desa,
		&i.TaxNumber,
		&i.Website,
		&i.BillingAddressID,
		&i.ShippingAddressID,
	)
	return i, err
}

const getCustomerByCode = `-- name: GetCustomerByCode :one
SELECT id, code, name, contact_person, phone, email, address, city,
       tax_number, credit_limit, payment_terms, customer_type, assigned_sales_id, is_active, deleted_at
FROM customers WHERE code = $1
`

type GetCustomerByCodeRow struct {
	ID              int64              `json:"id"`
	Code            string             `json:"code"`
	Name            string             `json:"name"`
	ContactPerson   pgtype.Text        `json:"contact_person"`
	Phone           pgtype.Text        `json:"phone"`
	Email           pgtype.Text        `json:"email"`
	Address         pgtype.Text        `json:"address"`
	City            pgtype.Text        `json:"city"`
	TaxNumber       pgtype.Text        `json:"tax_number"`
	CreditLimit     decimal.Decimal    `json:"credit_limit"`
	PaymentTerms    int32              `json:"payment_terms"`
	CustomerType    string             `json:"customer_type"`
	AssignedSalesID pgtype.Int8        `json:"assigned_sales_id"`
	IsActive        bool               `json:"is_active"`
	DeletedAt       pgtype.Timestamptz `json:"deleted_at"`
}

func (q *Queries) GetCustomerByCode(ctx context.Context, code string) (GetCustomerByCodeRow, error) {
	row := q.db.QueryRow(ctx, getCustomerByCode, code)
	var i GetCustomerByCodeRow
	err := row.Scan(
		&i.ID,
		&i.Code,
		&i.Name,
		&i.ContactPerson,
		&i.Phone,
		&i.Email,
		&i.Address,
		&i.City,
		&i.TaxNumber,
		&i.CreditLimit,
		&i.PaymentTerms,
		&i.CustomerType,
		&i.AssignedSalesID,
		&i.IsActive,
		&i.DeletedAt,
	)
	return i, err
}

const getCustomerByID = `-- name: GetCustomerByID :one
SELECT id, code, name, contact_person, phone, email, address, city,
       kecamatan, kelurahan, desa,
       tax_number, credit_limit, payment_terms, customer_type, assigned_sales_id, is_active, deleted_at
FROM customers WHERE id = $1 AND deleted_at IS NULL
`

type GetCustomerByIDRow struct {
	ID              int64              `json:"id"`
	Code            string             `json:"code"`
	Name            string             `json:"name"`
	ContactPerson   pgtype.Text        `json:"contact_person"`
	Phone           pgtype.Text        `json:"phone"`
	Email           pgtype.Text        `json:"email"`
	Address         pgtype.Text        `json:"address"`
	City            pgtype.Text        `json:"city"`
	Kecamatan       pgtype.Text        `json:"kecamatan"`
	Kelurahan       pgtype.Text        `json:"kelurahan"`
	Desa            pgtype.Text        `json:"desa"`
	TaxNumber       pgtype.Text        `json:"tax_number"`
	CreditLimit     decimal.Decimal    `json:"credit_limit"`
	PaymentTerms    int32              `json:"payment_terms"`
	CustomerType    string             `json:"customer_type"`
	AssignedSalesID pgtype.Int8        `json:"assigned_sales_id"`
	IsActive        bool               `json:"is_active"`
	DeletedAt       pgtype.Timestamptz `json:"deleted_at"`
}

func (q *Queries) GetCustomerByID(ctx context.Context, id int64) (GetCustomerByIDRow, error) {
	row := q.db.QueryRow(ctx, getCustomerByID, id)
	var i GetCustomerByIDRow
	err := row.Scan(
		&i.ID,
		&i.Code,
		&i.Name,
		&i.ContactPerson,
		&i.Phone,
		&i.Email,
		&i.Address,
		&i.City,
		&i.Kecamatan,
		&i.Kelurahan,
		&i.Desa,
		&i.TaxNumber,
		&i.CreditLimit,
		&i.PaymentTerms,
		&i.CustomerType,
		&i.AssignedSalesID,
		&i.IsActive,
		&i.DeletedAt,
	)
	return i, err
}

const getCustomerLoginUser = `-- name: GetCustomerLoginUser :one
SELECT u.id, u.is_active
FROM customers c
JOIN users u ON u.id = c.user_id
WHERE c.id = $1 AND c.deleted_at IS NULL
`

type GetCustomerLoginUserRow struct {
	ID       int64 `json:"id"`
	IsActive bool  `json:"is_active"`
}

// The linked B2B login for a customer (000151): NULL when the customer has no
// user account (a catalog-only record). The password-reset service refuses
// those — there is no credential to reset.
func (q *Queries) GetCustomerLoginUser(ctx context.Context, id int64) (GetCustomerLoginUserRow, error) {
	row := q.db.QueryRow(ctx, getCustomerLoginUser, id)
	var i GetCustomerLoginUserRow
	err := row.Scan(&i.ID, &i.IsActive)
	return i, err
}

const getSupplierByCode = `-- name: GetSupplierByCode :one
SELECT id, code, name, contact_person, phone, email, address, city,
       tax_number, bank_name, bank_account, credit_limit, payment_terms, is_active, deleted_at
FROM suppliers WHERE code = $1
`

type GetSupplierByCodeRow struct {
	ID            int64              `json:"id"`
	Code          string             `json:"code"`
	Name          string             `json:"name"`
	ContactPerson pgtype.Text        `json:"contact_person"`
	Phone         pgtype.Text        `json:"phone"`
	Email         pgtype.Text        `json:"email"`
	Address       pgtype.Text        `json:"address"`
	City          pgtype.Text        `json:"city"`
	TaxNumber     pgtype.Text        `json:"tax_number"`
	BankName      pgtype.Text        `json:"bank_name"`
	BankAccount   pgtype.Text        `json:"bank_account"`
	CreditLimit   decimal.Decimal    `json:"credit_limit"`
	PaymentTerms  int32              `json:"payment_terms"`
	IsActive      bool               `json:"is_active"`
	DeletedAt     pgtype.Timestamptz `json:"deleted_at"`
}

func (q *Queries) GetSupplierByCode(ctx context.Context, code string) (GetSupplierByCodeRow, error) {
	row := q.db.QueryRow(ctx, getSupplierByCode, code)
	var i GetSupplierByCodeRow
	err := row.Scan(
		&i.ID,
		&i.Code,
		&i.Name,
		&i.ContactPerson,
		&i.Phone,
		&i.Email,
		&i.Address,
		&i.City,
		&i.TaxNumber,
		&i.BankName,
		&i.BankAccount,
		&i.CreditLimit,
		&i.PaymentTerms,
		&i.IsActive,
		&i.DeletedAt,
	)
	return i, err
}

const getSupplierByID = `-- name: GetSupplierByID :one
SELECT id, code, name, contact_person, phone, email, address, city,
       tax_number, bank_name, bank_account, credit_limit, payment_terms, is_active, deleted_at
FROM suppliers WHERE id = $1 AND deleted_at IS NULL
`

type GetSupplierByIDRow struct {
	ID            int64              `json:"id"`
	Code          string             `json:"code"`
	Name          string             `json:"name"`
	ContactPerson pgtype.Text        `json:"contact_person"`
	Phone         pgtype.Text        `json:"phone"`
	Email         pgtype.Text        `json:"email"`
	Address       pgtype.Text        `json:"address"`
	City          pgtype.Text        `json:"city"`
	TaxNumber     pgtype.Text        `json:"tax_number"`
	BankName      pgtype.Text        `json:"bank_name"`
	BankAccount   pgtype.Text        `json:"bank_account"`
	CreditLimit   decimal.Decimal    `json:"credit_limit"`
	PaymentTerms  int32              `json:"payment_terms"`
	IsActive      bool               `json:"is_active"`
	DeletedAt     pgtype.Timestamptz `json:"deleted_at"`
}

func (q *Queries) GetSupplierByID(ctx context.Context, id int64) (GetSupplierByIDRow, error) {
	row := q.db.QueryRow(ctx, getSupplierByID, id)
	var i GetSupplierByIDRow
	err := row.Scan(
		&i.ID,
		&i.Code,
		&i.Name,
		&i.ContactPerson,
		&i.Phone,
		&i.Email,
		&i.Address,
		&i.City,
		&i.TaxNumber,
		&i.BankName,
		&i.BankAccount,
		&i.CreditLimit,
		&i.PaymentTerms,
		&i.IsActive,
		&i.DeletedAt,
	)
	return i, err
}

const listCustomers = `-- name: ListCustomers :many
SELECT id, code, name, contact_person, phone, email, address, city,
       kecamatan, kelurahan, desa,
       tax_number, credit_limit, payment_terms, customer_type, assigned_sales_id, is_active, deleted_at
FROM customers
WHERE deleted_at IS NULL
  AND ($3::text IS NULL OR (name ILIKE '%' || $3 || '%' OR code ILIKE '%' || $3 || '%'))
  AND ($4::bool IS NULL OR is_active = $4)
  AND ($5::text IS NULL OR customer_type = $5)
ORDER BY
  CASE WHEN $6::text = 'name' AND $7::text = 'desc' THEN name END DESC,
  CASE WHEN $6::text = 'name' THEN name END ASC,
  CASE WHEN $6::text = 'city' AND $7::text = 'desc' THEN city END DESC,
  CASE WHEN $6::text = 'city' THEN city END ASC,
  CASE WHEN $6::text = 'credit_limit' AND $7::text = 'desc' THEN credit_limit END DESC,
  CASE WHEN $6::text = 'credit_limit' THEN credit_limit END ASC,
  CASE WHEN $6::text = 'payment_terms' AND $7::text = 'desc' THEN payment_terms END DESC,
  CASE WHEN $6::text = 'payment_terms' THEN payment_terms END ASC,
  CASE WHEN $6::text = 'code' AND $7::text = 'desc' THEN code END DESC,
  CASE WHEN $6::text = 'code' THEN code END ASC,
  code ASC
LIMIT $1 OFFSET $2
`

type ListCustomersParams struct {
	Limit        int32       `json:"limit"`
	Offset       int32       `json:"offset"`
	Search       pgtype.Text `json:"search"`
	IsActive     pgtype.Bool `json:"is_active"`
	CustomerType pgtype.Text `json:"customer_type"`
	SortBy       pgtype.Text `json:"sort_by"`
	SortDir      pgtype.Text `json:"sort_dir"`
}

type ListCustomersRow struct {
	ID              int64              `json:"id"`
	Code            string             `json:"code"`
	Name            string             `json:"name"`
	ContactPerson   pgtype.Text        `json:"contact_person"`
	Phone           pgtype.Text        `json:"phone"`
	Email           pgtype.Text        `json:"email"`
	Address         pgtype.Text        `json:"address"`
	City            pgtype.Text        `json:"city"`
	Kecamatan       pgtype.Text        `json:"kecamatan"`
	Kelurahan       pgtype.Text        `json:"kelurahan"`
	Desa            pgtype.Text        `json:"desa"`
	TaxNumber       pgtype.Text        `json:"tax_number"`
	CreditLimit     decimal.Decimal    `json:"credit_limit"`
	PaymentTerms    int32              `json:"payment_terms"`
	CustomerType    string             `json:"customer_type"`
	AssignedSalesID pgtype.Int8        `json:"assigned_sales_id"`
	IsActive        bool               `json:"is_active"`
	DeletedAt       pgtype.Timestamptz `json:"deleted_at"`
}

func (q *Queries) ListCustomers(ctx context.Context, arg ListCustomersParams) ([]ListCustomersRow, error) {
	rows, err := q.db.Query(ctx, listCustomers,
		arg.Limit,
		arg.Offset,
		arg.Search,
		arg.IsActive,
		arg.CustomerType,
		arg.SortBy,
		arg.SortDir,
	)
	if err != nil {
		return nil, err
	}
	defer rows.Close()
	var items []ListCustomersRow
	for rows.Next() {
		var i ListCustomersRow
		if err := rows.Scan(
			&i.ID,
			&i.Code,
			&i.Name,
			&i.ContactPerson,
			&i.Phone,
			&i.Email,
			&i.Address,
			&i.City,
			&i.Kecamatan,
			&i.Kelurahan,
			&i.Desa,
			&i.TaxNumber,
			&i.CreditLimit,
			&i.PaymentTerms,
			&i.CustomerType,
			&i.AssignedSalesID,
			&i.IsActive,
			&i.DeletedAt,
		); err != nil {
			return nil, err
		}
		items = append(items, i)
	}
	if err := rows.Err(); err != nil {
		return nil, err
	}
	return items, nil
}

const listSuppliers = `-- name: ListSuppliers :many
SELECT id, code, name, contact_person, phone, email, address, city,
       tax_number, bank_name, bank_account, credit_limit, payment_terms, is_active, deleted_at
FROM suppliers
WHERE deleted_at IS NULL
  AND ($3::text IS NULL OR (name ILIKE '%' || $3 || '%' OR code ILIKE '%' || $3 || '%'))
  AND ($4::bool IS NULL OR is_active = $4)
ORDER BY
  CASE WHEN $5::text = 'name' AND $6::text = 'desc' THEN name END DESC,
  CASE WHEN $5::text = 'name' THEN name END ASC,
  CASE WHEN $5::text = 'city' AND $6::text = 'desc' THEN city END DESC,
  CASE WHEN $5::text = 'city' THEN city END ASC,
  CASE WHEN $5::text = 'credit_limit' AND $6::text = 'desc' THEN credit_limit END DESC,
  CASE WHEN $5::text = 'credit_limit' THEN credit_limit END ASC,
  CASE WHEN $5::text = 'payment_terms' AND $6::text = 'desc' THEN payment_terms END DESC,
  CASE WHEN $5::text = 'payment_terms' THEN payment_terms END ASC,
  CASE WHEN $5::text = 'code' AND $6::text = 'desc' THEN code END DESC,
  CASE WHEN $5::text = 'code' THEN code END ASC,
  code ASC
LIMIT $1 OFFSET $2
`

type ListSuppliersParams struct {
	Limit    int32       `json:"limit"`
	Offset   int32       `json:"offset"`
	Search   pgtype.Text `json:"search"`
	IsActive pgtype.Bool `json:"is_active"`
	SortBy   pgtype.Text `json:"sort_by"`
	SortDir  pgtype.Text `json:"sort_dir"`
}

type ListSuppliersRow struct {
	ID            int64              `json:"id"`
	Code          string             `json:"code"`
	Name          string             `json:"name"`
	ContactPerson pgtype.Text        `json:"contact_person"`
	Phone         pgtype.Text        `json:"phone"`
	Email         pgtype.Text        `json:"email"`
	Address       pgtype.Text        `json:"address"`
	City          pgtype.Text        `json:"city"`
	TaxNumber     pgtype.Text        `json:"tax_number"`
	BankName      pgtype.Text        `json:"bank_name"`
	BankAccount   pgtype.Text        `json:"bank_account"`
	CreditLimit   decimal.Decimal    `json:"credit_limit"`
	PaymentTerms  int32              `json:"payment_terms"`
	IsActive      bool               `json:"is_active"`
	DeletedAt     pgtype.Timestamptz `json:"deleted_at"`
}

func (q *Queries) ListSuppliers(ctx context.Context, arg ListSuppliersParams) ([]ListSuppliersRow, error) {
	rows, err := q.db.Query(ctx, listSuppliers,
		arg.Limit,
		arg.Offset,
		arg.Search,
		arg.IsActive,
		arg.SortBy,
		arg.SortDir,
	)
	if err != nil {
		return nil, err
	}
	defer rows.Close()
	var items []ListSuppliersRow
	for rows.Next() {
		var i ListSuppliersRow
		if err := rows.Scan(
			&i.ID,
			&i.Code,
			&i.Name,
			&i.ContactPerson,
			&i.Phone,
			&i.Email,
			&i.Address,
			&i.City,
			&i.TaxNumber,
			&i.BankName,
			&i.BankAccount,
			&i.CreditLimit,
			&i.PaymentTerms,
			&i.IsActive,
			&i.DeletedAt,
		); err != nil {
			return nil, err
		}
		items = append(items, i)
	}
	if err := rows.Err(); err != nil {
		return nil, err
	}
	return items, nil
}

const softDeleteCustomer = `-- name: SoftDeleteCustomer :execrows
UPDATE customers SET deleted_at = now() WHERE id=$1 AND deleted_at IS NULL
`

func (q *Queries) SoftDeleteCustomer(ctx context.Context, id int64) (int64, error) {
	result, err := q.db.Exec(ctx, softDeleteCustomer, id)
	if err != nil {
		return 0, err
	}
	return result.RowsAffected(), nil
}

const softDeleteSupplier = `-- name: SoftDeleteSupplier :execrows
UPDATE suppliers SET deleted_at = now() WHERE id=$1 AND deleted_at IS NULL
`

func (q *Queries) SoftDeleteSupplier(ctx context.Context, id int64) (int64, error) {
	result, err := q.db.Exec(ctx, softDeleteSupplier, id)
	if err != nil {
		return 0, err
	}
	return result.RowsAffected(), nil
}

const updateCustomer = `-- name: UpdateCustomer :execrows
UPDATE customers SET name=$2, contact_person=$3, phone=$4, email=$5, address=$6,
       city=$7, kecamatan=$8, kelurahan=$9, desa=$10,
       tax_number=$11, credit_limit=$12, payment_terms=$13, customer_type=$14,
       assigned_sales_id=$15, is_active=$16
WHERE id=$1 AND deleted_at IS NULL
`

type UpdateCustomerParams struct {
	ID              int64           `json:"id"`
	Name            string          `json:"name"`
	ContactPerson   pgtype.Text     `json:"contact_person"`
	Phone           pgtype.Text     `json:"phone"`
	Email           pgtype.Text     `json:"email"`
	Address         pgtype.Text     `json:"address"`
	City            pgtype.Text     `json:"city"`
	Kecamatan       pgtype.Text     `json:"kecamatan"`
	Kelurahan       pgtype.Text     `json:"kelurahan"`
	Desa            pgtype.Text     `json:"desa"`
	TaxNumber       pgtype.Text     `json:"tax_number"`
	CreditLimit     decimal.Decimal `json:"credit_limit"`
	PaymentTerms    int32           `json:"payment_terms"`
	CustomerType    string          `json:"customer_type"`
	AssignedSalesID pgtype.Int8     `json:"assigned_sales_id"`
	IsActive        bool            `json:"is_active"`
}

func (q *Queries) UpdateCustomer(ctx context.Context, arg UpdateCustomerParams) (int64, error) {
	result, err := q.db.Exec(ctx, updateCustomer,
		arg.ID,
		arg.Name,
		arg.ContactPerson,
		arg.Phone,
		arg.Email,
		arg.Address,
		arg.City,
		arg.Kecamatan,
		arg.Kelurahan,
		arg.Desa,
		arg.TaxNumber,
		arg.CreditLimit,
		arg.PaymentTerms,
		arg.CustomerType,
		arg.AssignedSalesID,
		arg.IsActive,
	)
	if err != nil {
		return 0, err
	}
	return result.RowsAffected(), nil
}

const updateCustomerProfileForUser = `-- name: UpdateCustomerProfileForUser :one
UPDATE customers
SET name = COALESCE($1, name),
    contact_person = COALESCE($2, contact_person),
    phone = COALESCE($3, phone),
    email = COALESCE($4, email),
    address = COALESCE($5, address),
    city = COALESCE($6, city),
    kecamatan = COALESCE($7, kecamatan),
    kelurahan = COALESCE($8, kelurahan),
    desa = COALESCE($9, desa),
    tax_number = COALESCE($10, tax_number),
    website = COALESCE($11, website),
    -- CASE, not COALESCE, for the two address pointers. COALESCE would read an
    -- explicit "clear to NULL" as "keep what is there", because the value and
    -- the absence of one are both NULL by the time they reach SQL. The *Set
    -- flags restore the distinction: false keeps the column, true writes the
    -- value even when that value is NULL. See partners.NullInt.
    billing_address_id = CASE WHEN $12::boolean THEN $13 ELSE billing_address_id END,
    shipping_address_id = CASE WHEN $14::boolean THEN $15 ELSE shipping_address_id END,
    updated_at = now()
WHERE user_id = $16 AND deleted_at IS NULL
RETURNING id
`

type UpdateCustomerProfileForUserParams struct {
	Name              pgtype.Text `json:"name"`
	ContactPerson     pgtype.Text `json:"contact_person"`
	Phone             pgtype.Text `json:"phone"`
	Email             pgtype.Text `json:"email"`
	Address           pgtype.Text `json:"address"`
	City              pgtype.Text `json:"city"`
	Kecamatan         pgtype.Text `json:"kecamatan"`
	Kelurahan         pgtype.Text `json:"kelurahan"`
	Desa              pgtype.Text `json:"desa"`
	TaxNumber         pgtype.Text `json:"tax_number"`
	Website           pgtype.Text `json:"website"`
	BillingSet        bool        `json:"billing_set"`
	BillingAddressID  pgtype.Int8 `json:"billing_address_id"`
	ShippingSet       bool        `json:"shipping_set"`
	ShippingAddressID pgtype.Int8 `json:"shipping_address_id"`
	UserID            pgtype.Int8 `json:"user_id"`
}

// The same scoping as CustomerProfileForUser: keyed by users.id, never by an
// id in the path. Every field is COALESCE'd against the current column so an
// omitted argument (NULL) leaves it alone.
//
// COALESCE, not NULLIF, on name as well. An earlier draft used
// NULLIF(name, ”) to make a blank name a no-op; that is indistinguishable
// from the client omitting the field, so a client that sent only {"website":""}
// could never clear its own name, and a client that sent {"name":""} got
// silence instead of an error. A blank company name is rejected in the service
// instead, where it can be reported.
func (q *Queries) UpdateCustomerProfileForUser(ctx context.Context, arg UpdateCustomerProfileForUserParams) (int64, error) {
	row := q.db.QueryRow(ctx, updateCustomerProfileForUser,
		arg.Name,
		arg.ContactPerson,
		arg.Phone,
		arg.Email,
		arg.Address,
		arg.City,
		arg.Kecamatan,
		arg.Kelurahan,
		arg.Desa,
		arg.TaxNumber,
		arg.Website,
		arg.BillingSet,
		arg.BillingAddressID,
		arg.ShippingSet,
		arg.ShippingAddressID,
		arg.UserID,
	)
	var id int64
	err := row.Scan(&id)
	return id, err
}

const updateSupplier = `-- name: UpdateSupplier :execrows
UPDATE suppliers SET name=$2, contact_person=$3, phone=$4, email=$5, address=$6,
       city=$7, tax_number=$8, bank_name=$9, bank_account=$10, credit_limit=$11,
       payment_terms=$12, is_active=$13
WHERE id=$1 AND deleted_at IS NULL
`

type UpdateSupplierParams struct {
	ID            int64           `json:"id"`
	Name          string          `json:"name"`
	ContactPerson pgtype.Text     `json:"contact_person"`
	Phone         pgtype.Text     `json:"phone"`
	Email         pgtype.Text     `json:"email"`
	Address       pgtype.Text     `json:"address"`
	City          pgtype.Text     `json:"city"`
	TaxNumber     pgtype.Text     `json:"tax_number"`
	BankName      pgtype.Text     `json:"bank_name"`
	BankAccount   pgtype.Text     `json:"bank_account"`
	CreditLimit   decimal.Decimal `json:"credit_limit"`
	PaymentTerms  int32           `json:"payment_terms"`
	IsActive      bool            `json:"is_active"`
}

func (q *Queries) UpdateSupplier(ctx context.Context, arg UpdateSupplierParams) (int64, error) {
	result, err := q.db.Exec(ctx, updateSupplier,
		arg.ID,
		arg.Name,
		arg.ContactPerson,
		arg.Phone,
		arg.Email,
		arg.Address,
		arg.City,
		arg.TaxNumber,
		arg.BankName,
		arg.BankAccount,
		arg.CreditLimit,
		arg.PaymentTerms,
		arg.IsActive,
	)
	if err != nil {
		return 0, err
	}
	return result.RowsAffected(), nil
}
