"""Step 1.1: Pull Objective API and store in local DB.

We pull "Сводные/Корпуса" (corp_sum) for Ekb covering last 12 calendar months —
this is the primary source of:
  - per-corpus monthly: deals (DDU+DKP), volume sold (m²), avg price/m², stock left
  - готовность %, старт продаж, планируемая дата ввода
  - район (Objective's classification)

Data lands in two tables:
  objective_raw_reports — JSON payload archive (1 row per fetch)
  objective_corp_month — flattened rows (one per month × project × corpus × room-type)
"""
import sqlite3, pathlib, requests, json, time, datetime as dt

DB = pathlib.Path(__file__).parent / "analysis.db"
API = "https://api.objctv.ru"
KEY = "623f6a57-0179-434b-8202-259525bdc77c"

SCHEMA = """
CREATE TABLE IF NOT EXISTS objective_raw_reports (
    id            INTEGER PRIMARY KEY AUTOINCREMENT,
    fetched_at    TEXT DEFAULT CURRENT_TIMESTAMP,
    report_kind   TEXT,
    group_name    TEXT,
    start_date    TEXT,
    end_date      TEXT,
    n_rows        INTEGER,
    payload       TEXT
);

CREATE TABLE IF NOT EXISTS objective_corp_month (
    month         TEXT,                  -- 'YYYY-MM'
    project       TEXT,
    developer     TEXT,
    district      TEXT,
    obj_class     TEXT,
    corpus        TEXT,
    sales_start   TEXT,
    plan_date     TEXT,
    fact_date     TEXT,
    months_in_sales INTEGER,
    rooms_bucket  TEXT,                  -- '1', '2', '3', '4+', 'студия', etc.
    lots_pd       INTEGER,
    area_pd       REAL,
    deals_total   INTEGER,
    deals_priced  INTEGER,
    sold_volume_m2 REAL,
    avg_price_m2  REAL,
    avg_area_m2   REAL,
    stock_lots    INTEGER,
    stock_m2      REAL,
    stock_avg_price_m2 REAL,
    PRIMARY KEY (month, project, corpus, rooms_bucket)
);
CREATE INDEX IF NOT EXISTS oc_district ON objective_corp_month(district);
CREATE INDEX IF NOT EXISTS oc_project  ON objective_corp_month(project);
"""

def get_token():
    r = requests.get(f"{API}/Users/User/GetToken", params={"apiKey": KEY}, timeout=30)
    r.raise_for_status()
    return r.json()["token"]

def fetch_corp_sum(token, group, sd, ed):
    r = requests.get(f"{API}/v2/Report/GetReport",
        params={"Page":"Отчеты","ReportSection":"Объединенные данные",
                "ReportType":"Сводные","ReportName":"Корпуса",
                "GroupName":group,"StartDate":sd,"EndDate":ed,
                "UseDdu":"true","UseDkp":"true"},
        headers={"Authorization":f"Bearer {token}","Accept-Encoding":"br"},
        timeout=120)
    r.raise_for_status()
    return r.json().get("result", [])

# Map raw RU column names to our schema
COL_MAP = {
    "month":"Месяц","project":"Проект","developer":"Девелопер","district":"Район",
    "obj_class":"Класс","corpus":"Корпус","sales_start":"Старт продаж",
    "plan_date":"Планируемая дата ввода","fact_date":"Фактическая дата ввода",
    "months_in_sales":"Месяцев в реализации","rooms_bucket":"Количество комнат (Данные Объектива)",
    "lots_pd":"Лотов по ПД, шт.","area_pd":"Площадь по ПД, м2.",
    "deals_total":"Количество в сделках (всего), шт.",
    "deals_priced":"Количество лотов в сделках (с ценами), шт.",
    "sold_volume_m2":"Объем реализации (всего), м2.",
    "avg_price_m2":"Средняя цена м2 лота в сделках, тыс.Р/м2",
    "avg_area_m2":"Средняя площадь лота в сделках, м2",
    "stock_lots":"Объем предложения, шт.","stock_m2":"Объем предложения, м2.",
    "stock_avg_price_m2":"Средняя цена м2 лота в продаже, тыс.Р/м2",
}

RU_MONTHS = {"январь":1,"февраль":2,"март":3,"апрель":4,"май":5,"июнь":6,
             "июль":7,"август":8,"сентябрь":9,"октябрь":10,"ноябрь":11,"декабрь":12}

def normalize_month(s):
    # 'апрель-2026' → '2026-04'
    if not s: return None
    parts = str(s).lower().replace("—","-").split("-")
    if len(parts) != 2: return s
    m = RU_MONTHS.get(parts[0].strip())
    y = parts[1].strip()
    return f"{y}-{m:02d}" if m else s

def main():
    conn = sqlite3.connect(DB)
    conn.executescript(SCHEMA)

    today = dt.date.today()
    sd = (today.replace(day=1) - dt.timedelta(days=365)).strftime("%Y.%m.%d")
    ed = today.strftime("%Y.%m.%d")
    group = "Екатеринбург"

    print(f"Fetching corp_sum {group} {sd}..{ed}")
    token = get_token()
    rows = fetch_corp_sum(token, group, sd, ed)
    print(f"  {len(rows)} rows")

    conn.execute("INSERT INTO objective_raw_reports(report_kind,group_name,start_date,end_date,n_rows,payload) VALUES (?,?,?,?,?,?)",
                 ("corp_sum_v2", group, sd, ed, len(rows), json.dumps(rows, ensure_ascii=False)))

    conn.execute("DELETE FROM objective_corp_month")
    inserted = skipped = 0
    for r in rows:
        try:
            vals = {k: r.get(v) for k, v in COL_MAP.items()}
            vals["month"] = normalize_month(vals["month"])
            cols = list(vals.keys())
            placeholders = ",".join(["?"] * len(cols))
            conn.execute(f"INSERT OR REPLACE INTO objective_corp_month({','.join(cols)}) VALUES ({placeholders})",
                         [vals[c] for c in cols])
            inserted += 1
        except Exception as e:
            skipped += 1
    conn.commit()
    print(f"  inserted: {inserted}, skipped: {skipped}")

    # Sanity
    n = conn.execute("SELECT count(*) FROM objective_corp_month").fetchone()[0]
    n_proj = conn.execute("SELECT count(DISTINCT project) FROM objective_corp_month").fetchone()[0]
    n_dist = conn.execute("SELECT count(DISTINCT district) FROM objective_corp_month").fetchone()[0]
    print(f"\nLocal: {n} rows, {n_proj} проекта, {n_dist} районов")
    print("\nDistricts (Objective):")
    for r in conn.execute("""SELECT district, count(*) c, count(DISTINCT project) np
                             FROM objective_corp_month GROUP BY 1 ORDER BY 3 DESC""").fetchall():
        print(f"  {r[0]:<30} rows={r[1]:>5}  projects={r[2]}")
    conn.close()

if __name__ == "__main__":
    main()
