"""Custom field definition commands."""

from __future__ import annotations

import argparse
import json
import time
from typing import Any, List

from store_db.db import connect
from store_db.operation_log import commit_with_log, log_read
from store_db.response import emit_error, emit_need_confirm, emit_ok

from store_db.field_defs import field_type_error_detail, validate_field_type
from store_customer_lib.common import SKILL


def cmd_field_def_add(args: argparse.Namespace) -> int:
    if not validate_field_type(args.field_type):
        emit_error("invalid_field_type", field_type_error_detail())
    entity = "member"
    t0 = time.perf_counter()
    conn = connect()
    conn.execute(
        """INSERT OR REPLACE INTO store_custom_field_defs (entity, field_key, label, field_type, options_json)
           VALUES (?,?,?,?,?)""",
        (entity, args.field_key, args.label, args.field_type, args.options_json or "[]"),
    )
    commit_with_log(
        conn, args, skill=SKILL, command="field-def-add", op="create", table_name="store_custom_field_defs",
        entity_id="{}:{}".format(entity, args.field_key),
        duration_ms=int((time.perf_counter() - t0) * 1000),
    )
    emit_ok({"entity": entity, "field_key": args.field_key})
    return 0


def cmd_field_def_update(args: argparse.Namespace) -> int:
    entity = "member"
    t0 = time.perf_counter()
    payload = json.loads(args.set)
    conn = connect()
    row = conn.execute(
        "SELECT * FROM store_custom_field_defs WHERE entity=? AND field_key=?",
        (entity, args.field_key),
    ).fetchone()
    if not row:
        emit_error("not_found", {"entity": entity, "field_key": args.field_key})
    sets: List[str] = []
    vals: List[Any] = []
    for key in ("label", "field_type", "options_json", "sort_order"):
        if key in payload:
            val = payload[key]
            if key == "field_type" and not validate_field_type(str(val)):
                emit_error("invalid_field_type", field_type_error_detail())
            if key == "options_json" and not isinstance(val, str):
                val = json.dumps(val, ensure_ascii=False)
            sets.append("{}=?".format(key))
            vals.append(val)
    if sets:
        sets.append("updated_at=datetime('now','localtime')")
        vals.extend([entity, args.field_key])
        conn.execute(
            "UPDATE store_custom_field_defs SET {} WHERE entity=? AND field_key=?".format(", ".join(sets)),
            vals,
        )
        commit_with_log(
            conn, args, skill=SKILL, command="field-def-update", op="update",
            table_name="store_custom_field_defs", entity_id="{}:{}".format(entity, args.field_key),
            duration_ms=int((time.perf_counter() - t0) * 1000),
        )
    emit_ok({"entity": entity, "field_key": args.field_key})
    return 0


def cmd_field_def_delete(args: argparse.Namespace) -> int:
    entity = "member"
    if not args.yes:
        emit_need_confirm({"action": "field-def-delete", "entity": entity, "field_key": args.field_key})
        return 0
    t0 = time.perf_counter()
    conn = connect()
    conn.execute(
        "DELETE FROM store_custom_field_defs WHERE entity=? AND field_key=?",
        (entity, args.field_key),
    )
    commit_with_log(
        conn, args, skill=SKILL, command="field-def-delete", op="delete",
        table_name="store_custom_field_defs", entity_id="{}:{}".format(entity, args.field_key),
        duration_ms=int((time.perf_counter() - t0) * 1000),
    )
    emit_ok({"entity": entity, "field_key": args.field_key, "deleted": True})
    return 0


def cmd_field_def_list(args: argparse.Namespace) -> int:
    entity = "member"
    t0 = time.perf_counter()
    conn = connect()
    rows = [
        dict(r)
        for r in conn.execute(
            "SELECT * FROM store_custom_field_defs WHERE entity=? ORDER BY sort_order, field_key",
            (entity,),
        )
    ]
    log_read(
        conn, args, skill=SKILL, command="field-def-list", table_name="store_custom_field_defs",
        duration_ms=int((time.perf_counter() - t0) * 1000),
    )
    emit_ok({"field_defs": rows})
    return 0
