BEGIN;

CREATE OR REPLACE FUNCTION public.homecare_is_arrival_pending_status(p_status TEXT)
RETURNS BOOLEAN
LANGUAGE sql
IMMUTABLE
AS $$
    SELECT upper(coalesce(trim(p_status), '')) IN (
        'ARRIVAL_PENDING',
        'WAITING_CONSUMER_CONFIRM',
        'WAITING_ARRIVAL_CONFIRM'
    )
$$;

CREATE OR REPLACE FUNCTION public.homecare_sync_arrival_pending_from_confirmation()
RETURNS trigger
LANGUAGE plpgsql
SET search_path = public
AS $$
BEGIN
    IF NEW.confirmation_type = 'ARRIVAL'
       AND upper(coalesce(NEW.status, '')) IN ('PENDING', 'WAITING', 'ARRIVAL_PENDING') THEN
        UPDATE public.ec_care_tasks
        SET
            status = 'ARRIVAL_PENDING',
            checked_in_at = COALESCE(checked_in_at, NEW.created_at),
            updated_at = now()
        WHERE id = NEW.work_order_id
          AND coalesce(status, '') <> 'ARRIVAL_PENDING';
    END IF;

    RETURN NEW;
END;
$$;

DROP TRIGGER IF EXISTS trg_homecare_sync_arrival_pending_from_confirmation
ON public.hc_work_order_confirmations;

CREATE TRIGGER trg_homecare_sync_arrival_pending_from_confirmation
AFTER INSERT OR UPDATE OF status
ON public.hc_work_order_confirmations
FOR EACH ROW
EXECUTE FUNCTION public.homecare_sync_arrival_pending_from_confirmation();

CREATE OR REPLACE FUNCTION public.homecare_find_related_work_order_id(p_order JSONB)
RETURNS UUID
LANGUAGE plpgsql
STABLE
SET search_path = public
AS $$
DECLARE
    v_id_text TEXT := coalesce(p_order ->> 'resolvedWorkOrderId', p_order ->> 'workOrderId', p_order ->> 'work_order_id', p_order ->> 'id', '');
    v_request_id TEXT := coalesce(p_order ->> 'requestId', p_order ->> 'request_id', '');
    v_order_no TEXT := coalesce(p_order ->> 'orderNo', p_order ->> 'order_no', '');
    v_work_order_id UUID;
BEGIN
    BEGIN
        IF v_id_text ~* '^[0-9a-f-]{36}$' THEN
            RETURN v_id_text::uuid;
        END IF;
    EXCEPTION WHEN OTHERS THEN
        NULL;
    END;

    BEGIN
        SELECT t.id
        INTO v_work_order_id
        FROM public.ec_care_tasks t
        WHERE (v_request_id <> '' AND coalesce(t.request_id::text, '') = v_request_id)
           OR (v_order_no <> '' AND coalesce(t.task_no, '') = v_order_no)
        ORDER BY coalesce(t.updated_at, t.created_at) DESC, t.created_at DESC
        LIMIT 1;
    EXCEPTION WHEN undefined_table OR undefined_column THEN
        v_work_order_id := NULL;
    END;

    RETURN v_work_order_id;
END;
$$;

CREATE OR REPLACE FUNCTION public.homecare_apply_arrival_pending_order(p_order JSONB)
RETURNS JSONB
LANGUAGE plpgsql
STABLE
SET search_path = public
AS $$
DECLARE
    v_order JSONB := coalesce(p_order, '{}'::jsonb);
    v_status TEXT := coalesce(v_order ->> 'status', '');
    v_original_status TEXT := coalesce(v_order ->> 'status', '');
    v_waiting BOOLEAN := lower(coalesce(v_order ->> 'waitingConsumerConfirm', v_order ->> 'waiting_consumer_confirm', 'false')) = 'true';
    v_has_pending_log BOOLEAN := false;
    v_has_pending_timeline BOOLEAN := false;
    v_work_order_id UUID;
    v_confirmation_status TEXT := '';
    v_time_text TEXT := coalesce(v_order ->> 'checkinTime', v_order ->> 'arriveTime', v_order ->> 'updatedAt', v_order ->> 'createdAt', '');
    v_timeline_item JSONB;
    v_status_log_item JSONB;
BEGIN
    IF jsonb_typeof(v_order -> 'statusLog') = 'array' THEN
        SELECT EXISTS (
            SELECT 1
            FROM jsonb_array_elements(v_order -> 'statusLog') AS item
            WHERE public.homecare_is_arrival_pending_status(coalesce(item ->> 'toStatus', item ->> 'to_status', item ->> 'status', ''))
        )
        INTO v_has_pending_log;
    END IF;

    IF jsonb_typeof(v_order -> 'timeline') = 'array' THEN
        SELECT EXISTS (
            SELECT 1
            FROM jsonb_array_elements(v_order -> 'timeline') AS item
            WHERE position('等待消费者确认到达' IN coalesce(item ->> 'title', '')) > 0
        )
        INTO v_has_pending_timeline;
    END IF;

    IF NOT v_waiting AND NOT public.homecare_is_arrival_pending_status(v_status) AND NOT v_has_pending_log THEN
        v_work_order_id := public.homecare_find_related_work_order_id(v_order);
        IF v_work_order_id IS NOT NULL THEN
            BEGIN
                SELECT upper(coalesce(c.status, ''))
                INTO v_confirmation_status
                FROM public.hc_work_order_confirmations c
                WHERE c.work_order_id = v_work_order_id
                  AND c.confirmation_type = 'ARRIVAL'
                ORDER BY coalesce(c.updated_at, c.created_at) DESC, c.created_at DESC
                LIMIT 1;
            EXCEPTION WHEN undefined_table OR undefined_column THEN
                v_confirmation_status := '';
            END;

            IF v_confirmation_status IN ('PENDING', 'WAITING', 'ARRIVAL_PENDING') THEN
                v_waiting := true;
            END IF;
        END IF;
    END IF;

    IF v_waiting OR public.homecare_is_arrival_pending_status(v_status) OR v_has_pending_log THEN
        v_order := v_order || jsonb_build_object(
            'status', 'ARRIVAL_PENDING',
            'statusText', '等待消费者确认到达',
            'statusTone', 'warning',
            'waitingConsumerConfirm', true
        );

        IF NOT v_has_pending_timeline THEN
            v_timeline_item := jsonb_build_object(
                'id', coalesce(v_order ->> 'id', 'order') || '-arrival-pending',
                'title', '等待消费者确认到达',
                'time', v_time_text,
                'description', '服务人员已提交到达签到，请确认其是否已到达服务地点'
            );
            v_order := jsonb_set(
                v_order,
                '{timeline}',
                jsonb_build_array(v_timeline_item) || coalesce(v_order -> 'timeline', '[]'::jsonb)
            );
        END IF;

        IF NOT v_has_pending_log THEN
            v_status_log_item := jsonb_build_object(
                'id', coalesce(v_order ->> 'id', 'order') || '-arrival-pending',
                'orderId', coalesce(v_order ->> 'id', ''),
                'fromStatus', v_original_status,
                'toStatus', 'ARRIVAL_PENDING',
                'operatorRole', 'delivery',
                'operatorId', '',
                'remark', '服务人员已提交到达签到，等待消费者确认',
                'createdAt', v_time_text
            );
            v_order := jsonb_set(
                v_order,
                '{statusLog}',
                jsonb_build_array(v_status_log_item) || coalesce(v_order -> 'statusLog', '[]'::jsonb)
            );
        END IF;
    END IF;

    RETURN v_order;
END;
$$;

CREATE OR REPLACE FUNCTION public.delivery_get_legacy_order_json(p_order_id TEXT)
RETURNS JSONB
LANGUAGE plpgsql
STABLE
SECURITY DEFINER
SET search_path = public
AS $$
DECLARE
    v_staff_id UUID := public.delivery_current_staff_id();
    v_raw JSONB;
    v_logs JSONB := '[]'::jsonb;
    v_records JSONB := '[]'::jsonb;
    v_evidence JSONB := '[]'::jsonb;
BEGIN
    SELECT to_jsonb(o)
    INTO v_raw
    FROM public.hss_service_orders o
    WHERE o.id = p_order_id
      AND o.deleted_at IS NULL
      AND (v_staff_id IS NULL OR o.current_staff_id = v_staff_id)
    LIMIT 1;

    IF v_raw IS NULL THEN
        RETURN NULL;
    END IF;

    SELECT coalesce(jsonb_agg(to_jsonb(l) ORDER BY l.created_at DESC), '[]'::jsonb)
    INTO v_logs
    FROM public.hss_service_order_status_logs l
    WHERE l.order_id = p_order_id;

    SELECT coalesce(jsonb_agg(to_jsonb(r) ORDER BY r.created_at DESC), '[]'::jsonb)
    INTO v_records
    FROM public.hss_service_execution_records r
    WHERE r.order_id = p_order_id;

    SELECT coalesce(jsonb_agg(to_jsonb(e) ORDER BY e.created_at DESC), '[]'::jsonb)
    INTO v_evidence
    FROM public.hss_service_evidence_files e
    WHERE e.order_id = p_order_id;

    RETURN public.homecare_apply_arrival_pending_order(
        public.delivery_build_order_json(v_raw, v_logs, v_records, v_evidence, NULL, 'legacy')
    );
END;
$$;

CREATE OR REPLACE FUNCTION public.delivery_get_care_order_json(p_order_id TEXT)
RETURNS JSONB
LANGUAGE plpgsql
STABLE
SECURITY DEFINER
SET search_path = public
AS $$
DECLARE
    v_user_id UUID := public.delivery_current_user_id();
    v_raw JSONB;
    v_request JSONB;
    v_logs JSONB := '[]'::jsonb;
    v_records JSONB := '[]'::jsonb;
    v_evidence JSONB := '[]'::jsonb;
    v_exception JSONB;
BEGIN
    IF NOT public.delivery_table_exists('ec_care_tasks') THEN
        RETURN NULL;
    END IF;

    BEGIN
        EXECUTE 'SELECT to_jsonb(t) FROM public.ec_care_tasks t WHERE t.id = $1::uuid AND ($2 IS NULL OR t.assigned_to = $2) LIMIT 1'
        INTO v_raw
        USING p_order_id, v_user_id;
    EXCEPTION WHEN OTHERS THEN
        RETURN NULL;
    END;

    IF v_raw IS NULL THEN
        RETURN NULL;
    END IF;

    BEGIN
        IF public.delivery_table_exists('ec_service_requests')
           AND coalesce(v_raw ->> 'request_id', '') <> '' THEN
            EXECUTE 'SELECT to_jsonb(r) FROM public.ec_service_requests r WHERE r.id = $1::uuid LIMIT 1'
            INTO v_request
            USING (v_raw ->> 'request_id');
        END IF;
    EXCEPTION WHEN OTHERS THEN
        v_request := NULL;
    END;

    IF v_request IS NOT NULL THEN
        v_raw := v_raw || jsonb_strip_nulls(
            jsonb_build_object(
                'service_name', coalesce(nullif(v_raw ->> 'service_name', ''), nullif(v_request ->> 'service_name', '')),
                'service_category', coalesce(nullif(v_raw ->> 'service_category', ''), nullif(v_request ->> 'service_category', '')),
                'elder_name', coalesce(nullif(v_raw ->> 'elder_name', ''), nullif(v_request ->> 'elder_name', '')),
                'elder_phone', coalesce(nullif(v_raw ->> 'elder_phone', ''), nullif(v_request ->> 'elder_phone', '')),
                'contact_name', coalesce(nullif(v_raw ->> 'contact_name', ''), nullif(v_request ->> 'contact_name', '')),
                'contact_phone', coalesce(nullif(v_raw ->> 'contact_phone', ''), nullif(v_request ->> 'contact_phone', '')),
                'remark', coalesce(nullif(v_raw ->> 'remark', ''), nullif(v_request ->> 'remark', '')),
                'scheduled_at', coalesce(nullif(v_raw ->> 'scheduled_at', ''), nullif(v_request ->> 'scheduled_at', '')),
                'appointment_time', coalesce(nullif(v_raw ->> 'appointment_time', ''), nullif(v_request ->> 'scheduled_at', '')),
                'service_snapshot_json', coalesce(
                    nullif(v_raw -> 'service_snapshot_json', '{}'::jsonb),
                    nullif(v_request -> 'service_snapshot_json', '{}'::jsonb),
                    jsonb_build_object('category', coalesce(v_request ->> 'service_category', ''), 'price', 0)
                ),
                'address_snapshot_json', coalesce(
                    nullif(v_raw -> 'address_snapshot_json', '{}'::jsonb),
                    nullif(v_raw -> 'address_snapshot', '{}'::jsonb),
                    nullif(v_request -> 'address_snapshot_json', '{}'::jsonb),
                    nullif(v_request -> 'address_snapshot', '{}'::jsonb)
                )
            )
        );
    END IF;

    BEGIN
        IF public.delivery_table_exists('hc_work_order_events') THEN
            EXECUTE 'SELECT coalesce(jsonb_agg(to_jsonb(e) ORDER BY e.created_at DESC), ''[]''::jsonb) FROM public.hc_work_order_events e WHERE e.work_order_id = $1::uuid'
            INTO v_logs
            USING p_order_id;
        END IF;
        IF public.delivery_table_exists('ec_care_records') THEN
            EXECUTE 'SELECT coalesce(jsonb_agg(to_jsonb(r) ORDER BY r.created_at DESC), ''[]''::jsonb) FROM public.ec_care_records r WHERE r.task_id = $1::uuid'
            INTO v_records
            USING p_order_id;
        END IF;
        IF public.delivery_table_exists('hc_evidence_files') THEN
            EXECUTE 'SELECT coalesce(jsonb_agg(to_jsonb(f) ORDER BY f.created_at DESC), ''[]''::jsonb) FROM public.hc_evidence_files f WHERE f.work_order_id = $1::uuid'
            INTO v_evidence
            USING p_order_id;
        END IF;
        IF public.delivery_table_exists('hc_work_order_exceptions') THEN
            EXECUTE 'SELECT to_jsonb(x) FROM public.hc_work_order_exceptions x WHERE x.work_order_id = $1::uuid ORDER BY x.created_at DESC LIMIT 1'
            INTO v_exception
            USING p_order_id;
        END IF;
    EXCEPTION WHEN OTHERS THEN
        NULL;
    END;

    RETURN public.homecare_apply_arrival_pending_order(
        public.delivery_build_order_json(v_raw, v_logs, v_records, v_evidence, v_exception, 'care')
    );
END;
$$;

CREATE OR REPLACE FUNCTION public.rpc_delivery_order_detail(p_order_id TEXT)
RETURNS JSONB
LANGUAGE plpgsql
STABLE
SECURITY DEFINER
SET search_path = public
AS $$
BEGIN
    IF auth.uid() IS NULL THEN
        RAISE EXCEPTION 'Permission denied';
    END IF;
    RETURN public.homecare_apply_arrival_pending_order(public.delivery_get_order_json(p_order_id));
END;
$$;

CREATE OR REPLACE FUNCTION public.rpc_delivery_order_list(
    p_staff_id UUID DEFAULT NULL,
    p_tab TEXT DEFAULT 'all',
    p_keyword TEXT DEFAULT ''
)
RETURNS JSONB
LANGUAGE plpgsql
STABLE
SECURITY DEFINER
SET search_path = public
AS $$
DECLARE
    v_user_id UUID := public.delivery_current_user_id();
    v_staff_id UUID := COALESCE(p_staff_id, public.delivery_current_staff_id());
    v_result JSONB := '[]'::jsonb;
    v_task JSONB;
    v_order JSONB;
    v_order_id TEXT;
BEGIN
    PERFORM public.delivery_assert_staff_access(v_staff_id);

    IF public.delivery_table_exists('ec_care_tasks') THEN
        BEGIN
            FOR v_task IN
                EXECUTE 'SELECT to_jsonb(t) FROM public.ec_care_tasks t WHERE ($1 IS NULL OR t.assigned_to = $1) ORDER BY t.created_at DESC'
                USING v_user_id
            LOOP
                v_order := public.homecare_apply_arrival_pending_order(
                    public.delivery_get_care_order_json(v_task ->> 'id')
                );
                v_result := public.delivery_append_if_match(v_result, v_order, p_tab, p_keyword);
            END LOOP;
        EXCEPTION WHEN OTHERS THEN
            NULL;
        END;
    END IF;

    FOR v_order_id IN
        SELECT o.id
        FROM public.hss_service_orders o
        WHERE o.deleted_at IS NULL
          AND (v_staff_id IS NULL OR o.current_staff_id = v_staff_id)
        ORDER BY COALESCE(o.updated_at, o.created_at) DESC, o.created_at DESC
    LOOP
        v_order := public.homecare_apply_arrival_pending_order(
            public.delivery_get_legacy_order_json(v_order_id)
        );
        v_result := public.delivery_append_if_match(v_result, v_order, p_tab, p_keyword);
    END LOOP;

    RETURN COALESCE(v_result, '[]'::jsonb);
END;
$$;

COMMIT;
