-- 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')
AND de.surname <> 'Shahrasebhi'
ORDER BY de.firstname ASC;

-- name: GetWeeklyTimeSummaryForEmployee :many
WITH all_time_entries AS (
  SELECT
    DATE_TRUNC('week', "startDate") AS week_start,
    SUM("duration" / 60.0) as worked_hours,
    count(DISTINCT DATE_TRUNC('day', "startDate"))::float as worked_days,
    0::float AS sick_hours,
    0::float AS holiday_days
  FROM "WorkTime"
  WHERE 
    "startDate" BETWEEN @start_date AND @end_date
    AND "userId"::int = @employee_id
    AND "startDate" IS NOT NULL
  GROUP BY
    DATE_TRUNC('week', "startDate")

  UNION ALL

  SELECT 
    DATE_TRUNC('week', "start") AS week_start,
    0::float as worked_hours,
    0::float as worked_days,
    SUM("hours") AS sick_hours,
    0::float AS holiday_days
  FROM "Sickdays"
  WHERE 
    "start" BETWEEN @start_date AND @end_date 
    AND "employeeId" = @employee_id
    AND "start" IS NOT NULL
  GROUP BY
    DATE_TRUNC('week', "start")
  
  UNION ALL

  SELECT
    DATE_TRUNC('week', "date") AS week_start,
    0::float as worked_hours,
    0::float as worked_days,
    0::float AS sick_hours,
    count(*)::float AS holiday_days
  FROM "Holiday"
  WHERE 
    "date" BETWEEN @start_date AND @end_date
    AND "employeeId" = @employee_id
    AND "date" IS NOT NULL
  GROUP BY
    DATE_TRUNC('week', "date")
)
SELECT
  week_start::timestamp,
  SUM(worked_hours)::float AS total_worked_hours,
  SUM(worked_days)::float AS total_worked_days,
  SUM(sick_hours)::float AS total_sick_hours,
  SUM(holiday_days)::float AS total_holiday_days
FROM all_time_entries
GROUP BY
  week_start
ORDER BY
  week_start;

-- name: EvaluatePunctualityForEmployee :one
WITH
planned_start_times AS (
  SELECT
    DISTINCT ON ("startDate"::DATE)
    "startDate"::DATE AS plan_day,
    "startDate" AS planned_start_time
  FROM "PlannedTime" as p
  WHERE
    p."userId"::int = @employee_id::bigint
    AND p."startDate" BETWEEN @start_date AND @end_date
    AND p."startDate" IS NOT NULL
    AND p.department <> 'Fortbildung'
    AND p.note IS NULL
  ORDER BY
    "startDate"::DATE, "startDate" ASC
),
actual_start_times AS (
  SELECT
    DISTINCT ON ("startDate"::DATE)
    "startDate"::DATE AS work_day,
    "startDate" AS actual_start_time
  FROM "WorkTime"
  WHERE
    "userId"::int = @employee_id::bigint
    AND "startDate" BETWEEN @start_date AND @end_date
    AND "startDate" IS NOT NULL
  ORDER BY
    "startDate"::DATE, "startDate" ASC
),
daily_comparison AS (
  SELECT
    p.plan_day,
    p.planned_start_time,
    a.actual_start_time,
    (a.actual_start_time IS NOT NULL AND a.actual_start_time <= p.planned_start_time) AS was_punctual
  FROM planned_start_times p
  LEFT JOIN actual_start_times a ON p.plan_day = a.work_day
)
SELECT
  COUNT(CASE WHEN was_punctual THEN 1 END) AS punctual_days
FROM daily_comparison;

-- name: IsEmployeesDepartmentKTW :one
SELECT COALESCE(
  (
    bool_or(department LIKE '%KTW%')
    AND
    bool_and(department <> 'Leitstelle')
  ),
  false
)::bool as meets_requirements
FROM "PlannedTime"
WHERE
  "userId"::int = @employee_id::bigint
  AND "startDate" BETWEEN @start_date AND @end_date
  AND department IS NOT NULL;

-- name: CountVerpflegungspauschale :one
SELECT
  count(*)
FROM "WorkTime"
WHERE
  duration > 480
  AND "startDate" BETWEEN @start_date AND @end_date
  AND "userId"::int = @employee_id::bigint;

-- 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" >= @start_date
    AND "startDate" <= @end_date
    AND ("driverId" ILIKE @employee_id OR "codriverId" ILIKE @employee_id)
  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
),
TourenGeld AS (
  SELECT 
    SUM(tourengeld)::float as tourengeld
  FROM
    HighActivityDays
)
SELECT 
  COALESCE(tourengeld, 0.0)
FROM TourenGeld;