"""Append v2 facts to DataSources_Analysis_Apr26 — deeper digging.
Visible script kept in repo for audit. Manually delete when no longer needed."""
import json
import pathlib

target = pathlib.Path(__file__).parent / "memory-gendesign.jsonl"

addendum = {
    "type": "entity",
    "name": "DataSources_DomRF_Catalog_Apr26",
    "entityType": "research",
    "observations": [
        "Дата: 26.04.2026, продолжение анализа ДОМ.РФ. Расширил understanding API после копки в /сервисы/api/kn/* и /portal-kn/api/*",
        "🎯 ГЛАВНЫЙ EXTRACT-FLOW для всех ЖК Свердл. обл. в один проход:",
        "ШАГ 1: GET /portal-kn/api/sales/portal?flatStatus=free,booked&regions=66 → возвращает плоский массив всех objId с продажами в регионе. Например, для Свердл. обл. ~100-200 ЖК",
        "ШАГ 2: для каждого objId: GET /сервисы/api/kn/object?objId={id} → полная карточка ЖК",
        "Header: Authorization: Basic MTpxd2U= (тот же 1:qwe). Запросов ~150-200 чтобы скачать всю Свердл. обл, при rate-limit 5 RPS — 30-40 сек на полный sync",
        "Структура ответа /сервисы/api/kn/object — 30+ полей: hobjId, objId, developer{devId, shortName, fullName, groupName, orgForm, companyGroup, devInn}, rpdRegionCd, objAddr, shortAddr, metro{id,name,line,color,time,isWalk}, freeFlatsInfo{priceMin,numberFlats}, objCommercNm (название ЖК), objFloorMin/Max, objElemLivingCnt (всего квартир), objReady100PercDt (дата сдачи), objSquareLiving (общая жилая площадь), latitude, longitude, siteStatus, objGuarantyEscrowFlg, residentialBuildings, rpdNum, pdId (ID проектной декларации), buildType, objStatus, hobjRenderPhotoUrl (рендер ЖК), objPriceAVG (средняя цена м² по ЖК!), objPublDt, aiDescription (AI-генерация — у них уже работает GPT)",
        "Реальный пример (Екб, ЖК «РАЗУМ на Малышева»): objId=65136, devInn=3000007315, lat/lon=56.8346/60.6396, метро Площадь 1905 года 27 мин, 413 квартир, 19089 м², дата сдачи 2028-12-31, средняя цена 180828 ₽/м², numberFlats свободных = 52",
        "objPriceAVG — золотое поле. Это среднее между всеми квартирами в ЖК, обновляется регулярно. Лучше чем priceMin (минимальная цена), который часто означает 'студия 25 м²'. Для финмодели использовать objPriceAVG",
        "freeFlatsInfo.numberFlats — динамика этого числа во времени = velocity proxy. Если ЖК утром было 60 свободных, вечером 52 — продали 8 квартир за день. Для Site Finder Velocity Score это ровно то что нужно. Парсить раз в сутки в нашу БД, считать delta",
        "🛠 Endpoints which work (status 200, returning JSON):",
        "GET /portal-analytics/api/dashboard/by-region (агрегаты по всей РФ)",
        "GET /portal-analytics/api/dashboard/by-region?regionId=66 (фильтр)",
        "GET /portal-analytics/api/dashboard/by-room-count (распределение комнатностей)",
        "GET /portal-analytics/api/dashboard/by-flat-area (распределение площадей)",
        "GET /portal-analytics/api/dashboard/by-developer (топ застройщиков)",
        "GET /portal-analytics/api/dictionaries/regions",
        "GET /portal-analytics/api/dictionaries/developers",
        "GET /portal-kn/api/sales/portal?flatStatus=free,booked&regions=66 (массив ID ЖК)",
        "GET /portal-kn/api/kn/places (справочник мест)",
        "GET /portal-kn/api/kn/places?regionCd=66",
        "GET /сервисы/api/kn/object?objId={id} (per-объект, ОСНОВНОЙ endpoint)",
        "GET /сервисы/api/kn/flats/map?latitudePoint1=...&latitudePoint2=...&longitudePoint1=...&longitudePoint2=...&flatStatus=free,booked&regions=66 (per-ЖК с координатами в bbox)",
        "GET /сервисы/api/kn/flats/filters (диапазоны цен/площадей/этажей)",
        "GET /сервисы/api/kn/dataForFilters (справочник UI)",
        "GET /сервисы/api/kn/meta?place=66&objStatus=0 (доступные значения mechanism, energyEff, wall, dduFlg etc)",
        "GET /сервисы/api/kn/developers?objStatus=0&place=66&offset=0&limit=30&sortField=devShortCleanNm",
        "GET /сервисы/api/kn/devGk?place=66 (группы компаний)",
        "GET /сервисы/api/kn/commissioning?place=66&objStatus=0 (даты сдач)",
        "GET /сервисы/api/kn/metro?place=66 (метро в регионе)",
        "GET /сервисы/api/kn/hru/groups?place=66",
        "🚫 Endpoints с проблемами (требуют доп. разбора):",
        "/сервисы/api/kn/freeFlats?objId={id} → 502 (proxy error, может быть путь неверный)",
        "/сервисы/api/kn/object/{id}/flats → 502",
        "/portal-kn/api/object/{id} → 500 INTERNAL_ERROR",
        "/portal-kn/api/object/{id}/flats → 500",
        "Для получения per-flat данных (отдельные квартиры в ЖК с их площадью/комнатностью/ценой) — пока не нашли работающий endpoint. Поле freeFlatsInfo.numberFlats даёт лишь количество, не детали. Возможно нужно искать через /api/kn/realt/* или другие поддомены",
        "📋 Базовый клиент-стратегия для нашего backend:",
        "1) cron-task daily_dom_rf_sync: для каждого региона из списка целей → /sales/portal → массив objId → batch fetch /object → upsert в нашу таблицу dom_rf_objects. Время на ~1000 ЖК (вся Свердл.+МО для пилотов): ~3-5 мин. Кладем в Redis cache на 6 ч",
        "2) cron-task daily_velocity_snapshot: пробежать те же objId, сохранить freeFlatsInfo.numberFlats с timestamp → таблица dom_rf_velocity_history (objId, snapshot_dt, free_count). Из истории считаем absorption rate",
        "3) on-demand: при запросе пользователя про участок → bbox 5км → /flats/map → топ-20 ЖК-аналогов → /object для каждого → median(objPriceAVG), median(objSquareLiving/objElemLivingCnt), avg(objReady100PercDt - objPublDt) (срок строительства)",
        "💡 Использование в трёх плитках Plan A:",
        "ПЛИТКА «ЧТО СТРОИТЬ»: для региона по /by-region+/by-flat-area получаем benchmark distribution. Для конкретного района (5км вокруг участка) — через /flats/map берем все objId, получаем для каждого freeFlatsInfo.numberFlats и objSquareLiving/objElemLivingCnt. Считаем: средний размер квартиры в районе = objSquareLiving / objElemLivingCnt (для каждого ЖК), distribution по комнатностям через /by-room-count?regionId=X. Smart unit-mix готов для любого участка",
        "ПЛИТКА «ПО КАКОЙ ЦЕНЕ»: median(objPriceAVG) по ЖК-аналогам в радиусе. Сравнить с baseline Росстата для региона. Sensitivity: спред p10-p90",
        "ПЛИТКА «ЗА КАКОЕ ВРЕМЯ ПРОДАСТСЯ»: для каждого ЖК-аналога взять daily snapshot freeFlatsInfo.numberFlats за последние 30 дней (нужно собирать). Получить velocity (квартир/мес проданных). Спроектировать на наш случай: при N квартирах в концепте, при таком же темпе = время поглощения. До накопления истории — использовать /аналитика/реализация_строящихся_квартир (там может быть готовая агрегация)",
        "🔐 Юридический статус ДОМ.РФ scraping: ДОМ.РФ — государственный портал, ЕИСЖС обязан публиковать эти данные согласно 214-ФЗ. JSON API публичный, captcha нет, robots.txt разрешает (надо проверить). Авторизация Basic MTpqd2U= — публичный 'технический' токен фронта. С точки зрения ТОС — это 'использование данных в формате, в котором они доступны на сайте'. Декларируем в реестре ПО как 'интеграция с ЕИСЖС ДОМ.РФ'. Юридически чисто",
        "User-Agent: ставить осмысленный (`GenDesign-DataSync/0.1 (https://gendsgn.ru; ops@gendsgn.ru)`). Если ДОМ.РФ когда-нибудь решит закрыть API — есть legal-fallback через их официальную форму обратной связи (nash@domrf.ru) на B2B-доступ к 'сервисы для бизнеса'",
        "📦 SCHEMA для миграции (когда будет Stage 2a):",
        "table dom_rf_objects (obj_id PK, hobj_id, dev_id FK, dev_inn, group_name, region_cd, obj_addr, obj_short_addr, latitude, longitude, metro_id, metro_name, metro_time, obj_commerc_nm, obj_floor_min, obj_floor_max, obj_elem_living_cnt, obj_ready_100perc_dt, obj_square_living, obj_price_avg, obj_publ_dt, site_status, escrow_flg, problem_flg, building_type, ai_description, render_url, raw_payload jsonb, last_synced_at)",
        "table dom_rf_developers (dev_id PK, dev_inn, short_name, full_name, group_name, company_group, org_form_id)",
        "table dom_rf_velocity_snapshots (obj_id, snapshot_dt, free_count, price_min, PK(obj_id, snapshot_dt))",
        "Индексы: GIST на (latitude, longitude) → ST_DWithin для радиус-запросов в районе",
    ],
}

relations = [
    {"type": "relation", "from": "DataSources_DomRF_Catalog_Apr26", "to": "DataSources_Analysis_Apr26", "relationType": "extends"},
    {"type": "relation", "from": "DataSources_DomRF_Catalog_Apr26", "to": "PlanA_AnalyticsFirst_Apr25", "relationType": "operationalizes"},
    {"type": "relation", "from": "DataSources_DomRF_Catalog_Apr26", "to": "Stages_MVP_v1", "relationType": "amends_stage_2a"},
]

with target.open("a", encoding="utf-8") as f:
    f.write(json.dumps(addendum, ensure_ascii=False) + "\n")
    for r in relations:
        f.write(json.dumps(r, ensure_ascii=False) + "\n")

print(f"Appended 1 entity + {len(relations)} relations")
print(f"Final line count: {sum(1 for _ in target.open('r', encoding='utf-8'))}")
