from fastapi import APIRouter, File, Form, HTTPException, UploadFile
from pydantic import BaseModel
from typing import Optional

from services.character_card import (
    list_characters,
    get_character,
    import_card_file,
    preview_card_file,
    update_character,
    update_appearance_tags,
)

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


class CardPatch(BaseModel):
    name: Optional[str] = None
    description: Optional[str] = None
    personality: Optional[str] = None
    scenario: Optional[str] = None
    first_mes: Optional[str] = None
    mes_example: Optional[str] = None
    appearance_tags: Optional[str] = None
    appearance_prose: Optional[str] = None
    lora_name: Optional[str] = None
    lora_weight: Optional[float] = None
    alternate_greetings_json: Optional[str] = None


@router.get("/")
async def list_all():
    return await list_characters()


@router.get("/{card_id}")
async def get_one(card_id: str):
    card = await get_character(card_id)
    if not card:
        raise HTTPException(status_code=404, detail="Карточка не найдена")
    return card


@router.post("/preview")
async def preview_card(file: UploadFile = File(...)):
    content = await file.read()
    try:
        return await preview_card_file(content, file.filename or "card.json")
    except Exception as e:
        raise HTTPException(status_code=400, detail=str(e))


@router.patch("/{card_id}")
async def patch_card(card_id: str, body: CardPatch):
    card = await get_character(card_id)
    if not card:
        raise HTTPException(status_code=404, detail="Карточка не найдена")
    fields = {k: v for k, v in body.model_dump().items() if v is not None}
    await update_character(card_id, fields)
    from services.personas import update_persona_appearance
    if "appearance_tags" in fields:
        await update_persona_appearance(f"card_{card_id}", fields["appearance_tags"])
    if {"lora_name", "lora_weight"} & fields.keys():
        from services.personas import update_persona_lora
        await update_persona_lora(f"card_{card_id}", fields.get("lora_name"), fields.get("lora_weight"))
    char_fields = {"name", "description", "personality", "scenario", "first_mes", "mes_example"}
    if char_fields & fields.keys():
        updated = await get_character(card_id)
        from services.character_card import build_system_prompt
        from services.personas import update_persona_prompt
        await update_persona_prompt(f"card_{card_id}", build_system_prompt(updated))
    if "first_mes" in fields or "alternate_greetings_json" in fields:
        from services.personas import patch_persona
        sync = {}
        if "first_mes" in fields:
            sync["first_mes"] = fields["first_mes"]
        if "alternate_greetings_json" in fields:
            sync["alternate_greetings_json"] = fields["alternate_greetings_json"]
        await patch_persona(f"card_{card_id}", sync)
    return await get_character(card_id)


@router.post("/{card_id}/avatar")
async def upload_avatar(card_id: str, file: UploadFile = File(...)):
    card = await get_character(card_id)
    if not card:
        raise HTTPException(status_code=404, detail="Карточка не найдена")
    content = await file.read()
    if not content.startswith(b"\x89PNG"):
        raise HTTPException(status_code=400, detail="Нужен PNG")
    from services.character_card import _save_avatar_bytes
    rel = _save_avatar_bytes(content, f"card_{card_id}")
    await update_character(card_id, {"avatar_path": rel})
    from services.personas import patch_persona
    await patch_persona(f"card_{card_id}", {"avatar_path": rel})
    return {"avatar_path": f"/static/{rel}"}


@router.post("/import")
async def import_card(
    file: UploadFile = File(...),
    lora_name: str = Form(""),
    lora_weight: float = Form(0.8),
    card_id: str = Form(""),
    name: str = Form(""),
    description: str = Form(""),
    personality: str = Form(""),
    scenario: str = Form(""),
    first_mes: str = Form(""),
    mes_example: str = Form(""),
    appearance_tags: str = Form(""),
    alternate_greetings_json: str = Form("[]"),
):
    content = await file.read()
    overrides = {
        "name": name or None,
        "description": description or None,
        "personality": personality or None,
        "scenario": scenario or None,
        "first_mes": first_mes or None,
        "mes_example": mes_example or None,
        "appearance_tags": appearance_tags or None,
        "alternate_greetings_json": alternate_greetings_json or "[]",
    }
    try:
        card = await import_card_file(
            content,
            file.filename or "card.json",
            lora_name=lora_name,
            lora_weight=lora_weight,
            overrides=overrides,
            card_id=card_id.strip() or None,
        )
    except Exception as e:
        raise HTTPException(status_code=400, detail=str(e))
    return {
        "status": "imported",
        "card_id": card["card_id"],
        "persona_id": f"card_{card['card_id']}",
        "name": card["name"],
        "alternate_greetings": card.get("alternate_greetings", []),
    }


@router.delete("/{card_id}")
async def remove_card(card_id: str):
    from services.personas import delete_persona

    if not await delete_persona(f"card_{card_id}"):
        raise HTTPException(status_code=404, detail="Карточка не найдена")
    return {"status": "deleted", "card_id": card_id}
