"""
cli.py — TerraLens UI
All Textual screens, widgets, the InsightTF app class, and the CLI entry point.
"""

from __future__ import annotations

import json
import subprocess
from pathlib import Path
from typing import Any

from textual import on, work
from textual.app import App, ComposeResult
from textual.binding import Binding
from textual.containers import Container, Horizontal, Vertical, ScrollableContainer
from textual.screen import ModalScreen
from textual.widgets import (
    Button,
    Footer,
    Header,
    Input,
    Label,
    RichLog,
    Static,
    TabbedContent,
    TabPane,
    TextArea,
    Tree,
)
from textual.widgets.tree import TreeNode
from rich.table import Table
from rich import box

from .state import APP_CONFIG, SAMPLE_STATE, load_state, format_value
from .catalog import (
    ALL_AWS_RESOURCES,
    RESOURCE_TEMPLATES,
)


# ─────────────────────────────────────────────
# Overview Page
# ─────────────────────────────────────────────
class StatCard(Static):
    DEFAULT_CSS = """
    StatCard {
        border: tall $accent;
        padding: 1 2;
        margin: 1;
        width: 1fr;
        background: $surface;
        height: 7;
    }
    StatCard .card-label {
        color: $text-muted;
        text-style: italic;
    }
    StatCard .card-value {
        text-style: bold;
        color: $accent;
        content-align: center middle;
        text-align: center;
        padding-top: 1;
    }
    """

    def __init__(self, label: str, value: str, **kwargs: Any) -> None:
        super().__init__(**kwargs)
        self._label = label
        self._value = value

    def compose(self) -> ComposeResult:
        yield Label(self._label, classes="card-label")
        yield Label(self._value, classes="card-value")


class OverviewPage(Container):
    DEFAULT_CSS = """
    OverviewPage {
        padding: 1 2;
    }
    #cards-row {
        height: auto;
        margin-bottom: 1;
    }
    #resource-table {
        border: tall $panel;
        padding: 1 2;
        background: $surface;
        height: 1fr;
    }
    .section-title {
        text-style: bold;
        color: $accent;
        margin-bottom: 1;
    }
    """

    def __init__(self, state: dict[str, Any], **kwargs: Any) -> None:
        super().__init__(**kwargs)
        self._state = state

    def compose(self) -> ComposeResult:
        resources = self._state.get("resources", [])
        tf_ver = self._state.get("terraform_version", "N/A")
        serial = self._state.get("serial", "N/A")
        total = len(resources)

        yield Label("📊  Infrastructure Overview", classes="section-title")
        with Horizontal(id="cards-row"):
            yield StatCard("Terraform Version", tf_ver)
            yield StatCard("State Serial", str(serial))
            yield StatCard("Total Resources", str(total))
            yield StatCard(
                "Providers",
                str(len({r.get("provider", "").split("/")[-1] for r in resources})),
            )

        yield Label("Resource Summary", classes="section-title")
        yield self._build_table(resources)

    def _build_table(self, resources: list[dict]) -> Static:
        table = Table(
            "Type", "Name", "Provider", "Instances",
            box=box.SIMPLE_HEAVY,
            border_style="cyan",
            header_style="bold cyan",
            show_lines=True,
        )
        for r in resources:
            rtype = r.get("type", "N/A")
            name = r.get("name", "N/A")
            provider = r.get("provider", "N/A").split("/")[-1].replace('"', "")
            instances = str(len(r.get("instances", [])))
            table.add_row(rtype, name, provider, instances)
        return Static(table)


# ─────────────────────────────────────────────
# Manage Page — widgets
# ─────────────────────────────────────────────
class ResourceTree(Tree):
    DEFAULT_CSS = """
    ResourceTree {
        border: tall $panel;
        background: $surface;
        padding: 0 1;
        width: 35;
    }
    """


class AttributePanel(ScrollableContainer):
    DEFAULT_CSS = """
    AttributePanel {
        border: tall $panel;
        background: $surface;
        padding: 1 2;
        width: 1fr;
    }
    #attr-title {
        text-style: bold;
        color: $accent;
        margin-bottom: 1;
    }
    #attr-content {
        color: $text;
    }
    """

    def compose(self) -> ComposeResult:
        yield Label("Select a resource →", id="attr-title")
        yield Label("", id="attr-content")

    def show_resource(self, resource: dict, instance_attrs: dict) -> None:
        title = f"{resource['type']}.{resource['name']}"
        self.query_one("#attr-title", Label).update(f"📦  {title}")
        lines = []
        for k, v in instance_attrs.items():
            val_str = format_value(v)
            lines.append(f"[bold cyan]{k}[/bold cyan]:  {val_str}")
        self.query_one("#attr-content", Label).update("\n".join(lines))


# ─────────────────────────────────────────────
# Manage Page
# ─────────────────────────────────────────────
class ManagePage(Container):
    DEFAULT_CSS = """
    ManagePage {
        padding: 0 1;
    }
    #top-controls {
        height: auto;
        padding: 1 0;
        margin-bottom: 1;
    }
    #top-controls Button {
        margin-right: 1;
    }
    #main-split {
        height: 1fr;
    }
    #output-panel {
        border: tall $panel;
        background: $surface;
        padding: 1;
        height: 12;
        margin-top: 1;
    }
    #output-label {
        text-style: bold;
        color: $accent;
        margin-bottom: 1;
    }
    Button.-success { background: $success; }
    Button.-warning { background: $accent; }
    Button.-error   { background: $error; }
    """

    def __init__(self, state: dict[str, Any], **kwargs: Any) -> None:
        super().__init__(**kwargs)
        self._state = state
        self._resource_map: dict[str, tuple[dict, dict]] = {}

    def compose(self) -> ComposeResult:
        with Horizontal(id="top-controls"):
            yield Button("📝  Open in Editor",  id="btn-editor",    variant="default")
            yield Button("🔍  Plan",            id="btn-plan",      variant="primary")
            yield Button("💰  Cost Estimate",   id="btn-cost",      variant="default")
            yield Button("🔄  Detect Drift",    id="btn-drift",     variant="primary")
            yield Button("🗑️  Destroy Selected", id="btn-destroy",  variant="error")
            yield Button("⚡  Apply Now",        id="btn-apply-now", variant="success")

        with Horizontal(id="main-split"):
            yield ResourceTree("Resources", id="resource-tree")
            yield AttributePanel(id="attr-panel")

        yield Label("Output", id="output-label")
        yield RichLog(id="output-log", highlight=True, markup=True)

    def on_mount(self) -> None:
        self._populate_tree()

    def _populate_tree(self) -> None:
        tree = self.query_one("#resource-tree", ResourceTree)
        tree.clear()
        root = tree.root
        root.expand()

        resources = self._state.get("resources", [])
        type_nodes: dict[str, TreeNode] = {}

        for resource in resources:
            rtype = resource.get("type", "unknown")
            rname = resource.get("name", "unknown")

            if rtype not in type_nodes:
                icon = self._type_icon(rtype)
                node = root.add(f"{icon} {rtype}", expand=True)
                type_nodes[rtype] = node

            instances = resource.get("instances", [{}])
            attrs = instances[0].get("attributes", {}) if instances else {}
            leaf = type_nodes[rtype].add_leaf(f"  {rname}")
            self._resource_map[leaf.label.plain.strip()] = (resource, attrs)

    def _type_icon(self, rtype: str) -> str:
        icons = {
            "aws_instance":            "🖥️",
            "aws_s3_bucket":           "🪣",
            "aws_security_group":      "🛡️",
            "aws_db_instance":         "🗄️",
            "aws_vpc":                 "🌐",
            "aws_subnet":              "📡",
            "aws_iam_role":            "👤",
            "aws_lambda_function":     "⚡",
            "google_compute_instance": "🖥️",
            "azurerm_virtual_machine": "🖥️",
        }
        return icons.get(rtype, "📦")

    @on(Tree.NodeSelected)
    def on_node_selected(self, event: Tree.NodeSelected) -> None:
        label = event.node.label.plain.strip()
        if label in self._resource_map:
            resource, attrs = self._resource_map[label]
            self.query_one("#attr-panel", AttributePanel).show_resource(resource, attrs)

    # ── Plan ─────────────────────────────────────────────────────────────
    @on(Button.Pressed, "#btn-plan")
    def run_plan(self) -> None:
        log = self.query_one("#output-log", RichLog)
        log.clear()
        log.write("[bold green]▶ Running terraform plan...[/bold green]")
        self._run_real_plan(log)

    @work(thread=True)
    def _run_real_plan(self, log: RichLog) -> None:
        tf_dir = self.app._tf_dir
        which = subprocess.run(["which", "terraform"], capture_output=True, text=True)
        if which.returncode != 0:
            self.app.call_from_thread(log.write, "[bold red]✖ 'terraform' not found in PATH.[/bold red]")
            return
        try:
            proc = subprocess.Popen(
                ["terraform", "plan", "-no-color"],
                stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True, cwd=tf_dir,
            )
            for line in proc.stdout:
                stripped = line.rstrip()
                if stripped:
                    self.app.call_from_thread(log.write, stripped)
            proc.wait()
            if proc.returncode == 0:
                self.app.call_from_thread(log.write, "\n[bold green]✅ Plan complete (no changes).[/bold green]")
            elif proc.returncode == 2:
                self.app.call_from_thread(log.write, "\n[bold cyan]⚠ Plan complete (changes detected).[/bold cyan]")
            else:
                self.app.call_from_thread(log.write, f"\n[bold red]✖ terraform plan exited with code {proc.returncode}[/bold red]")
        except Exception as e:
            self.app.call_from_thread(log.write, f"[bold red]✖ Error: {e}[/bold red]")

    # ── Cost Estimate ─────────────────────────────────────────────────────
    @on(Button.Pressed, "#btn-cost")
    def show_cost(self) -> None:
        log = self.query_one("#output-log", RichLog)
        log.clear()
        log.write("[bold cyan]💰 Running Infracost estimate...[/bold cyan]")
        self._run_infracost(log)

    @work(thread=True)
    def _run_infracost(self, log: RichLog) -> None:
        import shutil
        tf_dir = self.app._tf_dir

        infracost_bin = (
            APP_CONFIG.get("infracost_path")
            or shutil.which("infracost")
            or str(Path.home() / ".local" / "bin" / "infracost")
        )
        if not Path(infracost_bin).exists() and not shutil.which(infracost_bin):
            self.app.call_from_thread(log.write, "[bold red]✖ Infracost not found.[/bold red]")
            self.app.call_from_thread(log.write, "  [bold cyan]python installer.py[/bold cyan]")
            return

        creds_path = Path.home() / ".config" / "infracost" / "credentials.yml"
        if not creds_path.exists():
            self.app.call_from_thread(log.write, "[bold cyan]⚠ Infracost is not authenticated.[/bold cyan]")
            self.app.call_from_thread(log.write, "Run:  [bold cyan]infracost auth login[/bold cyan]")
            return

        try:
            self.app.call_from_thread(log.write, "[dim]Fetching cloud pricing data...[/dim]")
            proc = subprocess.run(
                [infracost_bin, "breakdown", "--path", tf_dir, "--format", "json", "--no-color"],
                capture_output=True, text=True,
            )
            if proc.returncode != 0:
                self.app.call_from_thread(log.write, "[bold red]✖ Infracost error:[/bold red]")
                for line in proc.stderr.splitlines():
                    if line.strip():
                        self.app.call_from_thread(log.write, line)
                return

            data = json.loads(proc.stdout)
            projects = data.get("projects", [])
            if not projects:
                self.app.call_from_thread(log.write, "[cyan]No projects found.[/cyan]")
                return

            resources = projects[0].get("breakdown", {}).get("resources", [])
            self.app.call_from_thread(log.write, "")
            self.app.call_from_thread(log.write, f"  {'Resource':<50} {'Monthly':>12}")
            self.app.call_from_thread(log.write, "  " + "─" * 64)

            total = 0.0
            for r in resources:
                name = r.get("name", "unknown")
                cost = r.get("monthlyCost")
                if cost is None:
                    cost_str = "[dim]usage-based[/dim]"
                else:
                    cost = float(cost)
                    total += cost
                    cost_str = f"[green]${cost:>10.2f}[/green]"
                self.app.call_from_thread(log.write, f"  {name:<50} {cost_str}")

            self.app.call_from_thread(log.write, "  " + "─" * 64)
            unsupported = data.get("summary", {}).get("totalUnsupportedResources", 0)
            self.app.call_from_thread(
                log.write,
                f"  [bold]{'TOTAL MONTHLY ESTIMATE':<50}[/bold] [bold green]${total:>10.2f}[/bold green]"
            )
            if unsupported:
                self.app.call_from_thread(log.write, f"  [dim]{unsupported} resource(s) not supported by Infracost[/dim]")
            self.app.call_from_thread(log.write, "")
            self.app.call_from_thread(log.write, "[bold green]✅ Estimate complete.[/bold green]")

        except json.JSONDecodeError:
            self.app.call_from_thread(log.write, "[bold red]✖ Failed to parse Infracost output.[/bold red]")
        except Exception as e:
            self.app.call_from_thread(log.write, f"[bold red]✖ Error: {e}[/bold red]")

    # ── Drift Detection ───────────────────────────────────────────────────
    @on(Button.Pressed, "#btn-drift")
    def detect_drift(self) -> None:
        log = self.query_one("#output-log", RichLog)
        log.clear()
        log.write("[bold cyan]🔄 Detecting infrastructure drift...[/bold cyan]")
        log.write("[dim]Running: terraform plan -refresh-only -detailed-exitcode[/dim]")
        log.write("")
        self._run_drift_detection(log)

    @work(thread=True)
    def _run_drift_detection(self, log: RichLog) -> None:
        tf_dir = self.app._tf_dir
        which = subprocess.run(["which", "terraform"], capture_output=True, text=True)
        if which.returncode != 0:
            self.app.call_from_thread(log.write, "[bold red]✖ 'terraform' not found in PATH.[/bold red]")
            return
        try:
            proc = subprocess.Popen(
                ["terraform", "plan", "-refresh-only", "-detailed-exitcode", "-no-color"],
                stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True, cwd=tf_dir,
            )
            stdout_lines = []
            for line in proc.stdout:
                stripped = line.rstrip()
                if stripped:
                    stdout_lines.append(stripped)
                    self.app.call_from_thread(log.write, stripped)
            proc.wait()
            stderr_out = proc.stderr.read().strip()

            self.app.call_from_thread(log.write, "")
            self.app.call_from_thread(log.write, "─" * 60)

            if proc.returncode == 0:
                self.app.call_from_thread(log.write, "[bold green]✅ No drift detected — infrastructure matches state.[/bold green]")
            elif proc.returncode == 2:
                self.app.call_from_thread(log.write, "[bold cyan]⚠  Drift detected! Real infrastructure differs from state.[/bold cyan]")
                self.app.call_from_thread(log.write, "")
                drifted = []
                for line in stdout_lines:
                    if " has changed" in line or " has been deleted" in line or " has been created" in line:
                        resource = line.strip().lstrip("# ").split(" ")[0]
                        if "." in resource:
                            status = "deleted outside Terraform" if "deleted" in line else \
                                     "created outside Terraform" if "created" in line else "changed"
                            drifted.append((resource, status))
                if drifted:
                    self.app.call_from_thread(log.write, "[bold]Drifted resources:[/bold]")
                    for resource, status in drifted:
                        icon = "🟡" if status == "changed" else "🔴"
                        self.app.call_from_thread(log.write, f"  {icon}  [cyan]{resource}[/cyan]  →  {status}")
                    self.app.call_from_thread(log.write, "")
                    self.app.call_from_thread(log.write, "[dim]To fix: run terraform apply -refresh-only[/dim]")
                else:
                    self.app.call_from_thread(log.write, "[dim]See full output above for details.[/dim]")
            else:
                self.app.call_from_thread(log.write, f"[bold red]✖ terraform exited with code {proc.returncode}[/bold red]")
                if stderr_out:
                    self.app.call_from_thread(log.write, "[red]Error output:[/red]")
                    for line in stderr_out.splitlines():
                        self.app.call_from_thread(log.write, f"  {line}")
        except Exception as e:
            self.app.call_from_thread(log.write, f"[bold red]✖ Error: {e}[/bold red]")

    # ── Add Resource ──────────────────────────────────────────────────────
    @on(Button.Pressed, "#btn-editor")
    def open_in_editor(self) -> None:
        import shutil
        import subprocess
        log = self.query_one("#output-log", RichLog)
        tf_dir = self.app._tf_dir

        if not shutil.which("code"):
            log.clear()
            log.write("[bold red]✖ VS Code not found in PATH.[/bold red]")
            log.write("[dim]Install VS Code and make sure 'code' command is available.[/dim]")
            log.write("[dim]In VS Code: Cmd+Shift+P → 'Shell Command: Install code in PATH'[/dim]")
            return

        try:
            # Launch VS Code in background — doesn't block the TUI
            subprocess.Popen(["code", tf_dir])
            log.clear()
            log.write(f"[bold green]📝 Opened {tf_dir} in VS Code.[/bold green]")
            log.write("[dim]Press r to reload state after making changes.[/dim]")
        except Exception as e:
            log.clear()
            log.write(f"[bold red]✖ Failed to open VS Code: {e}[/bold red]")



    @on(Button.Pressed, "#btn-apply-now")
    def apply_now(self) -> None:
        log = self.query_one("#output-log", RichLog)
        log.clear()
        log.write("[bold green]⚡ Running terraform apply --auto-approve...[/bold green]")
        log.write("")
        self._run_apply_now(log)

    @work(thread=True)
    def _run_apply_now(self, log: RichLog) -> None:
        tf_dir = self.app._tf_dir
        which = subprocess.run(["which", "terraform"], capture_output=True, text=True)
        if which.returncode != 0:
            self.app.call_from_thread(log.write, "[bold red]✖ 'terraform' not found in PATH.[/bold red]")
            return
        try:
            proc = subprocess.Popen(
                ["terraform", "apply", "-auto-approve", "-no-color"],
                stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True, cwd=tf_dir,
            )
            for line in proc.stdout:
                stripped = line.rstrip()
                if stripped:
                    self.app.call_from_thread(log.write, stripped)
            proc.wait()
            if proc.returncode == 0:
                self.app.call_from_thread(log.write, "\n[bold green]✅ Apply complete![/bold green]")
                self.app.call_from_thread(self.app.action_reload_state)
            else:
                self.app.call_from_thread(log.write, f"\n[bold red]✖ Apply failed (exit {proc.returncode})[/bold red]")
        except Exception as e:
            self.app.call_from_thread(log.write, f"[bold red]✖ Error: {e}[/bold red]")

    # ── Destroy Selected ──────────────────────────────────────────────────
    @on(Button.Pressed, "#btn-destroy")
    def destroy_selected(self) -> None:
        log = self.query_one("#output-log", RichLog)
        tree = self.query_one("#resource-tree", ResourceTree)
        selected = tree.cursor_node
        if not selected or selected.allow_expand:
            log.clear()
            log.write("[red]✖ No leaf resource selected. Select a resource in the tree first.[/red]")
            return

        label = selected.label.plain.strip()
        parent = selected.parent
        rtype = parent.label.plain.strip() if parent else "unknown"
        rtype = " ".join(rtype.split()[1:]) if rtype else rtype
        resource_addr = f"{rtype}.{label}"

        def on_confirm(confirmed: bool) -> None:
            if confirmed:
                log.clear()
                log.write(f"[bold red]🗑️  Destroying {resource_addr}...[/bold red]")
                self._run_destroy(resource_addr, log)
            else:
                log.clear()
                log.write("[dim]Destroy cancelled.[/dim]")

        self.app.push_screen(ConfirmDestroyScreen(resource_addr), on_confirm)

    @work(thread=True)
    def _run_destroy(self, resource_addr: str, log: RichLog) -> None:
        tf_dir = self.app._tf_dir
        try:
            proc = subprocess.Popen(
                ["terraform", "destroy", f"-target={resource_addr}", "-auto-approve", "-no-color"],
                stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True, cwd=tf_dir,
            )
            for line in proc.stdout:
                stripped = line.rstrip()
                if stripped:
                    self.app.call_from_thread(log.write, stripped)
            proc.wait()
            if proc.returncode == 0:
                self.app.call_from_thread(log.write, "\n[bold green]✅ Resource destroyed successfully.[/bold green]")
                self.app.call_from_thread(self.app.action_reload_state)
            else:
                self.app.call_from_thread(log.write, f"\n[bold red]✖ Destroy failed (exit {proc.returncode})[/bold red]")
        except Exception as e:
            self.app.call_from_thread(log.write, f"[bold red]✖ Error: {e}[/bold red]")


class ConfirmDestroyScreen(ModalScreen[bool]):
    DEFAULT_CSS = """
    ConfirmDestroyScreen { align: center middle; }
    #dialog { width: 64; height: auto; border: tall $error; background: $surface; padding: 2 4; }
    #dialog-title { text-style: bold; color: $error; margin-bottom: 1; }
    .dialog-body { color: $text-muted; margin-bottom: 2; }
    #dialog-addr { text-style: bold italic; color: $accent; margin-bottom: 2; }
    #btn-row { height: auto; align: right middle; }
    #btn-cancel { margin-right: 2; }
    """

    def __init__(self, resource_addr: str) -> None:
        super().__init__()
        self._addr = resource_addr

    def compose(self) -> ComposeResult:
        with Vertical(id="dialog"):
            yield Label("⚠️  Confirm Destroy", id="dialog-title")
            yield Label("You are about to permanently destroy:", classes="dialog-body")
            yield Label(self._addr, id="dialog-addr")
            yield Label("This will run terraform destroy -target and cannot be undone.", classes="dialog-body")
            with Horizontal(id="btn-row"):
                yield Button("Cancel",  id="btn-cancel",  variant="default")
                yield Button("Destroy", id="btn-confirm", variant="error")

    @on(Button.Pressed, "#btn-confirm")
    def confirm(self) -> None:
        self.dismiss(True)

    @on(Button.Pressed, "#btn-cancel")
    def cancel(self) -> None:
        self.dismiss(False)

    def on_key(self, event) -> None:
        if event.key == "escape":
            self.dismiss(False)


# ─────────────────────────────────────────────
# Main App
# ─────────────────────────────────────────────
class InsightTF(App):
    TITLE = "TerraLens"
    SUB_TITLE = "Terraform TUI Dashboard"

    CSS = """
    Screen { background: $background; }
    TabbedContent { height: 1fr; }
    TabPane { padding: 0; }
    #tab-overview { padding: 0; }
    #tab-manage { padding: 0; }
    """

    BINDINGS = [
        Binding("1", "switch_tab('overview')", "Overview",     show=True),
        Binding("2", "switch_tab('manage')",   "Manage",       show=True),
        Binding("r", "reload_state",           "Reload State", show=True),
        Binding("q", "quit",                   "Quit",         show=True),
    ]

    def __init__(self, state_path: str = "terraform.tfstate") -> None:
        super().__init__()
        self._state_path = state_path
        self._state = load_state(state_path)
        self._tf_dir = str(Path(state_path).parent.resolve()) if Path(state_path).exists() else str(Path.cwd())

    def compose(self) -> ComposeResult:
        yield Header(show_clock=True)
        with TabbedContent(initial="overview"):
            with TabPane("📊  Overview", id="overview"):
                yield OverviewPage(self._state, id="overview-page")
            with TabPane("⚙️   Manage", id="manage"):
                yield ManagePage(self._state, id="manage-page")
        yield Footer()

    def action_switch_tab(self, tab: str) -> None:
        self.query_one(TabbedContent).active = tab

    def action_reload_state(self) -> None:
        self._state = load_state(self._state_path)
        self.call_after_refresh(self._rebuild_pages)

    def _rebuild_pages(self) -> None:
        try:
            manage = self.query_one("#manage-page", ManagePage)
            manage._state = self._state
            manage.query_one("#resource-tree", ResourceTree).clear()
            manage._resource_map = {}
            manage._populate_tree()
            manage.query_one("#attr-panel", AttributePanel).query_one("#attr-title", Label).update("Select a resource →")
            manage.query_one("#attr-panel", AttributePanel).query_one("#attr-content", Label).update("")
        except Exception:
            pass
        try:
            overview = self.query_one("#overview-page", OverviewPage)
            overview.remove()
            self.query_one("#overview", TabPane).mount(OverviewPage(self._state, id="overview-page"))
        except Exception:
            pass
        self.notify("✅ State refreshed", severity="information")


# ─────────────────────────────────────────────
# Entry point
# ─────────────────────────────────────────────
def main():
    import sys
    state_path = sys.argv[1] if len(sys.argv) > 1 else "terraform.tfstate"
    InsightTF(state_path).run()


if __name__ == "__main__":
    main()