BEGIN;

-- 与 delivery 侧保持同版，供 consumer/delivery 双端使用同一套 homecare foundation schema。

CREATE TABLE IF NOT EXISTS public.ec_service_requests (
  id UUID PRIMARY KEY,
  user_id UUID NOT NULL,
  service_catalog_id TEXT NOT NULL DEFAULT '',
  service_name TEXT NOT NULL DEFAULT '',
  service_category TEXT NOT NULL DEFAULT '',
  elder_name TEXT NOT NULL DEFAULT '',
  elder_phone TEXT NOT NULL DEFAULT '',
  contact_name TEXT NOT NULL DEFAULT '',
  contact_phone TEXT NOT NULL DEFAULT '',
  address_snapshot JSONB,
  address_snapshot_json JSONB,
  scheduled_at TIMESTAMPTZ,
  remark TEXT NOT NULL DEFAULT '',
  status TEXT NOT NULL DEFAULT 'ORDER_CREATED',
  created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
  updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
);

CREATE TABLE IF NOT EXISTS public.ec_care_tasks (
  id UUID PRIMARY KEY,
  task_no TEXT NOT NULL UNIQUE,
  request_id UUID REFERENCES public.ec_service_requests(id) ON DELETE SET NULL,
  user_id UUID NOT NULL,
  assigned_to UUID,
  service_catalog_id TEXT NOT NULL DEFAULT '',
  service_name TEXT NOT NULL DEFAULT '',
  service_category TEXT NOT NULL DEFAULT '',
  service_snapshot_json JSONB NOT NULL DEFAULT '{}'::jsonb,
  elder_name TEXT NOT NULL DEFAULT '',
  elder_phone TEXT NOT NULL DEFAULT '',
  contact_name TEXT NOT NULL DEFAULT '',
  contact_phone TEXT NOT NULL DEFAULT '',
  address_snapshot JSONB,
  address_snapshot_json JSONB,
  scheduled_at TIMESTAMPTZ,
  appointment_time TIMESTAMPTZ,
  remark TEXT NOT NULL DEFAULT '',
  status TEXT NOT NULL DEFAULT 'ORDER_CREATED',
  reject_reason TEXT NOT NULL DEFAULT '',
  accepted_at TIMESTAMPTZ,
  departed_at TIMESTAMPTZ,
  checked_in_at TIMESTAMPTZ,
  service_started_at TIMESTAMPTZ,
  service_completed_at TIMESTAMPTZ,
  acceptance_pending_at TIMESTAMPTZ,
  accepted_by_family_at TIMESTAMPTZ,
  created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
  updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
);

CREATE TABLE IF NOT EXISTS public.ec_care_records (
  id TEXT PRIMARY KEY,
  task_id UUID NOT NULL REFERENCES public.ec_care_tasks(id) ON DELETE CASCADE,
  record_type TEXT NOT NULL DEFAULT 'service_record',
  care_record_type TEXT,
  created_by UUID,
  started_at TIMESTAMPTZ,
  finished_at TIMESTAMPTZ,
  checked_in_at TIMESTAMPTZ,
  checkin_time TIMESTAMPTZ,
  latitude DOUBLE PRECISION,
  longitude DOUBLE PRECISION,
  location_text TEXT NOT NULL DEFAULT '',
  duration_minutes INTEGER NOT NULL DEFAULT 0,
  actual_duration_minutes INTEGER NOT NULL DEFAULT 0,
  service_items_json JSONB NOT NULL DEFAULT '[]'::jsonb,
  service_content_json JSONB NOT NULL DEFAULT '[]'::jsonb,
  service_summary TEXT NOT NULL DEFAULT '',
  process_note TEXT NOT NULL DEFAULT '',
  summary TEXT NOT NULL DEFAULT '',
  content TEXT NOT NULL DEFAULT '',
  remark TEXT NOT NULL DEFAULT '',
  elder_status TEXT NOT NULL DEFAULT '',
  health_metrics_json JSONB NOT NULL DEFAULT '{}'::jsonb,
  materials_used TEXT NOT NULL DEFAULT '',
  abnormal_note TEXT NOT NULL DEFAULT '',
  photos_json JSONB NOT NULL DEFAULT '[]'::jsonb,
  staff_remark TEXT NOT NULL DEFAULT '',
  family_confirmation_json JSONB NOT NULL DEFAULT '{}'::jsonb,
  rating INTEGER,
  tags_json JSONB NOT NULL DEFAULT '[]'::jsonb,
  created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
  updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
);

CREATE TABLE IF NOT EXISTS public.hc_work_order_events (
  id TEXT PRIMARY KEY,
  task_id UUID NOT NULL REFERENCES public.ec_care_tasks(id) ON DELETE CASCADE,
  from_status TEXT,
  to_status TEXT NOT NULL DEFAULT '',
  actor_id UUID,
  actor_role TEXT NOT NULL DEFAULT '',
  action TEXT NOT NULL DEFAULT '',
  remark TEXT NOT NULL DEFAULT '',
  created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);

CREATE TABLE IF NOT EXISTS public.hc_work_order_exceptions (
  id TEXT PRIMARY KEY,
  task_id UUID NOT NULL REFERENCES public.ec_care_tasks(id) ON DELETE CASCADE,
  exception_type TEXT NOT NULL DEFAULT 'other',
  description TEXT NOT NULL DEFAULT '',
  occurred_at TIMESTAMPTZ,
  location_text TEXT NOT NULL DEFAULT '',
  images_json JSONB NOT NULL DEFAULT '[]'::jsonb,
  need_platform_intervention BOOLEAN NOT NULL DEFAULT false,
  request_cancel_order BOOLEAN NOT NULL DEFAULT false,
  request_reschedule BOOLEAN NOT NULL DEFAULT false,
  created_by UUID,
  created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
  updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
);

CREATE TABLE IF NOT EXISTS public.hc_evidence_files (
  id TEXT PRIMARY KEY,
  task_id UUID NOT NULL REFERENCES public.ec_care_tasks(id) ON DELETE CASCADE,
  care_record_id TEXT,
  phase TEXT NOT NULL DEFAULT 'service',
  file_type TEXT NOT NULL DEFAULT 'image',
  storage_path TEXT NOT NULL DEFAULT '',
  file_url TEXT NOT NULL DEFAULT '',
  latitude DOUBLE PRECISION,
  longitude DOUBLE PRECISION,
  captured_at TIMESTAMPTZ,
  created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);

CREATE INDEX IF NOT EXISTS idx_ec_service_requests_user_created
  ON public.ec_service_requests(user_id, created_at DESC);

CREATE INDEX IF NOT EXISTS idx_ec_care_tasks_user_created
  ON public.ec_care_tasks(user_id, created_at DESC);

CREATE INDEX IF NOT EXISTS idx_ec_care_tasks_assigned_status
  ON public.ec_care_tasks(assigned_to, status, created_at DESC);

CREATE INDEX IF NOT EXISTS idx_ec_care_records_task_created
  ON public.ec_care_records(task_id, created_at DESC);

CREATE INDEX IF NOT EXISTS idx_hc_work_order_events_task_created
  ON public.hc_work_order_events(task_id, created_at DESC);

CREATE INDEX IF NOT EXISTS idx_hc_work_order_exceptions_task_created
  ON public.hc_work_order_exceptions(task_id, created_at DESC);

CREATE INDEX IF NOT EXISTS idx_hc_evidence_files_task_created
  ON public.hc_evidence_files(task_id, created_at DESC);

CREATE OR REPLACE FUNCTION public.tg_ec_set_updated_at()
RETURNS trigger
LANGUAGE plpgsql
AS $$
BEGIN
  NEW.updated_at = now();
  RETURN NEW;
END;
$$;

DROP TRIGGER IF EXISTS trg_ec_service_requests_updated_at ON public.ec_service_requests;
CREATE TRIGGER trg_ec_service_requests_updated_at
BEFORE UPDATE ON public.ec_service_requests
FOR EACH ROW
EXECUTE FUNCTION public.tg_ec_set_updated_at();

DROP TRIGGER IF EXISTS trg_ec_care_tasks_updated_at ON public.ec_care_tasks;
CREATE TRIGGER trg_ec_care_tasks_updated_at
BEFORE UPDATE ON public.ec_care_tasks
FOR EACH ROW
EXECUTE FUNCTION public.tg_ec_set_updated_at();

DROP TRIGGER IF EXISTS trg_ec_care_records_updated_at ON public.ec_care_records;
CREATE TRIGGER trg_ec_care_records_updated_at
BEFORE UPDATE ON public.ec_care_records
FOR EACH ROW
EXECUTE FUNCTION public.tg_ec_set_updated_at();

DROP TRIGGER IF EXISTS trg_hc_work_order_exceptions_updated_at ON public.hc_work_order_exceptions;
CREATE TRIGGER trg_hc_work_order_exceptions_updated_at
BEFORE UPDATE ON public.hc_work_order_exceptions
FOR EACH ROW
EXECUTE FUNCTION public.tg_ec_set_updated_at();

ALTER TABLE public.ec_service_requests ENABLE ROW LEVEL SECURITY;
ALTER TABLE public.ec_care_tasks ENABLE ROW LEVEL SECURITY;
ALTER TABLE public.ec_care_records ENABLE ROW LEVEL SECURITY;
ALTER TABLE public.hc_work_order_events ENABLE ROW LEVEL SECURITY;
ALTER TABLE public.hc_work_order_exceptions ENABLE ROW LEVEL SECURITY;
ALTER TABLE public.hc_evidence_files ENABLE ROW LEVEL SECURITY;

DROP POLICY IF EXISTS ec_service_requests_owner_select ON public.ec_service_requests;
CREATE POLICY ec_service_requests_owner_select
  ON public.ec_service_requests
  FOR SELECT
  TO authenticated
  USING (user_id IN (SELECT id FROM public.ak_users WHERE auth_id = auth.uid()));

DROP POLICY IF EXISTS ec_service_requests_owner_insert ON public.ec_service_requests;
CREATE POLICY ec_service_requests_owner_insert
  ON public.ec_service_requests
  FOR INSERT
  TO authenticated
  WITH CHECK (user_id IN (SELECT id FROM public.ak_users WHERE auth_id = auth.uid()));

DROP POLICY IF EXISTS ec_service_requests_owner_update ON public.ec_service_requests;
CREATE POLICY ec_service_requests_owner_update
  ON public.ec_service_requests
  FOR UPDATE
  TO authenticated
  USING (user_id IN (SELECT id FROM public.ak_users WHERE auth_id = auth.uid()))
  WITH CHECK (user_id IN (SELECT id FROM public.ak_users WHERE auth_id = auth.uid()));

DROP POLICY IF EXISTS ec_care_tasks_owner_or_staff_select ON public.ec_care_tasks;
CREATE POLICY ec_care_tasks_owner_or_staff_select
  ON public.ec_care_tasks
  FOR SELECT
  TO authenticated
  USING (
    user_id IN (SELECT id FROM public.ak_users WHERE auth_id = auth.uid())
    OR assigned_to IN (SELECT id FROM public.ak_users WHERE auth_id = auth.uid())
  );

DROP POLICY IF EXISTS ec_care_tasks_owner_insert ON public.ec_care_tasks;
CREATE POLICY ec_care_tasks_owner_insert
  ON public.ec_care_tasks
  FOR INSERT
  TO authenticated
  WITH CHECK (user_id IN (SELECT id FROM public.ak_users WHERE auth_id = auth.uid()));

DROP POLICY IF EXISTS ec_care_tasks_owner_or_staff_update ON public.ec_care_tasks;
CREATE POLICY ec_care_tasks_owner_or_staff_update
  ON public.ec_care_tasks
  FOR UPDATE
  TO authenticated
  USING (
    user_id IN (SELECT id FROM public.ak_users WHERE auth_id = auth.uid())
    OR assigned_to IN (SELECT id FROM public.ak_users WHERE auth_id = auth.uid())
  )
  WITH CHECK (
    user_id IN (SELECT id FROM public.ak_users WHERE auth_id = auth.uid())
    OR assigned_to IN (SELECT id FROM public.ak_users WHERE auth_id = auth.uid())
  );

DROP POLICY IF EXISTS ec_care_records_task_access ON public.ec_care_records;
CREATE POLICY ec_care_records_task_access
  ON public.ec_care_records
  FOR ALL
  TO authenticated
  USING (
    task_id IN (
      SELECT t.id
      FROM public.ec_care_tasks t
      WHERE t.user_id IN (SELECT id FROM public.ak_users WHERE auth_id = auth.uid())
         OR t.assigned_to IN (SELECT id FROM public.ak_users WHERE auth_id = auth.uid())
    )
  )
  WITH CHECK (
    task_id IN (
      SELECT t.id
      FROM public.ec_care_tasks t
      WHERE t.user_id IN (SELECT id FROM public.ak_users WHERE auth_id = auth.uid())
         OR t.assigned_to IN (SELECT id FROM public.ak_users WHERE auth_id = auth.uid())
    )
  );

DROP POLICY IF EXISTS hc_work_order_events_task_access ON public.hc_work_order_events;
CREATE POLICY hc_work_order_events_task_access
  ON public.hc_work_order_events
  FOR ALL
  TO authenticated
  USING (
    task_id IN (
      SELECT t.id
      FROM public.ec_care_tasks t
      WHERE t.user_id IN (SELECT id FROM public.ak_users WHERE auth_id = auth.uid())
         OR t.assigned_to IN (SELECT id FROM public.ak_users WHERE auth_id = auth.uid())
    )
  )
  WITH CHECK (
    task_id IN (
      SELECT t.id
      FROM public.ec_care_tasks t
      WHERE t.user_id IN (SELECT id FROM public.ak_users WHERE auth_id = auth.uid())
         OR t.assigned_to IN (SELECT id FROM public.ak_users WHERE auth_id = auth.uid())
    )
  );

DROP POLICY IF EXISTS hc_work_order_exceptions_task_access ON public.hc_work_order_exceptions;
CREATE POLICY hc_work_order_exceptions_task_access
  ON public.hc_work_order_exceptions
  FOR ALL
  TO authenticated
  USING (
    task_id IN (
      SELECT t.id
      FROM public.ec_care_tasks t
      WHERE t.user_id IN (SELECT id FROM public.ak_users WHERE auth_id = auth.uid())
         OR t.assigned_to IN (SELECT id FROM public.ak_users WHERE auth_id = auth.uid())
    )
  )
  WITH CHECK (
    task_id IN (
      SELECT t.id
      FROM public.ec_care_tasks t
      WHERE t.user_id IN (SELECT id FROM public.ak_users WHERE auth_id = auth.uid())
         OR t.assigned_to IN (SELECT id FROM public.ak_users WHERE auth_id = auth.uid())
    )
  );

DROP POLICY IF EXISTS hc_evidence_files_task_access ON public.hc_evidence_files;
CREATE POLICY hc_evidence_files_task_access
  ON public.hc_evidence_files
  FOR ALL
  TO authenticated
  USING (
    task_id IN (
      SELECT t.id
      FROM public.ec_care_tasks t
      WHERE t.user_id IN (SELECT id FROM public.ak_users WHERE auth_id = auth.uid())
         OR t.assigned_to IN (SELECT id FROM public.ak_users WHERE auth_id = auth.uid())
    )
  )
  WITH CHECK (
    task_id IN (
      SELECT t.id
      FROM public.ec_care_tasks t
      WHERE t.user_id IN (SELECT id FROM public.ak_users WHERE auth_id = auth.uid())
         OR t.assigned_to IN (SELECT id FROM public.ak_users WHERE auth_id = auth.uid())
    )
  );

COMMIT;