// Code generated by sqlc. DO NOT EDIT.
// versions:
//   sqlc v1.30.0
// source: payroll.sql

package database

import (
	"context"
	"time"

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

const countTourengeldAmountInPeriod = `-- name: CountTourengeldAmountInPeriod :one
WITH ToursInPeriod AS (
  SELECT 
    (("startDate" AT TIME ZONE 'UTC') AT TIME ZONE 'Europe/Berlin')::DATE as day,
    "operationId",
    "occupiedKm",
    CASE
      WHEN "occupiedKm" <= 30 THEN 1.0
      ELSE ROUND("occupiedKm" / 30.0)
    END AS tour_value,
    CASE
      WHEN EXTRACT(ISODOW FROM "startDate") = 6 AND "occupiedKm" <= 30 THEN 0.5
      ELSE 0.0
    END AS weekend_bonus,
    "infectionName",
    CASE
      WHEN "infectionName" = 'Covid-19' THEN 0.5
      ELSE 0.0
    END AS infection_bonus
  FROM
    "Tour"
  WHERE
    "check" <> 3 
    AND "deletedAt" IS NULL
    AND (
      "patientId" IS NULL
      OR "patientId" NOT IN (
        'b7424477-a4b2-42f7-b7e7-a4bef24f6979',
        '3554e1a9-9c07-45e5-b53c-692a77e4fa9a'
      )
    )
    -- ID's for Pause and Feierabend respectively
    AND (
      "carName" IS NULL
      OR "carName" NOT IN (
        'Storno',
        'Abgabe',
        'Löschen'
      )
      AND "carName" LIKE '%KTW%'
    )
    AND "startDate" >= $1
    AND "startDate" <= $2
    AND ("driverId" ILIKE $3 OR "codriverId" ILIKE $3)
  ORDER BY 
    "day"
),
DailyCounts AS (
  SELECT
    day,
    SUM(tour_value) + SUM(weekend_bonus) + SUM(infection_bonus) AS tour_amount
  FROM
    ToursInPeriod
  GROUP BY
    day
),
HighActivityDays AS (
  SELECT 
    day, 
    GREATEST(0, tour_amount - 6) AS tourengeld 
  FROM 
    DailyCounts
)
SELECT 
  SUM(tourengeld)::float as tourengeld
FROM
  HighActivityDays
`

type CountTourengeldAmountInPeriodParams struct {
	StartDate  time.Time   `json:"start_date"`
	EndDate    time.Time   `json:"end_date"`
	EmployeeID pgtype.Text `json:"employee_id"`
}

func (q *Queries) CountTourengeldAmountInPeriod(ctx context.Context, arg CountTourengeldAmountInPeriodParams) (float64, error) {
	row := q.db.QueryRow(ctx, countTourengeldAmountInPeriod, arg.StartDate, arg.EndDate, arg.EmployeeID)
	var tourengeld float64
	err := row.Scan(&tourengeld)
	return tourengeld, err
}

const fetchDrivenToursInInterval = `-- name: FetchDrivenToursInInterval :many
SELECT id, done, direction, "carName", "operationId", "driverId", "driverName", "codriverId", "codriverName", "patientId", "patientName", "patientSurname", "patientStreet", "patientZip", "patientCity", "healthInsurance", "healthInsuranceNumber", type, category, "transportType", "ordinanceType", "rangeEndDate", "startInstitution", "startStreet", "startZip", "startCity", "targetInstitution", "targetStreet", "targetZip", "targetCity", "startDate", "check", "occupiedKm", "totalKm", "startBegin", "startEnd", target, "targetBegin", empty, "hasInfection", "infectionName", "revenueDispoLive", "billDate", "billNumber", revenue, "consumptionCosts", "revenueDeviation", "createdAt", "deletedAt", "ticketId", "updatedAt" FROM "Tour"
WHERE "check" <> 3 
AND "deletedAt" IS NULL
AND (
  "patientId" IS NULL
  OR "patientId" NOT IN (
    'b7424477-a4b2-42f7-b7e7-a4bef24f6979',
    '3554e1a9-9c07-45e5-b53c-692a77e4fa9a'
  )
)
AND (
  "carName" IS NULL
  OR "carName" NOT IN (
    'Storno',
    'Abgabe',
    'Löschen'
  )
)
AND "startDate" >= $1
AND "startDate" <= $2
AND ("driverId" = $3 OR "codriverId" = $3)
ORDER BY "startDate" DESC
`

type FetchDrivenToursInIntervalParams struct {
	StartDate  time.Time   `json:"start_date"`
	EndDate    time.Time   `json:"end_date"`
	EmployeeID pgtype.Text `json:"employee_id"`
}

// ID's for Pause and Feierabend respectively
func (q *Queries) FetchDrivenToursInInterval(ctx context.Context, arg FetchDrivenToursInIntervalParams) ([]Tour, error) {
	rows, err := q.db.Query(ctx, fetchDrivenToursInInterval, arg.StartDate, arg.EndDate, arg.EmployeeID)
	if err != nil {
		return nil, err
	}
	defer rows.Close()
	var items []Tour
	for rows.Next() {
		var i Tour
		if err := rows.Scan(
			&i.ID,
			&i.Done,
			&i.Direction,
			&i.CarName,
			&i.OperationId,
			&i.DriverId,
			&i.DriverName,
			&i.CodriverId,
			&i.CodriverName,
			&i.PatientId,
			&i.PatientName,
			&i.PatientSurname,
			&i.PatientStreet,
			&i.PatientZip,
			&i.PatientCity,
			&i.HealthInsurance,
			&i.HealthInsuranceNumber,
			&i.Type,
			&i.Category,
			&i.TransportType,
			&i.OrdinanceType,
			&i.RangeEndDate,
			&i.StartInstitution,
			&i.StartStreet,
			&i.StartZip,
			&i.StartCity,
			&i.TargetInstitution,
			&i.TargetStreet,
			&i.TargetZip,
			&i.TargetCity,
			&i.StartDate,
			&i.Check,
			&i.OccupiedKm,
			&i.TotalKm,
			&i.StartBegin,
			&i.StartEnd,
			&i.Target,
			&i.TargetBegin,
			&i.Empty,
			&i.HasInfection,
			&i.InfectionName,
			&i.RevenueDispoLive,
			&i.BillDate,
			&i.BillNumber,
			&i.Revenue,
			&i.ConsumptionCosts,
			&i.RevenueDeviation,
			&i.CreatedAt,
			&i.DeletedAt,
			&i.TicketId,
			&i.UpdatedAt,
		); err != nil {
			return nil, err
		}
		items = append(items, i)
	}
	if err := rows.Err(); err != nil {
		return nil, err
	}
	return items, nil
}

const getEmployeeByName = `-- name: GetEmployeeByName :one
SELECT 
  dy.id as dyflexis_id, 
  dl.id as dispolive_id, 
  dy."contractSalaryHour" 
FROM "DyflexisEmployee" as dy
INNER JOIN
  "Employee" as dl ON dy.id::text = dl."personnelNumber" 
WHERE 
  TRIM(dy.firstname) = $1 AND 
  TRIM(dy.surname) = $2 AND
  "contractStart" < CURRENT_DATE AND 
  "contractEnd" > (CURRENT_DATE - INTERVAL '2 months')
ORDER BY dy."contractEnd" DESC
`

type GetEmployeeByNameParams struct {
	Firstname string `json:"firstname"`
	Lastname  string `json:"lastname"`
}

type GetEmployeeByNameRow struct {
	DyflexisID         int32   `json:"dyflexis_id"`
	DispoliveID        string  `json:"dispolive_id"`
	ContractSalaryHour float64 `json:"contractSalaryHour"`
}

func (q *Queries) GetEmployeeByName(ctx context.Context, arg GetEmployeeByNameParams) (GetEmployeeByNameRow, error) {
	row := q.db.QueryRow(ctx, getEmployeeByName, arg.Firstname, arg.Lastname)
	var i GetEmployeeByNameRow
	err := row.Scan(&i.DyflexisID, &i.DispoliveID, &i.ContractSalaryHour)
	return i, err
}

const getEmployeeDyflexis = `-- name: GetEmployeeDyflexis :one
SELECT id, firstname, surname, "contractStart", "contractEnd", "contractHoursWeek", "contractSalaryHour", "contractTypeName", "internalId" FROM "DyflexisEmployee"
WHERE 
  id = $1 AND 
  "contractStart" < CURRENT_DATE AND 
  "contractEnd" > (CURRENT_DATE - INTERVAL '2 months')
LIMIT 1
`

func (q *Queries) GetEmployeeDyflexis(ctx context.Context, id int32) (DyflexisEmployee, error) {
	row := q.db.QueryRow(ctx, getEmployeeDyflexis, id)
	var i DyflexisEmployee
	err := row.Scan(
		&i.ID,
		&i.Firstname,
		&i.Surname,
		&i.ContractStart,
		&i.ContractEnd,
		&i.ContractHoursWeek,
		&i.ContractSalaryHour,
		&i.ContractTypeName,
		&i.InternalId,
	)
	return i, err
}

const getSicknessSummaryForEmployeeInPeriod = `-- name: GetSicknessSummaryForEmployeeInPeriod :one
WITH pt AS (
  SELECT 
    COUNT(*) as days,
    COALESCE(sum(duration), 0)::bigint as minutes
  FROM "PlannedTime"
  WHERE "userId" = $1 AND "startDate" > $2 AND "startDate" < $3 AND note = 'sick'
)
SELECT
  pt.days,
  (minutes / 60)::float as hours,
  pt.minutes
FROM pt
`

type GetSicknessSummaryForEmployeeInPeriodParams struct {
	EmployeeID string     `json:"employee_id"`
	StartDate  *time.Time `json:"start_date"`
	EndDate    *time.Time `json:"end_date"`
}

type GetSicknessSummaryForEmployeeInPeriodRow struct {
	Days    int64   `json:"days"`
	Hours   float64 `json:"hours"`
	Minutes int64   `json:"minutes"`
}

func (q *Queries) GetSicknessSummaryForEmployeeInPeriod(ctx context.Context, arg GetSicknessSummaryForEmployeeInPeriodParams) (GetSicknessSummaryForEmployeeInPeriodRow, error) {
	row := q.db.QueryRow(ctx, getSicknessSummaryForEmployeeInPeriod, arg.EmployeeID, arg.StartDate, arg.EndDate)
	var i GetSicknessSummaryForEmployeeInPeriodRow
	err := row.Scan(&i.Days, &i.Hours, &i.Minutes)
	return i, err
}

const getWorkSummaryForEmployeeInPeriod = `-- name: GetWorkSummaryForEmployeeInPeriod :one
WITH wt AS (
  SELECT 
    COUNT(*) as days,
    COALESCE(sum(duration), 0)::bigint as minutes
  FROM "WorkTime"
  WHERE "userId" = $1 AND "startDate" > $2 AND "startDate" < $3
)
SELECT
  wt.days,
  (minutes / 60.0)::float as hours,
  wt.minutes
FROM wt
`

type GetWorkSummaryForEmployeeInPeriodParams struct {
	EmployeeID string     `json:"employee_id"`
	StartDate  *time.Time `json:"start_date"`
	EndDate    *time.Time `json:"end_date"`
}

type GetWorkSummaryForEmployeeInPeriodRow struct {
	Days    int64   `json:"days"`
	Hours   float64 `json:"hours"`
	Minutes int64   `json:"minutes"`
}

func (q *Queries) GetWorkSummaryForEmployeeInPeriod(ctx context.Context, arg GetWorkSummaryForEmployeeInPeriodParams) (GetWorkSummaryForEmployeeInPeriodRow, error) {
	row := q.db.QueryRow(ctx, getWorkSummaryForEmployeeInPeriod, arg.EmployeeID, arg.StartDate, arg.EndDate)
	var i GetWorkSummaryForEmployeeInPeriodRow
	err := row.Scan(&i.Days, &i.Hours, &i.Minutes)
	return i, err
}

const listActiveEmployees = `-- name: ListActiveEmployees :many
SELECT 
  de.id, 
  de.firstname, 
  de.surname, 
  de."contractStart", 
  de."contractEnd", 
  de."contractHoursWeek", 
  de."contractSalaryHour",
  de."contractTypeName",
  e.id as "dlId",
  e."personTransportCertificate"
FROM "DyflexisEmployee" as de
INNER JOIN "Employee" as e ON de.id::text = e."personnelNumber"
WHERE de."contractStart" < CURRENT_DATE AND de."contractEnd" > (CURRENT_DATE - INTERVAL '2 months')
`

type ListActiveEmployeesRow struct {
	ID                         int32       `json:"id"`
	Firstname                  string      `json:"firstname"`
	Surname                    string      `json:"surname"`
	ContractStart              time.Time   `json:"contractStart"`
	ContractEnd                *time.Time  `json:"contractEnd"`
	ContractHoursWeek          float64     `json:"contractHoursWeek"`
	ContractSalaryHour         float64     `json:"contractSalaryHour"`
	ContractTypeName           pgtype.Text `json:"contractTypeName"`
	DlId                       string      `json:"dlId"`
	PersonTransportCertificate *time.Time  `json:"personTransportCertificate"`
}

func (q *Queries) ListActiveEmployees(ctx context.Context) ([]ListActiveEmployeesRow, error) {
	rows, err := q.db.Query(ctx, listActiveEmployees)
	if err != nil {
		return nil, err
	}
	defer rows.Close()
	var items []ListActiveEmployeesRow
	for rows.Next() {
		var i ListActiveEmployeesRow
		if err := rows.Scan(
			&i.ID,
			&i.Firstname,
			&i.Surname,
			&i.ContractStart,
			&i.ContractEnd,
			&i.ContractHoursWeek,
			&i.ContractSalaryHour,
			&i.ContractTypeName,
			&i.DlId,
			&i.PersonTransportCertificate,
		); err != nil {
			return nil, err
		}
		items = append(items, i)
	}
	if err := rows.Err(); err != nil {
		return nil, err
	}
	return items, nil
}

const listPlannedTimesForEmployeeInPeriod = `-- name: ListPlannedTimesForEmployeeInPeriod :many
SELECT 
  DISTINCT ON (day)
  "startDate"::DATE as day,
  "startDate",
  "endDate",
  department,
  pause,
  duration
FROM "PlannedTime"
WHERE 
  "userId" = $1 AND 
  "startDate" > $2 AND 
  "startDate" < $3 AND 
  department <> 'Fortbildung' AND
  note IS NULL
ORDER BY "day"
`

type ListPlannedTimesForEmployeeInPeriodParams struct {
	EmployeeID string     `json:"employee_id"`
	StartDate  *time.Time `json:"start_date"`
	EndDate    *time.Time `json:"end_date"`
}

type ListPlannedTimesForEmployeeInPeriodRow struct {
	Day        pgtype.Date `json:"day"`
	StartDate  *time.Time  `json:"startDate"`
	EndDate    *time.Time  `json:"endDate"`
	Department pgtype.Text `json:"department"`
	Pause      int32       `json:"pause"`
	Duration   int32       `json:"duration"`
}

func (q *Queries) ListPlannedTimesForEmployeeInPeriod(ctx context.Context, arg ListPlannedTimesForEmployeeInPeriodParams) ([]ListPlannedTimesForEmployeeInPeriodRow, error) {
	rows, err := q.db.Query(ctx, listPlannedTimesForEmployeeInPeriod, arg.EmployeeID, arg.StartDate, arg.EndDate)
	if err != nil {
		return nil, err
	}
	defer rows.Close()
	var items []ListPlannedTimesForEmployeeInPeriodRow
	for rows.Next() {
		var i ListPlannedTimesForEmployeeInPeriodRow
		if err := rows.Scan(
			&i.Day,
			&i.StartDate,
			&i.EndDate,
			&i.Department,
			&i.Pause,
			&i.Duration,
		); err != nil {
			return nil, err
		}
		items = append(items, i)
	}
	if err := rows.Err(); err != nil {
		return nil, err
	}
	return items, nil
}

const listWorkTimesForEmployeeInPeriod = `-- name: ListWorkTimesForEmployeeInPeriod :many
SELECT id, "userId", firstname, surname, "startDate", "endDate", department, pause, duration FROM "WorkTime"
WHERE "userId" = $1 AND "startDate" > $2 AND "startDate" < $3
`

type ListWorkTimesForEmployeeInPeriodParams struct {
	EmployeeID string     `json:"employee_id"`
	StartDate  *time.Time `json:"start_date"`
	EndDate    *time.Time `json:"end_date"`
}

func (q *Queries) ListWorkTimesForEmployeeInPeriod(ctx context.Context, arg ListWorkTimesForEmployeeInPeriodParams) ([]WorkTime, error) {
	rows, err := q.db.Query(ctx, listWorkTimesForEmployeeInPeriod, arg.EmployeeID, arg.StartDate, arg.EndDate)
	if err != nil {
		return nil, err
	}
	defer rows.Close()
	var items []WorkTime
	for rows.Next() {
		var i WorkTime
		if err := rows.Scan(
			&i.ID,
			&i.UserId,
			&i.Firstname,
			&i.Surname,
			&i.StartDate,
			&i.EndDate,
			&i.Department,
			&i.Pause,
			&i.Duration,
		); err != nil {
			return nil, err
		}
		items = append(items, i)
	}
	if err := rows.Err(); err != nil {
		return nil, err
	}
	return items, nil
}
