// Pure helpers for pmo_weekly_goals + pmo_daily_activities.
// All Date arithmetic uses UTC to avoid TZ surprises when persisting `date`
// columns in Postgres — the DB stores the calendar date as-is and the user's
// browser displays it in their local TZ.

export const WEEK_DAY_LABELS = ['Mo', 'Di', 'Mi', 'Do', 'Fr', 'Sa', 'So'] as const

export function getMondayOfWeek(d: Date): Date {
  const day = d.getUTCDay() // 0 = Sun, 1 = Mon, ..., 6 = Sat
  const offset = day === 0 ? -6 : 1 - day
  const monday = new Date(d)
  monday.setUTCDate(d.getUTCDate() + offset)
  monday.setUTCHours(0, 0, 0, 0)
  return monday
}

export function formatWeekKey(d: Date): string {
  return d.toISOString().slice(0, 10)
}

export function getWeekDays(monday: Date): Date[] {
  const out: Date[] = []
  for (let i = 0; i < 7; i++) {
    const d = new Date(monday)
    d.setUTCDate(monday.getUTCDate() + i)
    out.push(d)
  }
  return out
}

export function getWorkDays(monday: Date): Date[] {
  return getWeekDays(monday).slice(0, 5)
}

export function shiftWeek(monday: Date, weeks: number): Date {
  const d = new Date(monday)
  d.setUTCDate(monday.getUTCDate() + weeks * 7)
  return d
}

// ── Status enums (must mirror schema CHECK constraints) ────────────────────

export type GoalStatus = 'open' | 'in_progress' | 'done' | 'blocked' | 'rolled_over'
export type ActivityStatus = 'open' | 'in_progress' | 'done' | 'not_done' | 'rolled_over'

interface StatusOpt<T> {
  value: T
  label: string
}

export const STATUS_OPTIONS = {
  goal: [
    { value: 'open', label: 'Offen' },
    { value: 'in_progress', label: 'In Arbeit' },
    { value: 'done', label: 'Erledigt' },
    { value: 'blocked', label: 'Blockiert' },
    { value: 'rolled_over', label: 'Verschoben' },
  ] satisfies ReadonlyArray<StatusOpt<GoalStatus>>,
  activity: [
    { value: 'open', label: 'Offen' },
    { value: 'in_progress', label: 'In Arbeit' },
    { value: 'done', label: 'Erledigt' },
    { value: 'not_done', label: 'Nicht erledigt' },
    { value: 'rolled_over', label: 'Verschoben' },
  ] satisfies ReadonlyArray<StatusOpt<ActivityStatus>>,
} as const

const GOAL_STATUS_SET = new Set<string>(STATUS_OPTIONS.goal.map((s) => s.value))
const ACTIVITY_STATUS_SET = new Set<string>(STATUS_OPTIONS.activity.map((s) => s.value))

export function isValidGoalStatus(v: unknown): v is GoalStatus {
  return typeof v === 'string' && GOAL_STATUS_SET.has(v)
}

export function isValidActivityStatus(v: unknown): v is ActivityStatus {
  return typeof v === 'string' && ACTIVITY_STATUS_SET.has(v)
}

// ── Domain shapes used by client + server ──────────────────────────────────

export interface WeeklyGoal {
  id: string
  workstream_id: string
  arbeitspaket_id: string | null
  title: string
  description: string | null
  status: GoalStatus
  target_metric: string | null
  week_start: string // YYYY-MM-DD
}

export interface DailyActivity {
  id: string
  weekly_goal_id: string
  activity_date: string // YYYY-MM-DD
  title: string
  description: string | null
  owner_member_id: string | null
  status: ActivityStatus
  blocker: string | null
}
