"""Hetzner Cloud provider implementation."""

import socket
import time

from hcloud import Client
from hcloud.images import Image
from hcloud.server_types import ServerType

from beanflows_pipeline.providers import Instance
from beanflows_pipeline.vault import get_secret


def _get_client() -> Client:
    token = get_secret("HETZNER_API_TOKEN")
    if not token:
        raise ValueError("HETZNER_API_TOKEN not found in secrets")
    return Client(token=token)


def create_instance(
    name: str,
    instance_type: str,
    ssh_key: str,
    location: str | None = None,
) -> Instance:
    client = _get_client()

    # Get or create SSH key
    ssh_keys = client.ssh_keys.get_all(name="materia-key")
    if ssh_keys:
        hcloud_key = ssh_keys[0]
    else:
        hcloud_key = client.ssh_keys.create(name="materia-key", public_key=ssh_key)

    server_type = ServerType(name=instance_type)
    image = Image(name="ubuntu-24.04")
    location_obj = location or "nbg1"

    response = client.servers.create(
        name=name,
        server_type=server_type,
        image=image,
        ssh_keys=[hcloud_key],
        location=location_obj,
        labels={"managed_by": "materia"},
    )

    server = response.server
    server.wait_until_status_is("running")

    return Instance(
        id=str(server.id),
        name=server.name,
        ip=server.public_net.ipv4.ip,
        status=server.status,
        provider="hetzner",
        type=instance_type,
    )


def destroy_instance(instance_id: str) -> None:
    client = _get_client()
    server = client.servers.get_by_id(int(instance_id))
    if server:
        server.delete()


def list_instances(label: str | None = None) -> list[Instance]:
    client = _get_client()

    label_selector = {"managed_by": "materia"}
    if label:
        label_selector["pipeline"] = label

    servers = client.servers.get_all(label_selector=label_selector)

    return [
        Instance(
            id=str(server.id),
            name=server.name,
            ip=server.public_net.ipv4.ip,
            status=server.status,
            provider="hetzner",
            type=server.server_type.name,
        )
        for server in servers
    ]


def get_instance(name: str) -> Instance | None:
    client = _get_client()
    servers = client.servers.get_all(name=name)
    if not servers:
        return None

    server = servers[0]
    return Instance(
        id=str(server.id),
        name=server.name,
        ip=server.public_net.ipv4.ip,
        status=server.status,
        provider="hetzner",
        type=server.server_type.name,
    )


def wait_for_ssh(ip: str, timeout: int = 300) -> bool:
    start = time.time()
    while time.time() - start < timeout:
        try:
            sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            sock.settimeout(5)
            result = sock.connect_ex((ip, 22))
            sock.close()
            if result == 0:
                time.sleep(10)
                return True
        except Exception:
            pass
        time.sleep(5)
    return False
