import copy
import subprocess
from datetime import datetime
from typing import List

from . import checks
from .lib import AdjustedTxn, get_avg_fifo, get_xirr


def get_lots(txns: List[AdjustedTxn]) -> List[AdjustedTxn]:
    local_txns = copy.deepcopy(txns)
    checks.check_base_currency(txns)

    buys = [txn for txn in local_txns if txn.qtty >= 0]
    sells = [txn for txn in local_txns if txn.qtty < 0]

    buys_lot: List[AdjustedTxn] = buys if len(sells) == 0 else []
    for sell in sells:
        previous_buys = [txn for txn in buys if txn.date <= sell.date]
        checks.check_short_sell_past(previous_buys, sell)
        later_buys = [txn for txn in buys if txn.date > sell.date]
        sell_qtty = abs(sell.qtty)

        i = 0
        while i < len(previous_buys) and sell_qtty > 0:
            previous_buy = previous_buys[i]
            if sell_qtty >= previous_buy.qtty:
                sell_qtty -= previous_buy.qtty
                previous_buys[i].qtty = 0
            else:
                previous_buys[i].qtty -= sell_qtty
                sell_qtty = 0
            i += 1

        buys_lot = [*previous_buys, *later_buys]

    return buys_lot


def get_sell_lots(lots: List[AdjustedTxn], sell_date: str, sell_qtty: float):
    checks.check_short_sell_current(lots, sell_qtty)
    buy_lots = get_lots(lots)
    previous_buys = [lot for lot in buy_lots.copy() if lot.date <= sell_date]

    fifo_lots: List[AdjustedTxn] = []
    sell_qtty_curr = sell_qtty

    i = 0
    while sell_qtty_curr > 0 and i < len(lots):
        buy = previous_buys[i]
        if buy.qtty == 0:
            pass
        elif sell_qtty_curr > buy.qtty:
            fifo_lots.append(
                AdjustedTxn(buy.date, buy.price, buy.base_cur, buy.qtty, buy.acct)
            )
            sell_qtty_curr -= buy.qtty
        else:
            fifo_lots.append(
                AdjustedTxn(buy.date, buy.price, buy.base_cur, sell_qtty_curr, buy.acct)
            )
            sell_qtty_curr = 0
        i += 1

    return fifo_lots


def txn2hl(
    txns: List[AdjustedTxn],
    date: str,
    cur: str,
    cash_account: str,
    revenue_account: str,
    value: float,
):
    base_curr = txns[0].base_cur
    avg_cost = get_avg_fifo(txns)
    sum_qtty = sum(txn.qtty for txn in txns)
    price = value / sum_qtty
    dt = datetime.strptime(date, "%Y-%m-%d").date()
    xirr = get_xirr(price, dt, txns) or 0 * 100

    txn_hl = f"""
{date} Sold {cur}
    ; commodity:{cur}, qtty:{sum_qtty:,.2f}, price:{price:,.2f}
    ; avg_fifo_cost:{avg_cost:,.4f}, xirr:{xirr:.2f}% annual percent rate 30/360US
    {cash_account}  {value:.2f} {base_curr}
"""

    for txn in txns:
        txn_hl += f"    {txn.acct}    {txn.qtty * -1} {cur} @ {txn.price} {base_curr}  ; buy_date:{txn.date}, base_cur:{txn.base_cur}\n"

    txn_hl += f"    {revenue_account}   "
    comm = ["hledger", "-f-", "print", "--explicit"]
    txn_proc = subprocess.run(comm, input=txn_hl.encode(), capture_output=True)
    txn_print: str = txn_proc.stdout.decode("utf8")
    return txn_print
