CREATE OR REPLACE FUNCTION public.build_sector_coverage(
    p_center geometry(Point, 4326),
    p_azimuth double precision,
    p_beamwidth double precision,
    p_radius_m double precision,
    p_arc_segments integer DEFAULT 16
)
RETURNS geometry(Polygon, 4326)
LANGUAGE plpgsql
IMMUTABLE
STRICT
AS $$
DECLARE
    ring_points geometry[] := ARRAY[p_center];
    angle_degrees double precision;
    i integer;
BEGIN
    IF p_azimuth < 0 OR p_azimuth >= 360 THEN
        RAISE EXCEPTION 'Azimuth must be between 0 and 359 degrees';
    END IF;

    IF p_beamwidth <= 0 OR p_beamwidth > 360 THEN
        RAISE EXCEPTION 'Beamwidth must be between 1 and 360 degrees';
    END IF;

    IF p_radius_m <= 0 THEN
        RAISE EXCEPTION 'Coverage radius must be positive';
    END IF;

    IF p_arc_segments < 4 OR p_arc_segments > 72 THEN
        RAISE EXCEPTION 'Arc segments must be between 4 and 72';
    END IF;

    IF p_beamwidth = 360 THEN
        RETURN ST_Buffer(p_center::geography, p_radius_m)::geometry;
    END IF;

    FOR i IN 0..p_arc_segments LOOP
        angle_degrees := p_azimuth - (p_beamwidth / 2.0)
                         + (p_beamwidth * i / p_arc_segments);
        ring_points := array_append(
            ring_points,
            ST_Project(
                p_center::geography,
                p_radius_m,
                radians(angle_degrees)
            )::geometry
        );
    END LOOP;

    ring_points := array_append(ring_points, p_center);
    RETURN ST_ForcePolygonCCW(ST_MakePolygon(ST_MakeLine(ring_points)));
END;
$$;

COMMENT ON FUNCTION public.build_sector_coverage IS
    'Builds a directional coverage wedge from a site point and sector settings.';
