WITH 
-- 1. Получаем все проверки ICMP за период
checks AS (
    SELECT 
        h.host AS host_name,
        COALESCE(h.name, h.host) AS visible_name,
        -- Тип оборудования из инвентаризации (поле type), если пусто - берем hardware
        COALESCE(hinv."name", 'не указан') AS equipment_type,
        -- Номер объекта ИТС РО (храним в поле notes инвентаризации)
        COALESCE(hinv.notes, '') AS object_number,
        -- Координаты: объединяем широту и долготу через пробел
        CASE 
            WHEN hinv.location_lat IS NOT NULL AND hinv.location_lon IS NOT NULL 
                 AND hinv.location_lat != '' AND hinv.location_lon != ''
            THEN hinv.location_lat || ' ' || hinv.location_lon
            WHEN hinv.location_lat IS NOT NULL AND hinv.location_lat != '' 
            THEN hinv.location_lat
            WHEN hinv.location_lon IS NOT NULL AND hinv.location_lon != '' 
            THEN hinv.location_lon
            ELSE ''
        END AS coordinates,
        -- Время проверки с учетом часового пояса
        TO_TIMESTAMP(hx.clock) AT TIME ZONE 'Europe/Moscow' AS check_time,
        -- Статус: 1 = доступно, 0 = недоступно
        hx.value AS status
    FROM hosts h
    INNER JOIN items i 
        ON i.hostid = h.hostid 
        AND i.key_ = 'icmpping'
        AND i.status = 0
        AND i.value_type = 3  -- unsigned numeric
    INNER JOIN history_uint hx 
        ON hx.itemid = i.itemid
    LEFT JOIN host_inventory hinv 
        ON hinv.hostid = h.hostid
    WHERE 
        -- Только мониторимые хосты
        h.status = 0
        -- Исключаем оборудование, начинающееся на IRZ (любой регистр)
        --AND UPPER(h.host) NOT LIKE 'IRZ%'
        -- Период: май 2026 года (измените под свои даты)
        --and hinv.notes = 'ОБЪЕКТ № 5'
        --and hinv."name" = 'Метеостанция Кондор'
        and CAST(nullif(regexp_replace(hinv.notes, 'ОБЪЕКТ №\s*', '', 'g'),'') as INTEGER) 
        between 1 and 85 --in (44,77,43,54,27,48,12,49,65,9,60,35,38,1,51,41,53,84,8) 
        AND TO_TIMESTAMP(hx.clock) >= to_date(${start_dt}, 'yyyymmdd') - interval '1 day'
        AND TO_TIMESTAMP(hx.clock) <= to_date(${end_dt}, 'yyyymmdd') + interval '1 day'  
        --and hinv.notes is null
        
),

-- 2. Добавляем предыдущий статус для определения моментов смены
checks_with_prev AS (
    SELECT 
        *,
        LAG(status) OVER (PARTITION BY host_name ORDER BY check_time) AS prev_status,
        coalesce(lead(check_time) OVER (PARTITION BY host_name ORDER BY check_time), now()) AS next_check_time
    FROM checks
),

-- 3. Определяем моменты смены статуса (начало нового интервала)
status_changes AS (
    SELECT 
        host_name,
	    visible_name,
	    equipment_type,
	    object_number,
	    coordinates,
	    check_time,
	    status, 
	    prev_status,
	    case 
		    when DATE(next_check_time) > DATE(check_time) then date_trunc('day', next_check_time) + interval '00:00:00'
	    	else next_check_time 
	    end as next_check_time, 
        CASE WHEN status != prev_status THEN 1 
            ELSE 0 
        END AS is_start
    FROM checks_with_prev
    union all 
    SELECT
	    host_name,
	    visible_name,
	    equipment_type,
	    object_number,
	    coordinates,
	    date_trunc('day', next_check_time) + interval '00:00:00' as check_time,
	    status, 
	    prev_status,
	    next_check_time, 
	    1 as is_start
     FROM checks_with_prev
     where DATE(next_check_time) > DATE(check_time) 
),

-- 4. Нумеруем интервалы для каждого устройства
intervals AS (
    SELECT 
        *,
        SUM(is_start) OVER (PARTITION BY host_name ORDER BY check_time) AS interval_id
    FROM status_changes
    WHERE status IS NOT null
    and date_trunc('day', check_time) >= to_date(${start_dt}, 'yyyymmdd') and date_trunc('day', check_time) <= to_date(${end_dt}, 'yyyymmdd')
),

-- 5. Агрегируем каждый непрерывный интервал
grouped_intervals AS (
    SELECT 
        host_name,
        visible_name,
        equipment_type,
        object_number,
        coordinates,
        MIN(check_time) AS check_time,
        MAX(next_check_time) AS next_check_time,
        MAX(status) AS status
    FROM intervals
    GROUP BY 
        host_name, 
        visible_name,
        equipment_type,
        object_number,
        coordinates,
        interval_id
),

daily_stats AS (
	select *,
		case when unavailable_hours is not null then coalesce(extract('hour' from available_hours)::int,0) else 24 end AS a_h, 
		coalesce(extract('minute' from available_hours)::int,0) AS a_m,
		coalesce(extract('second' from available_hours)::int,0) AS a_s,
		case when available_hours is not null then coalesce(extract('hour' from unavailable_hours)::int,0) else 24 end AS u_h, 
		coalesce(extract('minute' from unavailable_hours)::int,0) AS u_m,
		coalesce(extract('second' from unavailable_hours)::int,0) AS u_s
	from 
	(
	    SELECT 
	        host_name,
	        visible_name,
	        equipment_type,
	        object_number,
	        coordinates,
	        DATE(check_time) AS check_date, 
	    	sum(case when status = 1 then next_check_time - check_time else null end) AS available_hours, 
	    	sum(case when status = 0 then next_check_time - check_time else null end) AS unavailable_hours  
	    	--sum(next_check_time - check_time)  AS all_hours
	    FROM grouped_intervals
	    GROUP BY 
	        host_name,
	        visible_name,
	        equipment_type,
	        object_number,
	        coordinates,
	        DATE(check_time)
	) f 
),

daily_graph AS (
    SELECT 
        visible_name,
        equipment_type,
        object_number,
        coordinates,
        max(case when object_number similar to '%№%' then regexp_replace(object_number, 'ОБЪЕКТ №\s*', '', 'g')::int else null end) as object_num,
        STRING_AGG(
            TO_CHAR(check_date, 'DD.MM') 
            || ': Доступно ' || a_h || 'ч.' || a_m || 'м.' || a_s|| 'с.'  
            || ', Недоступно ' || u_h || 'ч.' || u_m || 'м.' || u_s ||'с.', 
            '; ' ORDER BY check_date
        ) AS daily_schedule
    FROM daily_stats
    GROUP BY 
        visible_name,
        equipment_type,
        object_number,
        coordinates
),

device_summary AS (
    SELECT 
        visible_name,
        equipment_type,
        object_number,
        coordinates,
        SUM(CASE WHEN (a_h + a_m/60 + a_s/360) > 12 THEN 1 ELSE 0 END) AS days_available_gt_12h,
        SUM(CASE WHEN (a_h + a_m/60 + a_s/360) <= 12 THEN 1 ELSE 0 END) AS days_unavailable_ge_12h
    FROM daily_stats
    GROUP BY 
        visible_name,
        equipment_type,
        object_number,
        coordinates
)

SELECT 
    ROW_NUMBER() OVER (ORDER BY dg.object_num nulls last, dg.equipment_type) AS "№ п/п",
    dg.equipment_type AS "Тип оборудования",
    case when dg.object_num is null then 'на инвентаризации' else dg.object_number end AS "Номер_объекта_ИТС_РО",
    dg.coordinates AS "Координаты_расположения",
    dg.daily_schedule AS "Посуточный график функц оборуд",
    ds.days_available_gt_12h AS "Количество суток доступности",
    ds.days_unavailable_ge_12h AS "Количество суток недоступности"
FROM daily_graph dg
INNER JOIN device_summary ds 
    ON ds.visible_name = dg.visible_name
ORDER BY 1;