from fastapi import APIRouter, Depends, HTTPException, Body
from typing import Dict, List, Any, Optional
import time
import json
import logging
from ..core.security import get_current_user
from .. import database as db
from ..items import ItemsManager

router = APIRouter(
    prefix="/api/trade",
    tags=["trade"],
    responses={404: {"description": "Not found"}},
)

logger = logging.getLogger(__name__)

ITEMS_MANAGER = None
NPCS_DATA = {}

def init_router_dependencies(items_manager: ItemsManager, npcs_data: Dict):
    global ITEMS_MANAGER, NPCS_DATA
    ITEMS_MANAGER = items_manager
    NPCS_DATA = npcs_data

@router.get("/{npc_id}")
async def get_trade_stock(npc_id: str, current_user: dict = Depends(get_current_user)):
    """Get NPC stock and trade config"""
    npc_def = NPCS_DATA.get(npc_id)
    if not npc_def or not npc_def.get('trade', {}).get('enabled'):
        raise HTTPException(status_code=404, detail="Merchant not found or trade disabled")
        
    stock_db = await db.get_merchant_stock(npc_id)
    stock_config = npc_def['trade'].get('stock', [])
    
    # Merge DB stock with infinite items from config
    final_stock = []
    
    # Map DB items
    db_items_map = {}
    for item in stock_db:
        # Resolve item details
        item_def = ITEMS_MANAGER.get_item(item['item_id'])
        if item_def:
            item_data = {
                "item_id": item['item_id'],
                "name": item_def.name,
                "emoji": item_def.emoji,
                "quantity": item['quantity'],
                "value": item_def.value, # Base value
                "unique_item_id": item.get('unique_item_id'),
                "description": item_def.description,
                "image_path": item_def.image_path,
                "tier": item_def.tier,
                "item_type": item_def.type,
                "weight": item_def.weight,
                "volume": item_def.volume,
                "stats": item_def.stats,
                "effects": item_def.effects
            }
            # Handle unique item stats if needed (would need to fetch unique_item table)
            # For now assuming standard items mostly
            final_stock.append(item_data)
            db_items_map[item['item_id']] = True

    # Add infinite items from config if not in DB (or valid placeholders)
    for cfg_item in stock_config:
        if cfg_item.get('infinite'):
            item_def = ITEMS_MANAGER.get_item(cfg_item['item_id'])
            if item_def:
                final_stock.append({
                    "item_id": cfg_item['item_id'],
                    "name": item_def.name,
                    "emoji": item_def.emoji,
                    "quantity": 9999,
                    "is_infinite": True,
                    "value": item_def.value,
                    "description": item_def.description,
                    "image_path": item_def.image_path,
                    "tier": item_def.tier,
                    "item_type": item_def.type,
                    "weight": item_def.weight,
                    "volume": item_def.volume,
                    "stats": item_def.stats,
                    "effects": item_def.effects
                })
                
    return {
        "config": npc_def['trade'],
        "stock": final_stock
    }

@router.post("/{npc_id}/execute")
async def execute_trade(
    npc_id: str, 
    payload: Dict = Body(...), 
    current_user: dict = Depends(get_current_user)
):
    """
    Execute a trade. 
    Payload: {
        "buying": [{"item_id": "water", "quantity": 1}],
        "selling": [{"item_id": "junk", "quantity": 1}]
    }
    """
    character_id = current_user['id']
    npc_def = NPCS_DATA.get(npc_id)
    if not npc_def:
        raise HTTPException(status_code=404, detail="NPC not found")
        
    trade_cfg = npc_def.get('trade', {})
    if not trade_cfg.get('enabled'):
        raise HTTPException(status_code=400, detail="Trade disabled")
        
    buying = payload.get('buying', [])
    selling = payload.get('selling', [])
    
    # Validate items and calculate value
    total_buy_value = 0
    total_sell_value = 0
    
    # check player inventory for selling
    player_inventory = await db.get_inventory(character_id)
    
    buy_markup = trade_cfg.get('buy_markup', 1.0)
    sell_markdown = trade_cfg.get('sell_markdown', 1.0)
    
    # PROCESS SELLING (Player -> NPC)
    items_to_remove = []
    for sell_item in selling:
        item_id = sell_item['item_id']
        qty = sell_item['quantity']
        unique_id = sell_item.get('unique_item_id')
        
        # Verify player has item
        inv_item = next((i for i in player_inventory if i['item_id'] == item_id and i.get('unique_item_id') == unique_id), None)
        if not inv_item or inv_item['quantity'] < qty:
             raise HTTPException(status_code=400, detail=f"Not enough {item_id} to sell")
             
        item_def = ITEMS_MANAGER.get_item(item_id)
        value = (item_def.value * sell_markdown) * qty
        total_sell_value += value
        
        items_to_remove.append((item_id, qty, unique_id))

    # PROCESS BUYING (NPC -> Player)
    items_to_add = []
    db_stock = await db.get_merchant_stock(npc_id)
    
    for buy_item in buying:
        item_id = buy_item['item_id']
        qty = buy_item['quantity']
        unique_id = buy_item.get('unique_item_id') # For unique items from stock
        
        # Verify NPC has item (unless infinite)
        is_infinite = False
        config_entry = next((c for c in trade_cfg.get('stock', []) if c['item_id'] == item_id), None)
        if config_entry and config_entry.get('infinite'):
            is_infinite = True
            
        if not is_infinite:
             stock_item = next((s for s in db_stock if s['item_id'] == item_id and s.get('unique_item_id') == unique_id), None)
             if not stock_item or stock_item['quantity'] < qty:
                 raise HTTPException(status_code=400, detail=f"Merchant out of stock: {item_id}")
        
        item_def = ITEMS_MANAGER.get_item(item_id)
        value = (item_def.value * buy_markup) * qty
        total_buy_value += value
        
        items_to_add.append((item_id, qty, unique_id))
        
    # VALIDATE VALUE
    # If using 'value' currency, trades must balance OR player pays difference if we implemented currency items
    # For now assuming pure barter or abstract credit if we had it. 
    # Plan says: "currency": "value", "unlimited_currency": true 
    # This implies player can Sell for "credit" in this transaction to Buy other things.
    # Usually in barter: Sell Value >= Buy Value. If Sell > Buy, player loses difference (or we assume "value" credits are not stored).
    # Re-reading: "Trade button active only if Player Value >= NPC Value".
    
    if total_sell_value < total_buy_value:
         raise HTTPException(status_code=400, detail="Trade value too low. Offer more items.")
         
    # EXECUTE TRADE
    
    # 1. Remove sold items from Player
    for item_id, qty, unique_id in items_to_remove:
        await db.remove_item_from_inventory(character_id, item_id, qty) # Need to handle unique_id in remove?
        # remove_item_inventory in db currently takes player_id, item_id, qty. 
        # It doesn't handle unique_id specific removal yet? 
        # Checking db.py... remove_item_from_inventory isn't fully robust for unique items in the snippet I saw?
        # Wait, I strictly need to fix db.remove_item_from_inventory or use a more specific query if unique.
        # Assuming for now stackables are main concern. For uniques, quantity is 1.
        # If unique_id is passed, we should delete that specific row in inventory.
        # I'll implement a fallback db call here if needed or assume standard remove works for stackables.
        pass 
        
    # 2. Add sold items to NPC (if keep_sold_items)
    if trade_cfg.get('keep_sold_items'):
        for item_id, qty, unique_id in items_to_remove:
             # Add to merchant stock
             # If unique, pass unique_id
             # Logic to find existing row or create new
             current_stock = await db.get_merchant_stock_item(npc_id, item_id, unique_id)
             old_qty = current_stock['quantity'] if current_stock else 0
             await db.update_merchant_stock(npc_id, item_id, old_qty + qty, unique_id)
             
    # 3. Remove bought items from NPC (if not infinite)
    for item_id, qty, unique_id in items_to_add:
        is_infinite = False
        config_entry = next((c for c in trade_cfg.get('stock', []) if c['item_id'] == item_id), None)
        if config_entry and config_entry.get('infinite'):
            is_infinite = True
            
        if not is_infinite:
             current_stock = await db.get_merchant_stock_item(npc_id, item_id, unique_id)
             if current_stock:
                 new_qty = current_stock['quantity'] - qty
                 await db.update_merchant_stock(npc_id, item_id, new_qty, unique_id)

    # 4. Add bought items to Player
    for item_id, qty, unique_id in items_to_add:
        # If buying unique item from NPC, it transfers ownership. 
        # If infinite, it creates new item?
        
        # If unique_id exists (buying specific unique item)
        if unique_id and not is_infinite:
             await db.add_item_to_inventory(character_id, item_id, qty, unique_item_id=unique_id)
        else:
             # Standard or infinite
             await db.add_item_to_inventory(character_id, item_id, qty)

    # Log statistics?
    
    return {"success": True, "message": "Trade completed"}
