"""Database repositories for data access."""

from typing import Optional, List, Sequence
from datetime import datetime
from decimal import Decimal
from sqlalchemy import select, update, delete
from sqlalchemy.ext.asyncio import AsyncSession
from .database import Order, Position, OrderStatus, OrderSide, OrderType, MarketData

class BaseRepository:
    """Base repository."""
    
    def __init__(self, session: AsyncSession):
        """Initialize repository."""
        self.session = session

class OrderRepository(BaseRepository):
    """Order repository."""
    
    async def create(self, order: Order) -> Order:
        """Create new order."""
        self.session.add(order)
        await self.session.commit()
        await self.session.refresh(order)
        return order
    
    async def get_by_id(self, order_id: int) -> Optional[Order]:
        """Get order by ID."""
        result = await self.session.execute(
            select(Order).where(Order.id == order_id)
        )
        return result.scalar_one_or_none()
    
    async def get_all(self, limit: int = 100, offset: int = 0) -> Sequence[Order]:
        """Get all orders."""
        result = await self.session.execute(
            select(Order).limit(limit).offset(offset).order_by(Order.created_at.desc())
        )
        return result.scalars().all()
    
    async def update_status(
        self, 
        order_id: int, 
        status: OrderStatus, 
        exchange_order_id: Optional[str] = None,
        fee: Optional[Decimal] = None
    ) -> Optional[Order]:
        """Update order status."""
        values = {"status": status, "updated_at": datetime.utcnow()}
        if exchange_order_id:
            values["exchange_order_id"] = exchange_order_id
        if fee is not None:
            values["fee"] = fee
            
        await self.session.execute(
            update(Order)
            .where(Order.id == order_id)
            .values(**values)
        )
        await self.session.commit()
        return await self.get_by_id(order_id)

    async def get_open_orders(self, paper_trading: bool = True) -> Sequence[Order]:
        """Get open orders."""
        result = await self.session.execute(
            select(Order).where(
                Order.paper_trading == paper_trading,
                Order.status.in_([OrderStatus.PENDING, OrderStatus.OPEN, OrderStatus.PARTIALLY_FILLED])
            )
        )
        return result.scalars().all()
    
    async def delete(self, order_id: int) -> bool:
        """Delete order."""
        result = await self.session.execute(
            delete(Order).where(Order.id == order_id)
        )
        await self.session.commit()
        return result.rowcount > 0

class PositionRepository(BaseRepository):
    """Position repository."""
    
    async def get_all(self, paper_trading: bool = True) -> Sequence[Position]:
        """Get all positions."""
        result = await self.session.execute(
            select(Position).where(Position.paper_trading == paper_trading)
        )
        return result.scalars().all()
    
    async def get_by_symbol(self, symbol: str, paper_trading: bool = True) -> Optional[Position]:
        """Get position by symbol."""
        result = await self.session.execute(
            select(Position).where(
                Position.symbol == symbol,
                Position.paper_trading == paper_trading
            )
        )
        return result.scalar_one_or_none()
