from fastapi import APIRouter, Depends, HTTPException
from pydantic import BaseModel, Field
from typing import Optional
from sqlalchemy.orm import Session
from app.database import get_db
from app.models.miner import Miner
from app.services import mining_calculator, coingecko
from dataclasses import asdict

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


class CalculationRequest(BaseModel):
    miner_id: Optional[int] = None
    miner_name: Optional[str] = None
    coin: str = Field(..., description="Coin symbol: BTC, LTC, DOGE, etc.")
    electricity_price_sar: float = Field(..., gt=0, description="SAR per kWh")


class ComparisonRequest(BaseModel):
    miner_ids: list[int] = Field(..., min_length=2, max_length=10)
    coin: str
    electricity_price_sar: float = Field(..., gt=0)


@router.post("/")
async def calculate_profit(req: CalculationRequest, db: Session = Depends(get_db)):
    # Find miner
    miner = None
    if req.miner_id:
        miner = db.query(Miner).filter(Miner.id == req.miner_id).first()
    elif req.miner_name:
        miner = (
            db.query(Miner)
            .filter(Miner.name.ilike(f"%{req.miner_name.lower()}%"))
            .order_by(Miner.hashrate.desc())
            .first()
        )

    if not miner:
        raise HTTPException(status_code=404, detail="Miner not found")

    # Check coin compatibility
    supported = (miner.supported_coins or "").upper()
    if req.coin.upper() not in supported:
        raise HTTPException(
            status_code=400,
            detail=f"Miner {miner.name} does not support {req.coin}. Supported: {supported}",
        )

    # Get live price
    coin_price = await coingecko.get_coin_price(req.coin)
    mining_params = coingecko.get_mining_params(req.coin)

    result = mining_calculator.calculate_mining_profit(
        hashrate_ths=miner.hashrate,
        power_w=miner.power_consumption,
        electricity_sar_per_kwh=req.electricity_price_sar,
        coin_price_usd=coin_price,
        block_reward=mining_params["block_reward"],
        block_time_seconds=mining_params["block_time"],
        difficulty=mining_params["difficulty"],
        network_hashrate_ths=mining_params["network_hashrate"],
        miner_name=miner.name,
        coin=req.coin.upper(),
        algorithm=mining_params["algorithm"],
    )

    return {
        "miner": miner.to_dict(),
        "calculation": asdict(result),
        "coin_price_usd": coin_price,
        "is_profitable": result.daily_profit_usd > 0,
    }


@router.post("/compare")
async def compare_miners(req: ComparisonRequest, db: Session = Depends(get_db)):
    miners = db.query(Miner).filter(Miner.id.in_(req.miner_ids)).all()
    if not miners:
        raise HTTPException(status_code=404, detail="No miners found")

    coin_price = await coingecko.get_coin_price(req.coin)
    mining_params = coingecko.get_mining_params(req.coin)
    results = []

    for miner in miners:
        supported = (miner.supported_coins or "").upper()
        if req.coin.upper() not in supported:
            results.append({
                "miner": miner.to_dict(),
                "error": f"Does not support {req.coin}",
                "calculation": None,
            })
            continue

        result = mining_calculator.calculate_mining_profit(
            hashrate_ths=miner.hashrate,
            power_w=miner.power_consumption,
            electricity_sar_per_kwh=req.electricity_price_sar,
            coin_price_usd=coin_price,
            block_reward=mining_params["block_reward"],
            block_time_seconds=mining_params["block_time"],
            difficulty=mining_params["difficulty"],
            network_hashrate_ths=mining_params["network_hashrate"],
            miner_name=miner.name,
            coin=req.coin.upper(),
            algorithm=mining_params["algorithm"],
        )
        results.append({
            "miner": miner.to_dict(),
            "calculation": asdict(result),
            "is_profitable": result.daily_profit_usd > 0,
        })

    results.sort(
        key=lambda x: x["calculation"]["monthly_profit_usd"] if x["calculation"] else float("-inf"),
        reverse=True,
    )

    return {
        "coin": req.coin.upper(),
        "coin_price_usd": coin_price,
        "electricity_price_sar": req.electricity_price_sar,
        "results": results,
    }
