#!/usr/bin/env python3

import os
import subprocess
import argparse
import json
from tabulate import tabulate
from clboss.alias_cache import lookup_alias

def run_lightning_cli_command(lightning_dir, network_option, command, *args):
    try:
        command = ['lightning-cli', network_option, command, *args]
        if lightning_dir:
            command = command[:2] + [f'--lightning-dir={lightning_dir}'] + command[2:]
        result = subprocess.run(command, capture_output=True, text=True, check=True)
        return json.loads(result.stdout)
    except subprocess.CalledProcessError as e:
        print(f"Command '{command}' failed with error: {e}")
    except json.JSONDecodeError as e:
        print(f"Failed to parse JSON from command '{command}': {e}")
    return None

headers = [
    "Alias",
    "In Forwarded",
    "PPM",
    "In Earn",
    "Out Forwarded",
    "PPM",
    "Out Earn",
    "In Rebal",
    "PPM",
    "In Exp",
    "Out Rebal",
    "PPM",
    "Out Exp",
    "Net Earn",
]

def calculate_net_earnings(data, lightning_dir, network_option):
    rows = []

    # Initialize totals
    total_net_earnings = 0
    total_in_earnings = 0
    total_in_forwarded = 0
    total_in_expenditures = 0
    total_in_rebalanced = 0
    total_out_earnings = 0
    total_out_forwarded = 0
    total_out_expenditures = 0
    total_out_rebalanced = 0

    for node, stats in data['recent'].items():
        in_earnings = stats['in_earnings']
        in_forwarded = stats['in_forwarded']
        in_expenditures = stats['in_expenditures']
        in_rebalanced = stats['in_rebalanced']

        out_earnings = stats['out_earnings']
        out_forwarded = stats['out_forwarded']
        out_expenditures = stats['out_expenditures']
        out_rebalanced = stats['out_rebalanced']

        # Skip rows where all values are zero
        if (
            in_earnings == 0 and in_forwarded == 0 and in_expenditures == 0 and in_rebalanced == 0 and
            out_earnings == 0 and out_forwarded == 0 and out_expenditures == 0 and out_rebalanced == 0
        ):
            continue

        alias = lookup_alias(run_lightning_cli_command, lightning_dir, network_option, node)

        in_forwarded_rate = (in_earnings / in_forwarded) * 1_000_000 if in_forwarded != 0 else 0
        in_rebalance_rate = (in_expenditures / in_rebalanced) * 1_000_000 if in_rebalanced != 0 else 0
        out_forwarded_rate = (out_earnings / out_forwarded) * 1_000_000 if out_forwarded != 0 else 0
        out_rebalance_rate = (out_expenditures / out_rebalanced) * 1_000_000 if out_rebalanced != 0 else 0

        net_earnings = in_earnings - in_expenditures + out_earnings - out_expenditures

        # Update totals
        total_net_earnings += net_earnings
        total_in_earnings += in_earnings
        total_in_forwarded += in_forwarded
        total_in_expenditures += in_expenditures
        total_in_rebalanced += in_rebalanced
        total_out_earnings += out_earnings
        total_out_forwarded += out_forwarded
        total_out_expenditures += out_expenditures
        total_out_rebalanced += out_rebalanced

        rows.append([
            alias,
            f"{in_forwarded:,}".replace(',', '_'),
            f"{in_forwarded_rate:,.0f}",
            f"{in_earnings:,}".replace(',', '_'),
            f"{out_forwarded:,}".replace(',', '_'),
            f"{out_forwarded_rate:,.0f}",
            f"{out_earnings:,}".replace(',', '_'),
            f"{in_rebalanced:,}".replace(',', '_'),
            f"{in_rebalance_rate:,.0f}",
            f"{in_expenditures:,}".replace(',', '_'),
            f"{out_rebalanced:,}".replace(',', '_'),
            f"{out_rebalance_rate:,.0f}",
            f"{out_expenditures:,}".replace(',', '_'),
            f"{net_earnings:,}".replace(',', '_'),
        ])

    avg_in_earnings_rate = (total_in_earnings / total_in_forwarded) * 1_000_000 if total_in_forwarded != 0 else 0
    avg_out_earnings_rate = (total_out_earnings / total_out_forwarded) * 1_000_000 if total_out_forwarded != 0 else 0
    avg_in_expenditures_rate = (total_in_expenditures / total_in_rebalanced) * 1_000_000 if total_in_rebalanced != 0 else 0
    avg_out_expenditures_rate = (total_out_expenditures / total_out_rebalanced) * 1_000_000 if total_out_rebalanced != 0 else 0

    # Divide the net earnings total by 2
    total_net_earnings /= 2

    # Add a separator row
    rows.append(["-" * len(header) for header in headers])

    # Append the total row
    rows.append([
        "TOTAL",
        f"{total_in_forwarded:,}".replace(',', '_'),
        f"{avg_in_earnings_rate:,.0f}",
        f"{total_in_earnings:,}".replace(',', '_'),
        f"{total_out_forwarded:,}".replace(',', '_'),
        f"{avg_out_earnings_rate:,.0f}",
        f"{total_out_earnings:,}".replace(',', '_'),
        f"{total_in_rebalanced:,}".replace(',', '_'),
        f"{avg_in_expenditures_rate:,.0f}",
        f"{total_in_expenditures:,}".replace(',', '_'),
        f"{total_out_rebalanced:,}".replace(',', '_'),
        f"{avg_out_expenditures_rate:,.0f}",
        f"{total_out_expenditures:,}".replace(',', '_'),
        f"{int(total_net_earnings):,}".replace(',', '_'),
    ])

    return rows

def main():
    parser = argparse.ArgumentParser(description="Run lightning-cli with specified network")
    parser.add_argument('--mainnet', action='store_true', help='Run on mainnet')
    parser.add_argument('--testnet', action='store_true', help='Run on testnet')
    parser.add_argument('--signet', action='store_true', help='Run on signet')
    parser.add_argument('--regtest', action='store_true', help='Run on regtest')
    parser.add_argument('--network', help='Set the network explicitly')

    parser.add_argument('days', nargs='?', help='The number of days to pass to clboss-earnings-history (optional)')

    parser.add_argument('--lightning-dir', help='lightning data location')

    args = parser.parse_args()

    # Reconcile network option
    if args.network:
        network_option = f'--network={args.network}'
    elif args.testnet:
        network_option = '--network=testnet'
    elif args.signet:
        network_option = '--network=signet'
    elif args.regtest:
        network_option = '--network=regtest'
    else:
        network_option = '--network=bitcoin'	# lightning-cli wants "bitcoin" for mainnet

    if args.lightning_dir:
        lightning_dir = args.lightning_dir
        assert os.path.isdir(lightning_dir), f'"{lightning_dir}" is not a valid directory'
    else:
        lightning_dir = None

    if args.days:
        earnings_data = run_lightning_cli_command(lightning_dir, network_option, 'clboss-recent-earnings', str(args.days))
    else:
        earnings_data = run_lightning_cli_command(lightning_dir, network_option, 'clboss-recent-earnings')

    if earnings_data:
        rows = calculate_net_earnings(earnings_data, lightning_dir, network_option)
        print(tabulate(rows, headers=headers, tablefmt="pretty", stralign="right", numalign="right"))

if __name__ == "__main__":
    main()
