import os
import secrets
import json
import uuid
import logging
from typing import Optional, List
from fastapi import HTTPException
from sqlalchemy.orm import Session
import jinja2

from app.db import models
from app.api import schemas

logger = logging.getLogger(__name__)

class MeshService:
    def __init__(self, services=None):
        self.services = services
        # Setup Jinja2 templates
        self.templates_dir = os.path.join(os.path.dirname(__file__), "..", "templates", "provisioning")
        self.jinja_env = jinja2.Environment(loader=jinja2.FileSystemLoader(self.templates_dir)) if os.path.exists(self.templates_dir) else None

    # Extracted from nodes.py
    def require_node_access(self, user_id: str, node_id: str, db: Session):
        user = db.query(models.User).filter(models.User.id == user_id).first()
        if not user:
            raise HTTPException(status_code=404, detail="User not found.")
        
        if user.role == "admin":
            return user
            
        access = db.query(models.NodeGroupAccess).filter(
            models.NodeGroupAccess.node_id == node_id,
            models.NodeGroupAccess.group_id == user.group_id
        ).first()
        if access:
            return user
            
        if user.group and user.group.policy:
            policy_nodes = user.group.policy.get("nodes", [])
            if isinstance(policy_nodes, list) and node_id in policy_nodes:
                return user
                
        raise HTTPException(status_code=403, detail=f"Access Denied: You do not have permission to access node '{node_id}'.")

    def node_to_user_view(self, node: models.AgentNode, registry) -> schemas.AgentNodeUserView:
        live = registry.get_node(node.node_id)
        status = live._compute_status() if live else "offline"
        
        skill_cfg = node.skill_config or {}
        if isinstance(skill_cfg, str):
            try: skill_cfg = json.loads(skill_cfg)
            except: skill_cfg = {}
        available = [skill for skill, cfg in skill_cfg.items() if isinstance(cfg, dict) and cfg.get("enabled", True)]
        stats = live.stats if live else {}
        
        return schemas.AgentNodeUserView(
            node_id=node.node_id,
            display_name=node.display_name,
            description=node.description,
            capabilities=node.capabilities or {},
            available_skills=available,
            last_status=status,
            last_seen_at=node.last_seen_at,
            stats=schemas.AgentNodeStats(**stats) if stats else schemas.AgentNodeStats()
        )

    def generate_provisioning_script(self, node: models.AgentNode, config_yaml: str, base_url: str) -> str:
        if not self.jinja_env:
            return "Error: Templates directory not found."
        try:
            template = self.jinja_env.get_template("provision.py.j2")
            return template.render(
                node_id=node.node_id,
                config_yaml=config_yaml,
                base_url=base_url,
                invite_token=node.invite_token
            )
        except Exception as e:
            logger.error(f"Failed to generate provisioning script: {e}")
            return f"Error: {e}"

    def generate_provisioning_sh(self, node: models.AgentNode, config_yaml: str, base_url: str) -> str:
        if not self.jinja_env:
            return "Error: Templates directory not found."
        try:
            template = self.jinja_env.get_template("provision.sh.j2")
            return template.render(
                node_id=node.node_id,
                config_yaml=config_yaml,
                base_url=base_url,
                invite_token=node.invite_token
            )
        except Exception as e:
            logger.error(f"Failed to generate provisioning script: {e}")
            return f"Error: {e}"

    def get_template_content(self, filename: str) -> str:
        if not self.jinja_env:
            return ""
        try:
            return self.jinja_env.get_template(filename).render()
        except:
            return ""
