"""Barcode mapping CRUD endpoints."""

import json
from pathlib import Path
from typing import Dict, Optional, List

from fastapi import APIRouter, HTTPException, Depends
from pydantic import BaseModel

from web.backend.auth.dependencies import get_current_user

router = APIRouter(prefix="/api/barcodes", tags=["barcodes"])

_project_root = Path(__file__).resolve().parent.parent.parent.parent
_mappings_file = _project_root / "config" / "barcode_mappings.json"


class BarcodeMapping(BaseModel):
    barcode: str
    target: Optional[str] = None
    description: Optional[str] = None
    # Special rule fields
    multiplier: Optional[int] = None
    target_unit: Optional[str] = None
    fixed_price: Optional[float] = None
    specification: Optional[str] = None


class BarcodeMappingUpdate(BaseModel):
    target: Optional[str] = None
    description: Optional[str] = None
    multiplier: Optional[int] = None
    target_unit: Optional[str] = None
    fixed_price: Optional[float] = None
    specification: Optional[str] = None


def _load_mappings() -> Dict:
    if not _mappings_file.is_file():
        return {}
    try:
        return json.loads(_mappings_file.read_text(encoding="utf-8"))
    except Exception:
        return {}


def _save_mappings(data: Dict):
    _mappings_file.parent.mkdir(parents=True, exist_ok=True)
    _mappings_file.write_text(json.dumps(data, ensure_ascii=False, indent=2), encoding="utf-8")


@router.get("")
async def list_barcodes(
    search: str = "",
    current_user: dict = Depends(get_current_user),
):
    mappings = _load_mappings()
    items = []
    for barcode, info in mappings.items():
        if isinstance(info, dict):
            target = info.get("map_to", info.get("target", ""))
            desc = info.get("description", "")
            item = {
                "barcode": barcode,
                "target": target,
                "description": desc,
                "multiplier": info.get("multiplier"),
                "target_unit": info.get("target_unit"),
                "fixed_price": info.get("fixed_price"),
                "specification": info.get("specification"),
            }
        else:
            item = {
                "barcode": barcode,
                "target": str(info),
                "description": "",
                "multiplier": None,
                "target_unit": None,
                "fixed_price": None,
                "specification": None,
            }
        s = search.lower() if search else ""
        if s and s not in barcode.lower() and s not in item["target"].lower() and s not in (desc or "").lower():
            continue
        items.append(item)
    return {"items": items, "total": len(items)}


@router.get("/{barcode}")
async def get_barcode(
    barcode: str,
    current_user: dict = Depends(get_current_user),
):
    mappings = _load_mappings()
    if barcode not in mappings:
        raise HTTPException(404, f"未找到条码映射 {barcode}")
    info = mappings[barcode]
    if isinstance(info, dict):
        return {"barcode": barcode, "target": info.get("map_to", info.get("target", "")), "description": info.get("description", "")}
    return {"barcode": barcode, "target": str(info), "description": ""}


@router.post("")
async def create_barcode(
    body: BarcodeMapping,
    current_user: dict = Depends(get_current_user),
):
    mappings = _load_mappings()
    if body.barcode in mappings:
        raise HTTPException(409, f"条码 {body.barcode} 已存在")

    entry: dict = {"description": body.description or ""}
    if body.multiplier:
        entry["multiplier"] = body.multiplier
        if body.target_unit:
            entry["target_unit"] = body.target_unit
        if body.fixed_price is not None:
            entry["fixed_price"] = body.fixed_price
        if body.specification:
            entry["specification"] = body.specification
    else:
        entry["map_to"] = body.target or ""

    mappings[body.barcode] = entry
    _save_mappings(mappings)
    return {"message": f"已创建规则 {body.barcode}"}


@router.put("/{barcode}")
async def update_barcode(
    barcode: str,
    body: BarcodeMappingUpdate,
    current_user: dict = Depends(get_current_user),
):
    mappings = _load_mappings()
    if barcode not in mappings:
        raise HTTPException(404, f"未找到条码规则 {barcode}")

    existing = mappings[barcode]
    if not isinstance(existing, dict):
        existing = {"map_to": str(existing), "description": ""}

    # Check if this is a special rule (has multiplier) or being converted to one
    if body.multiplier is not None:
        # Convert to special rule: remove map_to, add multiplier fields
        existing.pop("map_to", None)
        existing["multiplier"] = body.multiplier
        if body.target_unit is not None:
            existing["target_unit"] = body.target_unit
        if body.fixed_price is not None:
            existing["fixed_price"] = body.fixed_price
        if body.specification is not None:
            existing["specification"] = body.specification
    elif body.target is not None:
        # Convert to simple mapping: remove special fields, add map_to
        for k in ("multiplier", "target_unit", "fixed_price", "specification"):
            existing.pop(k, None)
        existing["map_to"] = body.target

    if body.description is not None:
        existing["description"] = body.description

    mappings[barcode] = existing
    _save_mappings(mappings)
    return {"message": f"已更新规则 {barcode}"}


@router.delete("/{barcode}")
async def delete_barcode(
    barcode: str,
    current_user: dict = Depends(get_current_user),
):
    mappings = _load_mappings()
    if barcode not in mappings:
        raise HTTPException(404, f"未找到条码映射 {barcode}")
    del mappings[barcode]
    _save_mappings(mappings)
    return {"message": f"已删除映射 {barcode}"}
