BEGIN;

DROP FUNCTION IF EXISTS public.rpc_admin_save_delivery_staff(UUID, TEXT, TEXT, TEXT, SMALLINT);

CREATE OR REPLACE FUNCTION public.rpc_admin_save_delivery_staff(
    p_id UUID DEFAULT NULL,
    p_uid UUID DEFAULT NULL,
    p_station_id UUID DEFAULT NULL,
    p_staff_no TEXT DEFAULT NULL,
    p_nickname TEXT DEFAULT NULL,
    p_avatar TEXT DEFAULT NULL,
    p_phone TEXT DEFAULT NULL,
    p_status SMALLINT DEFAULT 1,
    p_online_status TEXT DEFAULT 'resting',
    p_certificate_status TEXT DEFAULT 'pending',
    p_certificate_expire_at DATE DEFAULT NULL,
    p_service_area TEXT DEFAULT '',
    p_skills JSONB DEFAULT '[]'::jsonb
)
RETURNS UUID
LANGUAGE plpgsql
SECURITY DEFINER
SET search_path = public
AS $$
DECLARE
    v_id UUID;
BEGIN
    IF NOT EXISTS (
        SELECT 1 FROM public.ak_users
        WHERE auth_id = auth.uid() AND role = 'admin'
    ) THEN
        RAISE EXCEPTION 'Permission denied';
    END IF;

    IF p_nickname IS NULL OR p_phone IS NULL THEN
        RAISE EXCEPTION 'Missing required fields: nickname or phone';
    END IF;

    IF p_online_status NOT IN ('online', 'resting', 'busy') THEN
        RAISE EXCEPTION 'Invalid online_status';
    END IF;

    IF p_certificate_status NOT IN ('valid', 'expired', 'pending') THEN
        RAISE EXCEPTION 'Invalid certificate_status';
    END IF;

    IF p_station_id IS NOT NULL AND NOT EXISTS (
        SELECT 1
        FROM public.ml_delivery_stations s
        WHERE s.id = p_station_id AND s.deleted_at IS NULL
    ) THEN
        RAISE EXCEPTION 'Delivery station not found';
    END IF;

    IF p_id IS NULL THEN
        INSERT INTO public.ml_delivery_staff (
            uid, station_id, staff_no, nickname, avatar, phone, status,
            online_status, certificate_status, certificate_expire_at,
            service_area, skills
        ) VALUES (
            p_uid, p_station_id, NULLIF(p_staff_no, ''), p_nickname, p_avatar, p_phone, p_status,
            p_online_status, p_certificate_status, p_certificate_expire_at,
            COALESCE(p_service_area, ''), COALESCE(p_skills, '[]'::jsonb)
        ) RETURNING id INTO v_id;
    ELSE
        UPDATE public.ml_delivery_staff
        SET
            uid = COALESCE(p_uid, uid),
            station_id = p_station_id,
            staff_no = CASE WHEN p_staff_no IS NULL OR p_staff_no = '' THEN NULL ELSE p_staff_no END,
            nickname = COALESCE(p_nickname, nickname),
            avatar = COALESCE(p_avatar, avatar),
            phone = COALESCE(p_phone, phone),
            status = COALESCE(p_status, status),
            online_status = COALESCE(p_online_status, online_status),
            certificate_status = COALESCE(p_certificate_status, certificate_status),
            certificate_expire_at = p_certificate_expire_at,
            service_area = COALESCE(p_service_area, service_area),
            skills = COALESCE(p_skills, skills),
            updated_at = now()
        WHERE id = p_id AND deleted_at IS NULL
        RETURNING id INTO v_id;

        IF v_id IS NULL THEN
            RAISE EXCEPTION 'Delivery staff not found';
        END IF;
    END IF;

    RETURN v_id;
END;
$$;

REVOKE ALL ON FUNCTION public.rpc_admin_save_delivery_staff(UUID, UUID, UUID, TEXT, TEXT, TEXT, TEXT, SMALLINT, TEXT, TEXT, DATE, TEXT, JSONB) FROM PUBLIC;
GRANT EXECUTE ON FUNCTION public.rpc_admin_save_delivery_staff(UUID, UUID, UUID, TEXT, TEXT, TEXT, TEXT, SMALLINT, TEXT, TEXT, DATE, TEXT, JSONB) TO authenticated;

DROP FUNCTION IF EXISTS public.rpc_admin_get_delivery_staff_list(TEXT, SMALLINT, INTEGER, INTEGER);

CREATE OR REPLACE FUNCTION public.rpc_admin_get_delivery_staff_list(
    p_search TEXT DEFAULT NULL,
    p_status SMALLINT DEFAULT NULL,
    p_page INTEGER DEFAULT 1,
    p_page_size INTEGER DEFAULT 20
)
RETURNS JSONB
LANGUAGE plpgsql
SECURITY DEFINER
SET search_path = public
AS $$
DECLARE
    v_offset INTEGER := (p_page - 1) * p_page_size;
    v_total BIGINT;
    v_items JSONB;
BEGIN
    IF NOT EXISTS (
        SELECT 1 FROM public.ak_users
        WHERE auth_id = auth.uid() AND role = 'admin'
    ) THEN
        RAISE EXCEPTION 'Permission denied';
    END IF;

    SELECT COUNT(*) INTO v_total
    FROM public.ml_delivery_staff s
    WHERE s.deleted_at IS NULL
      AND (p_status IS NULL OR s.status = p_status)
      AND (
        p_search IS NULL OR p_search = ''
        OR s.nickname ILIKE '%' || p_search || '%'
        OR s.phone ILIKE '%' || p_search || '%'
        OR s.staff_no ILIKE '%' || p_search || '%'
      );

    SELECT jsonb_agg(t) INTO v_items
    FROM (
        SELECT
            s.id,
            s.uid,
            s.station_id,
            st.name AS station_name,
            s.staff_no,
            s.nickname,
            s.avatar,
            s.phone,
            s.status,
            s.is_active,
            s.online_status,
            s.certificate_status,
            s.certificate_expire_at,
            s.service_area,
            s.skills,
            s.created_at,
            s.updated_at
        FROM public.ml_delivery_staff s
        LEFT JOIN public.ml_delivery_stations st ON st.id = s.station_id AND st.deleted_at IS NULL
        WHERE s.deleted_at IS NULL
          AND (p_status IS NULL OR s.status = p_status)
          AND (
            p_search IS NULL OR p_search = ''
            OR s.nickname ILIKE '%' || p_search || '%'
            OR s.phone ILIKE '%' || p_search || '%'
            OR s.staff_no ILIKE '%' || p_search || '%'
          )
        ORDER BY s.created_at DESC
        LIMIT p_page_size OFFSET v_offset
    ) t;

    RETURN jsonb_build_object(
        'total', v_total,
        'items', COALESCE(v_items, '[]'::jsonb)
    );
END;
$$;

REVOKE ALL ON FUNCTION public.rpc_admin_get_delivery_staff_list(TEXT, SMALLINT, INTEGER, INTEGER) FROM PUBLIC;
GRANT EXECUTE ON FUNCTION public.rpc_admin_get_delivery_staff_list(TEXT, SMALLINT, INTEGER, INTEGER) TO authenticated;

DROP FUNCTION IF EXISTS public.rpc_homecare_dispatch_candidate(TEXT, UUID);

CREATE OR REPLACE FUNCTION public.rpc_homecare_dispatch_candidate(
    p_service_code TEXT DEFAULT NULL,
    p_station_id UUID DEFAULT NULL
)
RETURNS JSONB
LANGUAGE plpgsql
SECURITY DEFINER
SET search_path = public
AS $$
DECLARE
    v_candidate JSONB;
BEGIN
    IF auth.uid() IS NULL OR NOT EXISTS (
        SELECT 1
        FROM public.ak_users u
        WHERE u.auth_id = auth.uid()
    ) THEN
        RAISE EXCEPTION 'Permission denied';
    END IF;

    SELECT jsonb_build_object(
        'id', s.id,
        'uid', s.uid,
        'station_id', s.station_id,
        'status', s.status,
        'online_status', s.online_status,
        'updated_at', s.updated_at,
        'created_at', s.created_at
    )
    INTO v_candidate
    FROM public.ml_delivery_staff s
    WHERE s.deleted_at IS NULL
      AND s.status = 1
      AND COALESCE(s.is_active, TRUE) = TRUE
      AND s.online_status = 'online'
      AND s.uid IS NOT NULL
      AND (p_station_id IS NULL OR s.station_id = p_station_id)
    ORDER BY COALESCE(s.updated_at, s.created_at) DESC, s.created_at DESC
    LIMIT 1;

    RETURN v_candidate;
END;
$$;

REVOKE ALL ON FUNCTION public.rpc_homecare_dispatch_candidate(TEXT, UUID) FROM PUBLIC;
GRANT EXECUTE ON FUNCTION public.rpc_homecare_dispatch_candidate(TEXT, UUID) TO authenticated;

COMMIT;