#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
DHCP服务器Skill - 控制DHCP服务端启动/停止/查看租约
注意: 与 dhcp_skill.py(DHCP检测/客户端探测) 不同,本Skill是服务端模式
"""

import sys
import os
import re
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.dirname(__file__))))

from skills.base_skill import BaseSkill


class DhcpServerSkill(BaseSkill):
    """DHCP服务器控制Skill(服务端模式)"""

    def get_metadata(self):
        return {
            "name": "dhcp_server",
            "display_name": "DHCP服务器",
            "description": "启动/停止DHCP服务器,为局域网设备自动分配IP地址,或查看当前租约",
            "category": "advanced",
            "keywords": [
                "dhcp服务器", "dhcp server", "启动dhcp服务", "停止dhcp服务",
                "分配ip", "ip分配", "dhcp租约", "查看租约", "dhcp服务端",
                "局域网dhcp", "自动分配ip", "设置dhcp"
            ],
            "parameters": [
                {
                    "name": "action",
                    "type": "string",
                    "required": False,
                    "default": "start",
                    "description": "操作: start(启动)/stop(停止)/status(查看租约)"
                },
                {
                    "name": "interface",
                    "type": "string",
                    "required": False,
                    "default": "",
                    "description": "网卡名称或关键词,如'以太网9'、'eth0'"
                },
                {
                    "name": "subnet",
                    "type": "string",
                    "required": False,
                    "default": "",
                    "description": "网段CIDR,如192.168.2.0/24,自动推算IP池和网关"
                },
                {
                    "name": "ip_start",
                    "type": "string",
                    "required": False,
                    "default": "",
                    "description": "IP池起始地址,如192.168.1.100"
                },
                {
                    "name": "ip_end",
                    "type": "string",
                    "required": False,
                    "default": "",
                    "description": "IP池结束地址,如192.168.1.200"
                }
            ],
            "examples": [
                "启动DHCP服务器",
                "停止DHCP服务器",
                "设置DHCP服务器 网卡以太网9 网段192.168.2.0/24",
                "开启DHCP服务 IP段192.168.1.100-200",
                "查看DHCP租约",
            ],
            "requires_admin": True,
            "requires_ui": True
        }

    # ── 工具函数 ────────────────────────────────────────────────────────────

    def _parse_subnet(self, subnet: str):
        """解析CIDR网段,返回 (base, start, end, gateway)
        例如 '192.168.2.0/24' → ('192.168.2', '192.168.2.100', '192.168.2.200', '192.168.2.1')
        """
        try:
            m = re.match(r'(\d+\.\d+\.\d+)\.\d+(?:/\d+)?', subnet.strip())
            if m:
                base = m.group(1)
                return base, f"{base}.100", f"{base}.200", f"{base}.1"
        except Exception:
            pass
        return None, "", "", ""

    def _find_iface_display(self, interface_hint: str):
        """在 toolkit.dhcp_iface_map 中模糊匹配网卡显示名称"""
        if not self.toolkit or not interface_hint:
            return None
        iface_map = getattr(self.toolkit, 'dhcp_iface_map', {})
        hint = interface_hint.strip().lower().replace(' ', '')

        # 精确匹配
        for display in iface_map:
            if hint in display.lower().replace(' ', ''):
                return display

        # 尝试用真实名称匹配(截断后的display可能不含完整名)
        iface_ip_map = getattr(self.toolkit, 'dhcp_iface_ip_map', {})
        try:
            import psutil
            net_if_addrs = psutil.net_if_addrs()
            for real_name, addrs in net_if_addrs.items():
                if hint in real_name.lower().replace(' ', ''):
                    # 找到了真实网卡名,在display map中查找对应IP
                    for addr in addrs:
                        if hasattr(addr, 'family') and addr.family == 2:
                            target_ip = addr.address
                            for display, ip in iface_ip_map.items():
                                if ip == target_ip:
                                    return display
        except Exception:
            pass
        return None

    def _extract_params_from_query(self, raw_query: str):
        """从原始用户输入中提取网卡名、网段等额外信息"""
        params = {}

        # 提取网段 CIDR: 192.168.x.x/xx
        m = re.search(r'(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/\d{1,2})', raw_query)
        if m:
            params['subnet'] = m.group(1)

        # 提取IP范围: 192.168.x.a-b 或 192.168.x.a到b
        m2 = re.search(r'(\d{1,3}\.\d{1,3}\.\d{1,3})\.(\d{1,3})[^\d]+(\d{1,3})', raw_query)
        if m2 and 'subnet' not in params:
            base = m2.group(1)
            params['ip_start'] = f"{base}.{m2.group(2)}"
            params['ip_end']   = f"{base}.{m2.group(3)}"

        # 提取网卡关键词: "网卡是XXX" / "网卡XXX" / "使用XXX"
        m3 = re.search(r'网卡[是为]?\s*([^\s,，。]+)', raw_query)
        if m3:
            params['interface'] = m3.group(1)

        return params

    # ── 主执行函数 ──────────────────────────────────────────────────────────

    def execute(self, action: str = "start", interface: str = "",
                subnet: str = "", ip_start: str = "", ip_end: str = "",
                **kwargs) -> str:

        # 尝试从 skill_manager 传入的原始 query 补充参数
        raw_query = kwargs.get('_raw_query', '') or kwargs.get('query', '')
        if raw_query:
            extra = self._extract_params_from_query(raw_query)
            if not interface and 'interface' in extra:
                interface = extra['interface']
            if not subnet and 'subnet' in extra:
                subnet = extra['subnet']
            if not ip_start and 'ip_start' in extra:
                ip_start = extra['ip_start']
            if not ip_end and 'ip_end' in extra:
                ip_end = extra['ip_end']

        action = (action or "start").strip().lower()
        stop_keywords  = ("stop", "停止", "关闭", "停", "close", "off")
        stat_keywords  = ("status", "状态", "租约", "查看", "list", "show")
        is_stop   = any(k in action for k in stop_keywords)
        is_status = any(k in action for k in stat_keywords)

        # 如果有网段CIDR,推算IP池和网关
        if subnet and not ip_start:
            _, ip_start, ip_end, auto_gw = self._parse_subnet(subnet)

        if self.toolkit:
            try:
                # ── 查看租约 ──────────────────────────────────
                if is_status:
                    self._switch_to_server_panel("dhcp")
                    leases  = getattr(self.toolkit, '_dhcp_leases', {})
                    running = getattr(self.toolkit, '_dhcp_server_running', False)
                    if not leases:
                        status = "运行中" if running else "未启动"
                        return f"📋 DHCP服务器状态: {status}\n当前无租约记录"
                    import time
                    lines = [f"📋 DHCP租约列表 (共{len(leases)}条):"]
                    for mac, info in leases.items():
                        remain = max(0, int(info['expire'] - time.time()))
                        lines.append(
                            f"  • {mac} → {info['ip']}"
                            f"  主机:{info.get('hostname','N/A')}"
                            f"  剩余:{remain}秒"
                        )
                    return "\n".join(lines)

                # ── 停止 ─────────────────────────────────────
                if is_stop:
                    if hasattr(self.toolkit, 'stop_dhcp_server'):
                        self._switch_to_server_panel("dhcp")
                        self.toolkit.stop_dhcp_server()
                        return "✅ DHCP服务器已停止"
                    return "❌ 未找到stop_dhcp_server方法"

                # ── 启动 ─────────────────────────────────────
                if hasattr(self.toolkit, 'start_dhcp_server'):
                    self._switch_to_server_panel("dhcp")

                    # 1. 设置网卡
                    if interface:
                        display = self._find_iface_display(interface)
                        if display:
                            self.toolkit.dhcp_iface_var.set(display)
                            # 触发自动推荐配置(填写同网段的IP池/网关)
                            self.toolkit._on_dhcp_iface_selected()
                        else:
                            return (
                                f"❌ 未找到网卡: '{interface}'\n\n"
                                f"可用网卡:\n" +
                                "\n".join(f"  • {d}" for d in
                                          getattr(self.toolkit, 'dhcp_iface_map', {}).keys())
                            )

                    # 2. 若指定了网段/IP范围,覆盖自动填写的值
                    if ip_start and hasattr(self.toolkit, 'dhcp_ip_start_var'):
                        self.toolkit.dhcp_ip_start_var.set(ip_start)
                    if ip_end and hasattr(self.toolkit, 'dhcp_ip_end_var'):
                        self.toolkit.dhcp_ip_end_var.set(ip_end)

                    # 3. 网段CIDR指定时自动填网关
                    if subnet:
                        _, _, _, auto_gw = self._parse_subnet(subnet)
                        if auto_gw and hasattr(self.toolkit, 'dhcp_gw_var'):
                            self.toolkit.dhcp_gw_var.set(auto_gw)

                    # 4. 启动
                    self.toolkit.start_dhcp_server()

                    cfg  = getattr(self.toolkit, '_dhcp_config', {})
                    pool = cfg.get('pool', [])
                    return (
                        f"✅ DHCP服务器已启动\n"
                        f"• 服务网卡: {self.toolkit.dhcp_iface_var.get()}\n"
                        f"• 服务IP:   {cfg.get('server_ip','?')}\n"
                        f"• IP池:     {cfg.get('pool', ['?'])[0] if pool else '?'}"
                        f" ~ {cfg.get('pool', ['?'])[-1] if pool else '?'}"
                        f"  ({len(pool)}个地址)\n"
                        f"• 网关:     {cfg.get('gateway','?')}\n"
                        f"• DNS:      {cfg.get('dns','?')}\n"
                        f"• 租约:     {cfg.get('lease_time',3600)}秒\n\n"
                        f"客户端设置为DHCP自动获取即可"
                    )
            except Exception as e:
                return f"❌ 操作失败: {e}"

        action_cn = "停止" if is_stop else ("查看租约" if is_status else "启动")
        return (
            f"🌐 DHCP服务器 — {action_cn}\n\n"
            f"请切换到 [🖥️ 服务器] → [🌐 DHCP服务器] 手动操作。\n"
            f"• 网卡: {interface or '请选择'}\n"
            f"• 网段: {subnet or f'{ip_start}~{ip_end}' or '请配置'}\n"
            f"• 需要管理员权限 + scapy/Npcap"
        )

    def _switch_to_server_panel(self, panel_type: str):
        try:
            if hasattr(self.toolkit, 'switch_server_panel'):
                self.toolkit.root.after(0, lambda: self.toolkit.switch_server_panel(panel_type))
        except Exception:
            pass

    def match_query(self, query: str) -> float:
        q = query.lower()
        if "dhcp服务器" in q or "dhcp server" in q:
            return 0.97
        if "启动dhcp" in q or "停止dhcp" in q or "dhcp服务" in q or "设置dhcp" in q:
            return 0.93
        if "dhcp租约" in q or "查看租约" in q or "自动分配ip" in q:
            return 0.9
        return super().match_query(query)
