from __future__ import annotations

from typing import Any

from asgiref.sync import sync_to_async

from .client import MDY_ENDPOINT_GET_FILTER_ROWS, get_default_mingdaoyun_client
from .mappings import (
    MDY_WORKSHEET_ID_CUSTOMER,
    MDY_WORKSHEET_ID_FABRIC,
    MDY_WORKSHEET_ID_PLATE_ORDER,
    MDY_WORKSHEET_ID_PRODUCT,
)
from .models import Customer, Fabric, Product
from .parsers import pick_customer, pick_fabric, pick_product


async def fetch_products_from_mingdaoyun(page: int = 1, page_size: int = 100) -> tuple[list[Product], int]:
    """从明道云获取产品列表"""

    client = get_default_mingdaoyun_client()
    response = await client.post(
        endpoint=MDY_ENDPOINT_GET_FILTER_ROWS,
        data={
            "worksheetId": MDY_WORKSHEET_ID_PRODUCT,
            "pageIndex": page,
            "pageSize": page_size,
            "sortId": "ctime",
            "isAsc": True,
        },
    )

    data = response.get("data") if isinstance(response, dict) else None
    if data:
        print(
            f'[product-sync] page={page} size={page_size} rows={len(data.get("rows", []))} total={data.get("total")}'
        )
    else:
        print(f"[product-sync] page={page} size={page_size} received empty data")
    if not data:
        return [], 0

    products = [pick_product(item) for item in data.get("rows", [])]
    total_count = data.get("total", 0)
    return products, total_count


async def fetch_customers_from_mingdaoyun(page: int = 1, page_size: int = 100) -> tuple[list[Customer], int]:
    """从明道云获取客户列表"""

    client = get_default_mingdaoyun_client()
    response = await client.post(
        endpoint=MDY_ENDPOINT_GET_FILTER_ROWS,
        data={
            "worksheetId": MDY_WORKSHEET_ID_CUSTOMER,
            "pageIndex": page,
            "pageSize": page_size,
            "sortId": "ctime",
            "isAsc": True,
        },
    )

    data = response.get("data") if isinstance(response, dict) else None
    if data:
        print(
            f'[customer-sync] page={page} size={page_size} rows={len(data.get("rows", []))} total={data.get("total")}'
        )
    else:
        print(f"[customer-sync] page={page} size={page_size} received empty data")
    if not data:
        return [], 0

    customers = [pick_customer(item) for item in data.get("rows", [])]
    total_count = data.get("total", 0)
    return customers, total_count


async def fetch_row_by_rowid_from_mingdaoyun(
    worksheet_id: str,
    rowid: str,
    *,
    sort_id: str = "ctime",
    is_asc: bool = False,
    list_type: int = 1,
    not_get_total: bool = True,
    data_type: int = 2,
    filter_type: int = 3,
    control_id: str = "rowId",
) -> dict[str, Any] | None:
    """按 rowId 查询工作表的单条记录（仅封装 rowId 等值查询）。

    按照明道云 getFilterRows 的 filters 结构构造请求：
    - dataType=2 表示字符串
    - filterType=3 表示“相等”

    返回：
    - 匹配到记录：返回第一条 row dict
    - 未匹配或响应无 data：返回 None
    """

    client = get_default_mingdaoyun_client()
    response = await client.post(
        endpoint=MDY_ENDPOINT_GET_FILTER_ROWS,
        data={
            "worksheetId": worksheet_id,
            "listType": list_type,
            "sortId": sort_id,
            "isAsc": is_asc,
            "notGetTotal": not_get_total,
            "filters": [
                {
                    "controlId": control_id,
                    "dataType": data_type,
                    "filterType": filter_type,
                    "value": rowid,
                }
            ],
        },
    )

    data = response.get("data") if isinstance(response, dict) else None
    if not data:
        return None

    rows = data.get("rows") or []
    if not rows:
        return None
    if isinstance(rows[0], dict):
        first = rows[0]
        # 明道云在 filters 不合法/不生效时可能仍返回默认列表数据。
        # 这里做一次校验，避免“误返回不匹配的第一条记录”。
        if first.get("rowid") != rowid:
            return None
        return first
    return None


async def fetch_plate_orders_from_mingdaoyun(
    page: int = 1,
    page_size: int = 100,
    *,
    sort_id: str = "ctime",
    is_asc: bool = True,
) -> tuple[list[dict[str, Any]], int]:
    """从明道云获取“开版数据表”记录列表（原始行字典，不做字段映射解析）"""

    client = get_default_mingdaoyun_client()
    response = await client.post(
        endpoint=MDY_ENDPOINT_GET_FILTER_ROWS,
        data={
            "worksheetId": MDY_WORKSHEET_ID_PLATE_ORDER,
            "pageIndex": page,
            "pageSize": page_size,
            "sortId": sort_id,
            "isAsc": is_asc,
        },
    )

    data = response.get("data") if isinstance(response, dict) else None
    if data:
        print(
            f'[plate-order-fetch] page={page} size={page_size} rows={len(data.get("rows", []))} total={data.get("total")}'
        )
    else:
        print(f"[plate-order-fetch] page={page} size={page_size} received empty data")
    if not data:
        return [], 0

    rows = data.get("rows", [])
    total_count = data.get("total", 0)
    return rows, total_count


async def sync_fabric_from_mingdaoyun(page: int = 1, page_size: int = 100) -> int:
    """从明道云同步面料数据（用于创建/更新 QuickInput: 布料名）"""

    client = get_default_mingdaoyun_client()
    response = await client.post(
        endpoint=MDY_ENDPOINT_GET_FILTER_ROWS,
        data={
            "worksheetId": MDY_WORKSHEET_ID_FABRIC,
            "pageIndex": page,
            "pageSize": page_size,
            "sortId": "ctime",
            "isAsc": False,
        },
    )

    data = response.get("data") if isinstance(response, dict) else None
    if data:
        rows = data.get("rows", [])
        print(f"[fabric-sync] fetch rows={len(rows)} total={data.get('total')}")
        if rows:
            print(f"[fabric-sync] first row keys: {list(rows[0].keys())[:10]}")
            print(f"[fabric-sync] first row sample: {rows[0]}")
    else:
        print(f"[fabric-sync] fetch empty data (page={page}, size={page_size})")
    if not data:
        return 0

    fabrics = [pick_fabric(item) for item in data.get("rows", [])]
    total_count = data.get("total", 0)

    await sync_to_async(_create_fabric_quick_inputs)(
        page,
        page_size,
        fabrics,
    )
    return total_count


def _create_fabric_quick_inputs(page: int, page_size: int, fabrics: list[Fabric]) -> None:
    from basic_info import models as basic_models

    total = len(fabrics)
    created_count = 0
    sample_names = [fabric.name for fabric in fabrics[:5]]
    print(f"[fabric-sync] page={page} size={page_size} fetched={total}")
    print(f"[fabric-sync] sample names: {sample_names}")
    for fabric in fabrics:
        if not fabric.name:
            continue
        obj, created = basic_models.QuickInput.objects.update_or_create(
            name=fabric.name,
            group="布料名",
            defaults={"value": fabric.name},
        )
        if created:
            created_count += 1
    print(f"[fabric-sync] page={page} new_records={created_count} updated_or_existing={total - created_count}")
