"""Tax lot tracking for cost basis and wash sale detection.

Feature: autonomous-trading-engine

Pure computation module for FIFO tax lot closing and wash sale
detection within the 30-day window. Used by the Trading Engine
for tax-loss harvesting awareness.
"""

from __future__ import annotations

from dataclasses import dataclass
from datetime import date, timedelta


@dataclass
class TaxLot:
    """A single tax lot representing a purchase of shares."""

    ticker: str
    quantity: int
    cost_basis_per_share: float
    acquisition_date: date
    status: str = "open"  # open | closed | washed


@dataclass
class ClosedLot:
    """Result of closing a tax lot via FIFO."""

    ticker: str
    quantity: int
    cost_basis_per_share: float
    exit_price: float
    realized_pnl: float
    acquisition_date: date
    closed_date: date


class TaxLotTracker:
    """Pure computation for FIFO lot closing and wash sale detection."""

    def close_lots_fifo(
        self,
        lots: list[TaxLot],
        quantity: int,
        exit_price: float,
        exit_date: date,
    ) -> list[ClosedLot]:
        """Close lots in FIFO order (earliest acquired first).

        Processes open lots sorted by acquisition_date ascending,
        closing shares until the requested quantity is fulfilled.
        Returns a list of ClosedLot records with realized P&L.

        Parameters
        ----------
        lots:
            All tax lots for the ticker (open ones will be selected).
        quantity:
            Number of shares to close.
        exit_price:
            Price per share at exit.
        exit_date:
            Date the lots are being closed.

        Returns
        -------
        list[ClosedLot]
            Closed lot records in FIFO order.
        """
        open_lots = sorted(
            [lot for lot in lots if lot.status == "open"],
            key=lambda lot: lot.acquisition_date,
        )

        closed: list[ClosedLot] = []
        remaining = quantity

        for lot in open_lots:
            if remaining <= 0:
                break

            close_qty = min(lot.quantity, remaining)
            realized_pnl = (exit_price - lot.cost_basis_per_share) * close_qty

            closed.append(
                ClosedLot(
                    ticker=lot.ticker,
                    quantity=close_qty,
                    cost_basis_per_share=lot.cost_basis_per_share,
                    exit_price=exit_price,
                    realized_pnl=realized_pnl,
                    acquisition_date=lot.acquisition_date,
                    closed_date=exit_date,
                )
            )

            remaining -= close_qty

        return closed

    def check_wash_sale(
        self,
        loss_date: date,
        purchases: list[TaxLot],
    ) -> bool:
        """Check whether any purchase falls within the 30-day wash sale window.

        A wash sale occurs when the same ticker is purchased within
        30 days before or after a loss-closing date.

        Parameters
        ----------
        loss_date:
            The date the loss was realized.
        purchases:
            Tax lots representing purchases of the same ticker.

        Returns
        -------
        bool
            True if any purchase is within the 30-day window.
        """
        window_start = loss_date - timedelta(days=30)
        window_end = loss_date + timedelta(days=30)

        for lot in purchases:
            if window_start <= lot.acquisition_date <= window_end:
                return True

        return False
