#!/usr/bin/env -S uv run --script

# /// script
# requires-python = ">=3.10"
# dependencies = [
#   "click>=8.3.3",
#   "requests[socks]>=2.34.0",
# ]
# ///

from backends import get_backend
from backend import Change
from server import SocketServer, setup_server_logging

import os
import click
import json
import logging
import sqlite3
import sys

root = logging.getLogger()
root.setLevel(logging.INFO)

handler = logging.StreamHandler(sys.stdout)
handler.setLevel(logging.DEBUG)
formatter = logging.Formatter("%(message)s")
handler.setFormatter(formatter)
root.addHandler(handler)


@click.command()
@click.argument("backend-url")
@click.option(
    "--lightning-dir",
    type=click.Path(exists=True),
    default=None,
    help="Use an existing lightning directory (default: initialize an empty backup).",
)
def init(lightning_dir, backend_url):
    destination = backend_url
    backend = get_backend(destination, create=True)

    if lightning_dir is not None:
        lock_file = os.path.join(lightning_dir, "backup.lock")
        db_file = os.path.join(lightning_dir, "lightningd.sqlite3")

        with open(lock_file, "w") as f:
            f.write(
                json.dumps(
                    {
                        "backend_url": destination,
                    }
                )
            )

        data_version = 0
        if os.path.exists(db_file):
            print(
                "Found an existing database at {db_file}, initializing the backup with a snapshot".format(
                    db_file=db_file
                )
            )
            # Peek into the DB to see if we have
            db = sqlite3.connect(db_file)
            cur = db.cursor()
            rows = cur.execute("SELECT intval FROM vars WHERE name = 'data_version'")
            data_version = rows.fetchone()[0]

            snapshot = Change(
                version=data_version,
                snapshot=open(db_file, "rb").read(),
                transaction=None,
            )
            if not backend.add_change(snapshot):
                print("Could not write snapshot to backend")
                sys.exit(1)
            else:
                print(
                    "Successfully written initial snapshot to {destination}".format(
                        destination=destination
                    )
                )
        else:
            print("Database does not exist yet, created an empty backup file")

    print(
        "Initialized backup backend {destination}, you can now start Core-Lightning".format(
            destination=destination,
        )
    )


@click.command()
@click.argument("backend-url")
@click.argument("restore-destination")
def restore(backend_url, restore_destination):
    destination = backend_url
    backend = get_backend(destination)
    backend.restore(restore_destination)


@click.command()
@click.argument("backend-url")
@click.argument("addr")
@click.option(
    "--log-mode",
    type=click.Choice(["plain", "systemd"], case_sensitive=False),
    default="plain",
    help="Debug log mode, defaults to plain",
)
@click.option(
    "--log-level",
    type=click.Choice(
        ["debug", "info", "notice", "warning", "error", "critical"],
        case_sensitive=False,
    ),
    default="info",
    help="Debug log level, defaults to info",
)
def server(backend_url, addr, log_mode, log_level):
    backend = get_backend(backend_url)
    addr, port = addr.split(":")
    port = int(port)

    setup_server_logging(log_mode, log_level)

    server = SocketServer((addr, port), backend)
    server.run()


@click.group()
def cli():
    pass


cli.add_command(init)
cli.add_command(restore)
cli.add_command(server)

if __name__ == "__main__":
    cli()
