-- Leave of Absence table
DO $$
BEGIN
  IF NOT EXISTS (SELECT 1 FROM pg_type WHERE typname = 'leave_type') THEN
    CREATE TYPE leave_type AS ENUM (
      'emergency_leave',
      'parental_leave',
      'sick_leave',
      'vacation_leave'
    );
  END IF;
END $$;

DO $$
BEGIN
  IF NOT EXISTS (SELECT 1 FROM pg_type WHERE typname = 'leave_status') THEN
    CREATE TYPE leave_status AS ENUM (
      'pending',
      'approved',
      'rejected',
      'cancelled'
    );
  END IF;
END $$;

CREATE TABLE IF NOT EXISTS leave_of_absence (
  id            UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  user_id       UUID NOT NULL REFERENCES auth.users(id) ON DELETE CASCADE,
  leave_type    leave_type NOT NULL,
  justification TEXT NOT NULL,
  start_time    TIMESTAMPTZ NOT NULL,
  end_time      TIMESTAMPTZ NOT NULL,
  status        leave_status NOT NULL DEFAULT 'pending',
  filed_by      UUID NOT NULL REFERENCES auth.users(id),
  created_at    TIMESTAMPTZ NOT NULL DEFAULT now(),
  updated_at    TIMESTAMPTZ NOT NULL DEFAULT now(),

  CONSTRAINT valid_time_range CHECK (end_time > start_time)
);

-- Indexes
CREATE INDEX IF NOT EXISTS idx_leave_user_id ON leave_of_absence(user_id);
CREATE INDEX IF NOT EXISTS idx_leave_start_time ON leave_of_absence(start_time);
CREATE INDEX IF NOT EXISTS idx_leave_status ON leave_of_absence(status);

-- RLS
ALTER TABLE leave_of_absence ENABLE ROW LEVEL SECURITY;

DROP POLICY IF EXISTS "Privileged users can view all leaves" ON leave_of_absence;
DROP POLICY IF EXISTS "Users can view own leaves" ON leave_of_absence;
DROP POLICY IF EXISTS "Privileged users can file own leaves" ON leave_of_absence;
DROP POLICY IF EXISTS "Users can file own leaves" ON leave_of_absence;
DROP POLICY IF EXISTS "Admins can approve or reject leaves" ON leave_of_absence;
DROP POLICY IF EXISTS "Users can cancel own future approved leaves" ON leave_of_absence;
DROP POLICY IF EXISTS "Admins can cancel future approved leaves" ON leave_of_absence;
DROP POLICY IF EXISTS "Privileged users can update leaves" ON leave_of_absence;
DROP POLICY IF EXISTS "Users can cancel own pending leaves" ON leave_of_absence;

-- Admin/dispatcher/it_staff can see all leaves
CREATE POLICY "Privileged users can view all leaves"
  ON leave_of_absence FOR SELECT
  USING (
    EXISTS (
      SELECT 1 FROM profiles
      WHERE profiles.id = auth.uid()
        AND profiles.role IN ('admin', 'dispatcher', 'it_staff')
    )
  );

-- All users can see their own leaves
CREATE POLICY "Users can view own leaves"
  ON leave_of_absence FOR SELECT
  USING (user_id = auth.uid());

-- Only admin/dispatcher/it_staff can file leaves (for themselves)
CREATE POLICY "Privileged users can file own leaves"
  ON leave_of_absence FOR INSERT
  WITH CHECK (
    user_id = auth.uid()
    AND filed_by = auth.uid()
    AND EXISTS (
      SELECT 1 FROM profiles
      WHERE profiles.id = auth.uid()
        AND profiles.role IN ('admin', 'dispatcher', 'it_staff')
    )
  );

-- Only admins can approve/reject pending leaves
CREATE POLICY "Admins can approve or reject leaves"
  ON leave_of_absence FOR UPDATE
  USING (
    status = 'pending'
    AND EXISTS (
      SELECT 1 FROM profiles
      WHERE profiles.id = auth.uid()
        AND profiles.role = 'admin'
    )
  )
  WITH CHECK (
    status IN ('approved', 'rejected')
  );

-- Users can cancel their own future approved leaves
CREATE POLICY "Users can cancel own future approved leaves"
  ON leave_of_absence FOR UPDATE
  USING (
    user_id = auth.uid()
    AND status = 'approved'
    AND start_time > now()
  )
  WITH CHECK (
    status = 'cancelled'
  );

-- Admins can cancel future approved leaves
CREATE POLICY "Admins can cancel future approved leaves"
  ON leave_of_absence FOR UPDATE
  USING (
    status = 'approved'
    AND start_time > now()
    AND EXISTS (
      SELECT 1 FROM profiles
      WHERE profiles.id = auth.uid()
        AND profiles.role = 'admin'
    )
  )
  WITH CHECK (
    status = 'cancelled'
  );

-- Drop legacy reason column if it exists from an earlier migration
ALTER TABLE leave_of_absence DROP COLUMN IF EXISTS reason;

-- Updated_at trigger
CREATE OR REPLACE FUNCTION update_leave_updated_at()
RETURNS TRIGGER AS $$
BEGIN
  NEW.updated_at = now();
  RETURN NEW;
END;
$$ LANGUAGE plpgsql;

DROP TRIGGER IF EXISTS trigger_leave_updated_at ON leave_of_absence;
CREATE TRIGGER trigger_leave_updated_at
  BEFORE UPDATE ON leave_of_absence
  FOR EACH ROW
  EXECUTE FUNCTION update_leave_updated_at();
