package main

import (
	"context"
	"fmt"
	"time"

	"github.com/spf13/cobra"

	"git.wntrmute.dev/kyle/mc-proxy/client/mcproxy"
)

func firewallCmd() *cobra.Command {
	cmd := &cobra.Command{
		Use:   "firewall",
		Short: "Manage firewall rules",
		Long:  "Manage firewall rules for mc-proxy.",
	}

	cmd.AddCommand(firewallListCmd())
	cmd.AddCommand(firewallAddCmd())
	cmd.AddCommand(firewallRemoveCmd())

	return cmd
}

func firewallListCmd() *cobra.Command {
	return &cobra.Command{
		Use:   "list",
		Short: "List all firewall rules",
		Long:  "List all configured firewall rules.",
		RunE: func(cmd *cobra.Command, args []string) error {
			client := clientFromContext(cmd.Context())

			ctx, cancel := context.WithTimeout(cmd.Context(), 5*time.Second)
			defer cancel()

			rules, err := client.GetFirewallRules(ctx)
			if err != nil {
				return fmt.Errorf("listing firewall rules: %w", err)
			}

			if len(rules) == 0 {
				fmt.Println("No firewall rules configured")
				return nil
			}

			// Find max type length for alignment
			maxTypeLen := 0
			for _, r := range rules {
				if len(r.Type) > maxTypeLen {
					maxTypeLen = len(string(r.Type))
				}
			}

			fmt.Println("Firewall rules:")
			for _, r := range rules {
				fmt.Printf("  %-*s  %s\n", maxTypeLen, r.Type, r.Value)
			}

			return nil
		},
	}
}

func firewallAddCmd() *cobra.Command {
	return &cobra.Command{
		Use:   "add TYPE VALUE",
		Short: "Add a firewall rule",
		Long:  "Add a firewall rule. TYPE must be one of: ip, cidr, country.",
		Args:  cobra.ExactArgs(2),
		RunE: func(cmd *cobra.Command, args []string) error {
			ruleType, err := parseRuleType(args[0])
			if err != nil {
				return err
			}
			value := args[1]
			client := clientFromContext(cmd.Context())

			ctx, cancel := context.WithTimeout(cmd.Context(), 5*time.Second)
			defer cancel()

			if err := client.AddFirewallRule(ctx, ruleType, value); err != nil {
				return fmt.Errorf("adding firewall rule: %w", err)
			}

			fmt.Printf("Added firewall rule: %s %s\n", ruleType, value)
			return nil
		},
	}
}

func firewallRemoveCmd() *cobra.Command {
	return &cobra.Command{
		Use:   "remove TYPE VALUE",
		Short: "Remove a firewall rule",
		Long:  "Remove a firewall rule. TYPE must be one of: ip, cidr, country.",
		Args:  cobra.ExactArgs(2),
		RunE: func(cmd *cobra.Command, args []string) error {
			ruleType, err := parseRuleType(args[0])
			if err != nil {
				return err
			}
			value := args[1]
			client := clientFromContext(cmd.Context())

			ctx, cancel := context.WithTimeout(cmd.Context(), 5*time.Second)
			defer cancel()

			if err := client.RemoveFirewallRule(ctx, ruleType, value); err != nil {
				return fmt.Errorf("removing firewall rule: %w", err)
			}

			fmt.Printf("Removed firewall rule: %s %s\n", ruleType, value)
			return nil
		},
	}
}

func parseRuleType(s string) (mcproxy.FirewallRuleType, error) {
	switch s {
	case "ip":
		return mcproxy.FirewallRuleIP, nil
	case "cidr":
		return mcproxy.FirewallRuleCIDR, nil
	case "country":
		return mcproxy.FirewallRuleCountry, nil
	default:
		return "", fmt.Errorf("invalid rule type %q: must be one of: ip, cidr, country", s)
	}
}
