import json
from datetime import datetime

from indian_paper_trading_strategy.engine.db import db_connection, get_context

DEFAULT_CONFIG = {
    "active": False,
    "sip_amount": 0,
    "sip_frequency": {"value": 30, "unit": "days"},
    "next_run": None
}

def _maybe_parse_json(value):
    if value is None:
        return None
    if not isinstance(value, str):
        return value
    text = value.strip()
    if not text:
        return None
    try:
        return json.loads(text)
    except Exception:
        return value


def _format_ts(value: datetime | None):
    if value is None:
        return None
    return value.isoformat()


def load_strategy_config(user_id: str | None = None, run_id: str | None = None):
    scope_user, scope_run = get_context(user_id, run_id)
    with db_connection() as conn:
        with conn.cursor() as cur:
            cur.execute(
                """
                SELECT strategy, sip_amount, sip_frequency_value, sip_frequency_unit,
                       mode, broker, active, frequency, frequency_days, unit, next_run
                FROM strategy_config
                WHERE user_id = %s AND run_id = %s
                LIMIT 1
                """,
                (scope_user, scope_run),
            )
            row = cur.fetchone()
            if not row:
                return DEFAULT_CONFIG.copy()

    cfg = DEFAULT_CONFIG.copy()
    cfg["strategy"] = row[0]
    cfg["strategy_name"] = row[0]
    cfg["sip_amount"] = float(row[1]) if row[1] is not None else cfg.get("sip_amount")
    cfg["mode"] = row[4]
    cfg["broker"] = row[5]
    cfg["active"] = row[6] if row[6] is not None else cfg.get("active")
    cfg["frequency"] = _maybe_parse_json(row[7])
    cfg["frequency_days"] = row[8]
    cfg["unit"] = row[9]
    cfg["next_run"] = _format_ts(row[10])
    if row[2] is not None or row[3] is not None:
        cfg["sip_frequency"] = {"value": row[2], "unit": row[3]}
    else:
        value = cfg.get("frequency")
        unit = cfg.get("unit")
        if isinstance(value, dict):
            unit = value.get("unit", unit)
            value = value.get("value")
        if value is None and cfg.get("frequency_days") is not None:
            value = cfg.get("frequency_days")
            unit = unit or "days"
        if value is not None and unit:
            cfg["sip_frequency"] = {"value": value, "unit": unit}
    return cfg

def save_strategy_config(cfg, user_id: str | None = None, run_id: str | None = None):
    scope_user, scope_run = get_context(user_id, run_id)
    sip_frequency = cfg.get("sip_frequency")
    sip_value = None
    sip_unit = None
    if isinstance(sip_frequency, dict):
        sip_value = sip_frequency.get("value")
        sip_unit = sip_frequency.get("unit")

    frequency = cfg.get("frequency")
    if not isinstance(frequency, str) and frequency is not None:
        frequency = json.dumps(frequency)

    next_run = cfg.get("next_run")
    next_run_dt = None
    if isinstance(next_run, str):
        try:
            next_run_dt = datetime.fromisoformat(next_run)
        except ValueError:
            next_run_dt = None

    strategy = cfg.get("strategy") or cfg.get("strategy_name")

    with db_connection() as conn:
        with conn:
            with conn.cursor() as cur:
                cur.execute(
                    """
                    INSERT INTO strategy_config (
                        user_id,
                        run_id,
                        strategy,
                        sip_amount,
                        sip_frequency_value,
                        sip_frequency_unit,
                        mode,
                        broker,
                        active,
                        frequency,
                        frequency_days,
                        unit,
                        next_run
                    )
                    VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)
                    ON CONFLICT (user_id, run_id) DO UPDATE
                    SET strategy = EXCLUDED.strategy,
                        sip_amount = EXCLUDED.sip_amount,
                        sip_frequency_value = EXCLUDED.sip_frequency_value,
                        sip_frequency_unit = EXCLUDED.sip_frequency_unit,
                        mode = EXCLUDED.mode,
                        broker = EXCLUDED.broker,
                        active = EXCLUDED.active,
                        frequency = EXCLUDED.frequency,
                        frequency_days = EXCLUDED.frequency_days,
                        unit = EXCLUDED.unit,
                        next_run = EXCLUDED.next_run
                    """,
                    (
                        scope_user,
                        scope_run,
                        strategy,
                        cfg.get("sip_amount"),
                        sip_value,
                        sip_unit,
                        cfg.get("mode"),
                        cfg.get("broker"),
                        cfg.get("active"),
                        frequency,
                        cfg.get("frequency_days"),
                        cfg.get("unit"),
                        next_run_dt,
                    ),
                )

