"""
Policy generator that creates Polar code from registered rules
"""

import os

from .registry import get_registry


class PolicyBuilder:
    """Main policy builder that generates Polar code"""

    def __init__(self):
        self.registry = get_registry()

    def enable_groups(self):
        """Enable group-based access control

        Adds the group inheritance rule that allows users to inherit
        roles from groups they belong to.
        """
        self.registry.add_group_inheritance_rule()
        return self

    def enable_nested_groups(self):
        """Enable nested group inheritance

        Allows groups to be members of other groups, creating hierarchies.
        """
        self.registry.add_nested_groups_rule()
        return self

    def generate(self) -> str:
        """Generate the complete Polar policy"""
        lines = []

        # Add header comment
        lines.append("# Generated by Oso Policy Builder")
        lines.append("")

        # Add actor declarations
        if self.registry.actors:
            lines.append("# Actor declarations")
            if "User" in self.registry.actors.keys():
                lines.append("actor User {}")
            for actor_name in sorted(self.registry.actors.keys()):
                if actor_name != "User":
                    lines.append(f"actor {actor_name} {{}}")
            lines.append("")

        if self.registry.global_info["roles"] or self.registry.global_info["permissions"]:
            lines.append("global {")

            if self.registry.global_info["roles"]:
                roles_str = ", ".join(f'"{r}"' for r in self.registry.global_info["roles"])
                lines.append(f"  roles = [{roles_str}];")

            if self.registry.global_info["permissions"]:
                perms_str = ", ".join(f'"{p}"' for p in self.registry.global_info["permissions"])
                lines.append(f"  permissions = [{perms_str}];")

            # Add global rules
            global_rules = [r for r in self.registry.rules if r.rule_type == "global"]
            if global_rules:
                if self.registry.global_info["roles"] or self.registry.global_info["permissions"]:
                    lines.append("")
                for rule in global_rules:
                    lines.append(f"  {rule}")

            lines.append("}")

        custom_rules = [r for r in self.registry.rules if r.rule_type == "custom_rule"]
        if custom_rules:
            for rule in custom_rules:
                lines.append(str(rule))
            lines.append("")

        # Add global custom rules (rules not tied to specific resources)
        global_rules = [
            r for r in self.registry.rules if r.rule_type == "custom" and r.resource_type == ""
        ]
        if global_rules:
            lines.append("# Global rules")
            for rule in global_rules:
                lines.append(str(rule))
            lines.append("")

        # Add resource declarations with embedded shorthand rules only
        if self.registry.resources:
            for resource_name in sorted(self.registry.resources.keys()):
                resource_info = self.registry.resources[resource_name]
                permissions = resource_info["permissions"]
                roles = resource_info["roles"]
                relations = resource_info["relations"]

                lines.append(f"resource {resource_name} {{")

                if permissions:
                    perms_str = ", ".join(f'"{p}"' for p in permissions)
                    lines.append(f"  permissions = [{perms_str}];")

                if roles:
                    roles_str = ", ".join(f'"{r}"' for r in roles)
                    lines.append(f"  roles = [{roles_str}];")

                if relations:
                    lines.append("  relations = {")
                    for rel_name, rel_type in relations.items():
                        type_name = getattr(rel_type, "__name__", str(rel_type))
                        lines.append(f"    {rel_name}: {type_name},")
                    lines.append("  };")

                # Add shorthand rules for this resource (only inside resource block)
                shorthand_rules = [
                    r
                    for r in self.registry.rules
                    if r.rule_type == "shorthand" and r.resource_type == resource_name
                ]
                relation_shorthand_rules = [
                    r
                    for r in self.registry.rules
                    if r.rule_type == "relation" and r.resource_type == resource_name
                ]
                all_shorthand_rules = shorthand_rules + relation_shorthand_rules
                if all_shorthand_rules:
                    if permissions or roles or relations:
                        lines.append("")
                    for rule in all_shorthand_rules:
                        lines.append(f"  {rule}")

                lines.append("}")

                # Add complex rules for this resource (outside resource block, grouped under it)
                resource_rules = [
                    r
                    for r in self.registry.rules
                    if r.rule_type == "resource_rule" and r.resource_type == resource_name
                ]
                unconditional_rules = [
                    r
                    for r in self.registry.rules
                    if r.rule_type == "custom" and r.resource_type == resource_name
                ]

                all_resource_rules = resource_rules + unconditional_rules
                if all_resource_rules:
                    lines.append("")
                    for rule in all_resource_rules:
                        lines.append(str(rule))

                lines.append("")  # Empty line after each resource section

        # Add facts
        if self.registry.facts:
            lines.append("# Facts")
            for fact in self.registry.facts:
                lines.append(f"{fact};")
            lines.append("")

        return "\n".join(lines).rstrip() + "\n"

    def save(self, filename: str = "authorization.polar", directory: str = ".") -> str:
        """Save the generated policy to a file"""
        policy_text = self.generate()

        # Ensure directory exists
        os.makedirs(directory, exist_ok=True)

        # Write to file
        filepath = os.path.join(directory, filename)
        with open(filepath, "w") as f:
            f.write(policy_text)

        print(f"Oso policy saved to: {filepath}")
        return filepath

    def clear(self):
        """Clear all registered rules"""
        self.registry.clear()

    def stats(self) -> dict:
        """Get statistics about the current policy"""
        return {
            "actors": len(self.registry.actors),
            "resources": len(self.registry.resources),
            "rules": len(self.registry.rules),
            "facts": len(self.registry.facts),
        }
