// Code generated by sqlc. DO NOT EDIT.
// versions:
//   sqlc v1.27.0
// source: salestracking.sql

package db

import (
	"context"

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

const countCustomersActiveForVisit = `-- name: CountCustomersActiveForVisit :one
SELECT count(*) FROM customers WHERE id=$1 AND deleted_at IS NULL
`

func (q *Queries) CountCustomersActiveForVisit(ctx context.Context, id int64) (int64, error) {
	row := q.db.QueryRow(ctx, countCustomersActiveForVisit, id)
	var count int64
	err := row.Scan(&count)
	return count, err
}

const countSalesRoutes = `-- name: CountSalesRoutes :one
SELECT count(*) FROM sales_routes
WHERE ($1::bigint IS NULL OR sales_id = $1)
  AND ($2::text IS NULL OR status = $2)
  AND ($3::date IS NULL OR route_date >= $3)
  AND ($4::date IS NULL OR route_date <= $4)
`

type CountSalesRoutesParams struct {
	SalesID  pgtype.Int8 `json:"sales_id"`
	Status   pgtype.Text `json:"status"`
	DateFrom pgtype.Date `json:"date_from"`
	DateTo   pgtype.Date `json:"date_to"`
}

func (q *Queries) CountSalesRoutes(ctx context.Context, arg CountSalesRoutesParams) (int64, error) {
	row := q.db.QueryRow(ctx, countSalesRoutes,
		arg.SalesID,
		arg.Status,
		arg.DateFrom,
		arg.DateTo,
	)
	var count int64
	err := row.Scan(&count)
	return count, err
}

const countSalesVisits = `-- name: CountSalesVisits :one
SELECT count(*) FROM sales_visits v
WHERE ($1::bigint IS NULL OR v.sales_id = $1)
  AND ($2::text IS NULL OR v.status = $2)
  AND ($3::date IS NULL OR v.visit_date >= $3)
  AND ($4::date IS NULL OR v.visit_date <= $4)
  AND ($5::text IS NULL OR v.visit_type = $5)
`

type CountSalesVisitsParams struct {
	SalesID   pgtype.Int8 `json:"sales_id"`
	Status    pgtype.Text `json:"status"`
	DateFrom  pgtype.Date `json:"date_from"`
	DateTo    pgtype.Date `json:"date_to"`
	VisitType pgtype.Text `json:"visit_type"`
}

func (q *Queries) CountSalesVisits(ctx context.Context, arg CountSalesVisitsParams) (int64, error) {
	row := q.db.QueryRow(ctx, countSalesVisits,
		arg.SalesID,
		arg.Status,
		arg.DateFrom,
		arg.DateTo,
		arg.VisitType,
	)
	var count int64
	err := row.Scan(&count)
	return count, err
}

const createSalesActivity = `-- name: CreateSalesActivity :one
INSERT INTO sales_activities (sales_id, sales_visit_id, activity_date, activity_type,
       description, result, follow_up_date, follow_up_notes)
VALUES ($1,$2,$3,$4,$5,$6,$7,$8)
RETURNING id
`

type CreateSalesActivityParams struct {
	SalesID       pgtype.Int8 `json:"sales_id"`
	SalesVisitID  pgtype.Int8 `json:"sales_visit_id"`
	ActivityDate  pgtype.Date `json:"activity_date"`
	ActivityType  string      `json:"activity_type"`
	Description   pgtype.Text `json:"description"`
	Result        pgtype.Text `json:"result"`
	FollowUpDate  pgtype.Date `json:"follow_up_date"`
	FollowUpNotes pgtype.Text `json:"follow_up_notes"`
}

func (q *Queries) CreateSalesActivity(ctx context.Context, arg CreateSalesActivityParams) (int64, error) {
	row := q.db.QueryRow(ctx, createSalesActivity,
		arg.SalesID,
		arg.SalesVisitID,
		arg.ActivityDate,
		arg.ActivityType,
		arg.Description,
		arg.Result,
		arg.FollowUpDate,
		arg.FollowUpNotes,
	)
	var id int64
	err := row.Scan(&id)
	return id, err
}

const createSalesLocation = `-- name: CreateSalesLocation :exec
INSERT INTO sales_locations (sales_id, latitude, longitude, accuracy, speed,
       heading, battery_level, recorded_at)
VALUES ($1,$2,$3,$4,$5,$6,$7,$8)
`

type CreateSalesLocationParams struct {
	SalesID      pgtype.Int8         `json:"sales_id"`
	Latitude     decimal.NullDecimal `json:"latitude"`
	Longitude    decimal.NullDecimal `json:"longitude"`
	Accuracy     decimal.NullDecimal `json:"accuracy"`
	Speed        decimal.NullDecimal `json:"speed"`
	Heading      decimal.NullDecimal `json:"heading"`
	BatteryLevel pgtype.Int2         `json:"battery_level"`
	RecordedAt   pgtype.Timestamptz  `json:"recorded_at"`
}

func (q *Queries) CreateSalesLocation(ctx context.Context, arg CreateSalesLocationParams) error {
	_, err := q.db.Exec(ctx, createSalesLocation,
		arg.SalesID,
		arg.Latitude,
		arg.Longitude,
		arg.Accuracy,
		arg.Speed,
		arg.Heading,
		arg.BatteryLevel,
		arg.RecordedAt,
	)
	return err
}

const createSalesRoute = `-- name: CreateSalesRoute :one
INSERT INTO sales_routes (sales_id, route_date, name, planned_customers, status, notes)
VALUES ($1,$2,$3,$4,$5,$6)
RETURNING id
`

type CreateSalesRouteParams struct {
	SalesID          pgtype.Int8 `json:"sales_id"`
	RouteDate        pgtype.Date `json:"route_date"`
	Name             pgtype.Text `json:"name"`
	PlannedCustomers []byte      `json:"planned_customers"`
	Status           string      `json:"status"`
	Notes            pgtype.Text `json:"notes"`
}

func (q *Queries) CreateSalesRoute(ctx context.Context, arg CreateSalesRouteParams) (int64, error) {
	row := q.db.QueryRow(ctx, createSalesRoute,
		arg.SalesID,
		arg.RouteDate,
		arg.Name,
		arg.PlannedCustomers,
		arg.Status,
		arg.Notes,
	)
	var id int64
	err := row.Scan(&id)
	return id, err
}

const createSalesVisit = `-- name: CreateSalesVisit :one
INSERT INTO sales_visits (sales_id, customer_id, visit_date, purpose, result, notes, status, visit_type, scheduled_by)
VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9)
RETURNING id
`

type CreateSalesVisitParams struct {
	SalesID     pgtype.Int8 `json:"sales_id"`
	CustomerID  pgtype.Int8 `json:"customer_id"`
	VisitDate   pgtype.Date `json:"visit_date"`
	Purpose     pgtype.Text `json:"purpose"`
	Result      pgtype.Text `json:"result"`
	Notes       pgtype.Text `json:"notes"`
	Status      string      `json:"status"`
	VisitType   string      `json:"visit_type"`
	ScheduledBy pgtype.Int8 `json:"scheduled_by"`
}

func (q *Queries) CreateSalesVisit(ctx context.Context, arg CreateSalesVisitParams) (int64, error) {
	row := q.db.QueryRow(ctx, createSalesVisit,
		arg.SalesID,
		arg.CustomerID,
		arg.VisitDate,
		arg.Purpose,
		arg.Result,
		arg.Notes,
		arg.Status,
		arg.VisitType,
		arg.ScheduledBy,
	)
	var id int64
	err := row.Scan(&id)
	return id, err
}

const getSalesVisitByID = `-- name: GetSalesVisitByID :one
SELECT v.id, v.sales_id, v.customer_id, c.id, c.code, c.name, c.customer_type, c.credit_limit,
       v.visit_date, v.check_in_time, v.check_out_time, v.check_in_lat, v.check_in_lng,
       v.check_out_lat, v.check_out_lng, v.purpose, v.result, v.notes, v.sales_order_id, v.status,
       v.visit_type, v.scheduled_by
FROM sales_visits v LEFT JOIN customers c ON c.id = v.customer_id
WHERE v.id=$1
`

type GetSalesVisitByIDRow struct {
	ID           int64               `json:"id"`
	SalesID      pgtype.Int8         `json:"sales_id"`
	CustomerID   pgtype.Int8         `json:"customer_id"`
	ID_2         pgtype.Int8         `json:"id_2"`
	Code         pgtype.Text         `json:"code"`
	Name         pgtype.Text         `json:"name"`
	CustomerType pgtype.Text         `json:"customer_type"`
	CreditLimit  decimal.NullDecimal `json:"credit_limit"`
	VisitDate    pgtype.Date         `json:"visit_date"`
	CheckInTime  pgtype.Timestamptz  `json:"check_in_time"`
	CheckOutTime pgtype.Timestamptz  `json:"check_out_time"`
	CheckInLat   decimal.NullDecimal `json:"check_in_lat"`
	CheckInLng   decimal.NullDecimal `json:"check_in_lng"`
	CheckOutLat  decimal.NullDecimal `json:"check_out_lat"`
	CheckOutLng  decimal.NullDecimal `json:"check_out_lng"`
	Purpose      pgtype.Text         `json:"purpose"`
	Result       pgtype.Text         `json:"result"`
	Notes        pgtype.Text         `json:"notes"`
	SalesOrderID pgtype.Int8         `json:"sales_order_id"`
	Status       string              `json:"status"`
	VisitType    string              `json:"visit_type"`
	ScheduledBy  pgtype.Int8         `json:"scheduled_by"`
}

func (q *Queries) GetSalesVisitByID(ctx context.Context, id int64) (GetSalesVisitByIDRow, error) {
	row := q.db.QueryRow(ctx, getSalesVisitByID, id)
	var i GetSalesVisitByIDRow
	err := row.Scan(
		&i.ID,
		&i.SalesID,
		&i.CustomerID,
		&i.ID_2,
		&i.Code,
		&i.Name,
		&i.CustomerType,
		&i.CreditLimit,
		&i.VisitDate,
		&i.CheckInTime,
		&i.CheckOutTime,
		&i.CheckInLat,
		&i.CheckInLng,
		&i.CheckOutLat,
		&i.CheckOutLng,
		&i.Purpose,
		&i.Result,
		&i.Notes,
		&i.SalesOrderID,
		&i.Status,
		&i.VisitType,
		&i.ScheduledBy,
	)
	return i, err
}

const latestSalesLocations = `-- name: LatestSalesLocations :many
SELECT id, sales_id, latitude, longitude, accuracy, speed, heading, battery_level, recorded_at
FROM sales_locations
WHERE id IN (SELECT DISTINCT ON (sales_id) id FROM sales_locations ORDER BY sales_id, recorded_at DESC)
ORDER BY sales_id
`

type LatestSalesLocationsRow struct {
	ID           int64               `json:"id"`
	SalesID      pgtype.Int8         `json:"sales_id"`
	Latitude     decimal.NullDecimal `json:"latitude"`
	Longitude    decimal.NullDecimal `json:"longitude"`
	Accuracy     decimal.NullDecimal `json:"accuracy"`
	Speed        decimal.NullDecimal `json:"speed"`
	Heading      decimal.NullDecimal `json:"heading"`
	BatteryLevel pgtype.Int2         `json:"battery_level"`
	RecordedAt   pgtype.Timestamptz  `json:"recorded_at"`
}

func (q *Queries) LatestSalesLocations(ctx context.Context) ([]LatestSalesLocationsRow, error) {
	rows, err := q.db.Query(ctx, latestSalesLocations)
	if err != nil {
		return nil, err
	}
	defer rows.Close()
	var items []LatestSalesLocationsRow
	for rows.Next() {
		var i LatestSalesLocationsRow
		if err := rows.Scan(
			&i.ID,
			&i.SalesID,
			&i.Latitude,
			&i.Longitude,
			&i.Accuracy,
			&i.Speed,
			&i.Heading,
			&i.BatteryLevel,
			&i.RecordedAt,
		); err != nil {
			return nil, err
		}
		items = append(items, i)
	}
	if err := rows.Err(); err != nil {
		return nil, err
	}
	return items, nil
}

const listSalesEmployees = `-- name: ListSalesEmployees :many
SELECT id, name FROM employees
WHERE department = 'sales' AND is_active = true AND deleted_at IS NULL
ORDER BY name
`

type ListSalesEmployeesRow struct {
	ID   int64  `json:"id"`
	Name string `json:"name"`
}

func (q *Queries) ListSalesEmployees(ctx context.Context) ([]ListSalesEmployeesRow, error) {
	rows, err := q.db.Query(ctx, listSalesEmployees)
	if err != nil {
		return nil, err
	}
	defer rows.Close()
	var items []ListSalesEmployeesRow
	for rows.Next() {
		var i ListSalesEmployeesRow
		if err := rows.Scan(&i.ID, &i.Name); err != nil {
			return nil, err
		}
		items = append(items, i)
	}
	if err := rows.Err(); err != nil {
		return nil, err
	}
	return items, nil
}

const listSalesRoutes = `-- name: ListSalesRoutes :many
SELECT r.id, r.sales_id, r.route_date, r.name, r.planned_customers, r.status, r.notes,
       COALESCE(e.name, '') AS sales_name,
       COALESCE(jsonb_array_length(r.planned_customers), 0)::bigint AS location_count
FROM sales_routes r
LEFT JOIN employees e ON e.id = r.sales_id
WHERE ($3::bigint IS NULL OR r.sales_id = $3)
  AND ($4::text IS NULL OR r.status = $4)
  AND ($5::date IS NULL OR r.route_date >= $5)
  AND ($6::date IS NULL OR r.route_date <= $6)
ORDER BY r.route_date DESC, r.id DESC
LIMIT $1 OFFSET $2
`

type ListSalesRoutesParams struct {
	Limit    int32       `json:"limit"`
	Offset   int32       `json:"offset"`
	SalesID  pgtype.Int8 `json:"sales_id"`
	Status   pgtype.Text `json:"status"`
	DateFrom pgtype.Date `json:"date_from"`
	DateTo   pgtype.Date `json:"date_to"`
}

type ListSalesRoutesRow struct {
	ID               int64       `json:"id"`
	SalesID          pgtype.Int8 `json:"sales_id"`
	RouteDate        pgtype.Date `json:"route_date"`
	Name             pgtype.Text `json:"name"`
	PlannedCustomers []byte      `json:"planned_customers"`
	Status           string      `json:"status"`
	Notes            pgtype.Text `json:"notes"`
	SalesName        string      `json:"sales_name"`
	LocationCount    int64       `json:"location_count"`
}

func (q *Queries) ListSalesRoutes(ctx context.Context, arg ListSalesRoutesParams) ([]ListSalesRoutesRow, error) {
	rows, err := q.db.Query(ctx, listSalesRoutes,
		arg.Limit,
		arg.Offset,
		arg.SalesID,
		arg.Status,
		arg.DateFrom,
		arg.DateTo,
	)
	if err != nil {
		return nil, err
	}
	defer rows.Close()
	var items []ListSalesRoutesRow
	for rows.Next() {
		var i ListSalesRoutesRow
		if err := rows.Scan(
			&i.ID,
			&i.SalesID,
			&i.RouteDate,
			&i.Name,
			&i.PlannedCustomers,
			&i.Status,
			&i.Notes,
			&i.SalesName,
			&i.LocationCount,
		); err != nil {
			return nil, err
		}
		items = append(items, i)
	}
	if err := rows.Err(); err != nil {
		return nil, err
	}
	return items, nil
}

const listSalesVisits = `-- name: ListSalesVisits :many
SELECT v.id, v.sales_id, v.customer_id, c.id, c.code, c.name, c.customer_type, c.credit_limit,
       v.visit_date, v.check_in_time, v.check_out_time, v.check_in_lat, v.check_in_lng,
       v.check_out_lat, v.check_out_lng, v.purpose, v.result, v.notes, v.sales_order_id, v.status,
       v.visit_type, v.scheduled_by,
       COALESCE(e.name, '') AS sales_name
FROM sales_visits v LEFT JOIN customers c ON c.id = v.customer_id
LEFT JOIN employees e ON e.id = v.sales_id
WHERE ($3::bigint IS NULL OR v.sales_id = $3)
  AND ($4::text IS NULL OR v.status = $4)
  AND ($5::date IS NULL OR v.visit_date >= $5)
  AND ($6::date IS NULL OR v.visit_date <= $6)
  AND ($7::text IS NULL OR v.visit_type = $7)
ORDER BY v.visit_date DESC, v.id DESC
LIMIT $1 OFFSET $2
`

type ListSalesVisitsParams struct {
	Limit     int32       `json:"limit"`
	Offset    int32       `json:"offset"`
	SalesID   pgtype.Int8 `json:"sales_id"`
	Status    pgtype.Text `json:"status"`
	DateFrom  pgtype.Date `json:"date_from"`
	DateTo    pgtype.Date `json:"date_to"`
	VisitType pgtype.Text `json:"visit_type"`
}

type ListSalesVisitsRow struct {
	ID           int64               `json:"id"`
	SalesID      pgtype.Int8         `json:"sales_id"`
	CustomerID   pgtype.Int8         `json:"customer_id"`
	ID_2         pgtype.Int8         `json:"id_2"`
	Code         pgtype.Text         `json:"code"`
	Name         pgtype.Text         `json:"name"`
	CustomerType pgtype.Text         `json:"customer_type"`
	CreditLimit  decimal.NullDecimal `json:"credit_limit"`
	VisitDate    pgtype.Date         `json:"visit_date"`
	CheckInTime  pgtype.Timestamptz  `json:"check_in_time"`
	CheckOutTime pgtype.Timestamptz  `json:"check_out_time"`
	CheckInLat   decimal.NullDecimal `json:"check_in_lat"`
	CheckInLng   decimal.NullDecimal `json:"check_in_lng"`
	CheckOutLat  decimal.NullDecimal `json:"check_out_lat"`
	CheckOutLng  decimal.NullDecimal `json:"check_out_lng"`
	Purpose      pgtype.Text         `json:"purpose"`
	Result       pgtype.Text         `json:"result"`
	Notes        pgtype.Text         `json:"notes"`
	SalesOrderID pgtype.Int8         `json:"sales_order_id"`
	Status       string              `json:"status"`
	VisitType    string              `json:"visit_type"`
	ScheduledBy  pgtype.Int8         `json:"scheduled_by"`
	SalesName    string              `json:"sales_name"`
}

func (q *Queries) ListSalesVisits(ctx context.Context, arg ListSalesVisitsParams) ([]ListSalesVisitsRow, error) {
	rows, err := q.db.Query(ctx, listSalesVisits,
		arg.Limit,
		arg.Offset,
		arg.SalesID,
		arg.Status,
		arg.DateFrom,
		arg.DateTo,
		arg.VisitType,
	)
	if err != nil {
		return nil, err
	}
	defer rows.Close()
	var items []ListSalesVisitsRow
	for rows.Next() {
		var i ListSalesVisitsRow
		if err := rows.Scan(
			&i.ID,
			&i.SalesID,
			&i.CustomerID,
			&i.ID_2,
			&i.Code,
			&i.Name,
			&i.CustomerType,
			&i.CreditLimit,
			&i.VisitDate,
			&i.CheckInTime,
			&i.CheckOutTime,
			&i.CheckInLat,
			&i.CheckInLng,
			&i.CheckOutLat,
			&i.CheckOutLng,
			&i.Purpose,
			&i.Result,
			&i.Notes,
			&i.SalesOrderID,
			&i.Status,
			&i.VisitType,
			&i.ScheduledBy,
			&i.SalesName,
		); err != nil {
			return nil, err
		}
		items = append(items, i)
	}
	if err := rows.Err(); err != nil {
		return nil, err
	}
	return items, nil
}

const updateSalesVisit = `-- name: UpdateSalesVisit :execrows
UPDATE sales_visits SET check_in_time=$3, check_out_time=$4, check_in_lat=$5,
       check_in_lng=$6, check_out_lat=$7, check_out_lng=$8, result=$9, notes=$10, status=$11
WHERE id=$1 AND sales_id=$2
`

type UpdateSalesVisitParams struct {
	ID           int64               `json:"id"`
	SalesID      pgtype.Int8         `json:"sales_id"`
	CheckInTime  pgtype.Timestamptz  `json:"check_in_time"`
	CheckOutTime pgtype.Timestamptz  `json:"check_out_time"`
	CheckInLat   decimal.NullDecimal `json:"check_in_lat"`
	CheckInLng   decimal.NullDecimal `json:"check_in_lng"`
	CheckOutLat  decimal.NullDecimal `json:"check_out_lat"`
	CheckOutLng  decimal.NullDecimal `json:"check_out_lng"`
	Result       pgtype.Text         `json:"result"`
	Notes        pgtype.Text         `json:"notes"`
	Status       string              `json:"status"`
}

func (q *Queries) UpdateSalesVisit(ctx context.Context, arg UpdateSalesVisitParams) (int64, error) {
	result, err := q.db.Exec(ctx, updateSalesVisit,
		arg.ID,
		arg.SalesID,
		arg.CheckInTime,
		arg.CheckOutTime,
		arg.CheckInLat,
		arg.CheckInLng,
		arg.CheckOutLat,
		arg.CheckOutLng,
		arg.Result,
		arg.Notes,
		arg.Status,
	)
	if err != nil {
		return 0, err
	}
	return result.RowsAffected(), nil
}
