"""
Cloud Resource Manager API emulator.

Handles project CRUD used by Terraform's google_project resources and
data sources. Terraform's provider needs projects to exist for nearly
every resource it manages.
"""

from flask import Blueprint, jsonify, request

from gcplocal.services.base import GCPService
from gcplocal.constants import CRM_API_PREFIX
from gcplocal.utils import error_response, gcp_id, timestamp_now


class ResourceManagerService(GCPService):
    service_name = "cloudresourcemanager"
    api_prefix = CRM_API_PREFIX

    def register_routes(self, bp: Blueprint) -> None:
        bp.add_url_rule(
            f"{self.api_prefix}/projects/<project_id>",
            "get_project",
            self.get_project,
            methods=["GET"],
        )
        bp.add_url_rule(
            f"{self.api_prefix}/projects",
            "create_project",
            self.create_project,
            methods=["POST"],
        )
        bp.add_url_rule(
            f"{self.api_prefix}/projects/<project_id>",
            "update_project",
            self.update_project,
            methods=["PUT"],
        )
        bp.add_url_rule(
            f"{self.api_prefix}/projects/<project_id>",
            "delete_project",
            self.delete_project,
            methods=["DELETE"],
        )
        bp.add_url_rule(
            f"{self.api_prefix}/projects/<project_id>:getIamPolicy",
            "get_project_iam_policy",
            self.get_iam_policy,
            methods=["POST"],
        )
        bp.add_url_rule(
            f"{self.api_prefix}/projects/<project_id>:setIamPolicy",
            "set_project_iam_policy",
            self.set_iam_policy,
            methods=["POST"],
        )

    def _ensure_project(self, project_id: str) -> None:
        """Auto-create a project stub if it doesn't exist yet."""
        if not self.state.exists("crm", project_id, "projects", project_id):
            self.state.put("crm", project_id, "projects", project_id, {
                "projectId": project_id,
                "projectNumber": gcp_id(),
                "name": project_id,
                "lifecycleState": "ACTIVE",
                "createTime": timestamp_now(),
            })

    def get_project(self, project_id: str):
        self._ensure_project(project_id)
        project = self.state.get("crm", project_id, "projects", project_id)
        return jsonify(project)

    def create_project(self):
        body = request.get_json(silent=True) or {}
        project_id = body.get("projectId", f"project-{gcp_id()[:8]}")
        project = {
            "projectId": project_id,
            "projectNumber": gcp_id(),
            "name": body.get("name", project_id),
            "lifecycleState": "ACTIVE",
            "createTime": timestamp_now(),
            "labels": body.get("labels", {}),
            "parent": body.get("parent", {}),
        }
        self.state.put("crm", project_id, "projects", project_id, project)
        return jsonify(project), 200

    def update_project(self, project_id: str):
        existing = self.state.get("crm", project_id, "projects", project_id)
        if not existing:
            return error_response(404, f"Project {project_id} not found")
        body = request.get_json(silent=True) or {}
        existing.update({k: v for k, v in body.items() if v is not None})
        self.state.put("crm", project_id, "projects", project_id, existing)
        return jsonify(existing)

    def delete_project(self, project_id: str):
        if not self.state.delete("crm", project_id, "projects", project_id):
            return error_response(404, f"Project {project_id} not found")
        return "", 204

    def get_iam_policy(self, project_id: str):
        self._ensure_project(project_id)
        policy = self.state.get("crm", project_id, "iam_policy", project_id)
        if not policy:
            policy = {"version": 1, "etag": "ACAB", "bindings": []}
            self.state.put("crm", project_id, "iam_policy", project_id, policy)
        return jsonify(policy)

    def set_iam_policy(self, project_id: str):
        self._ensure_project(project_id)
        body = request.get_json(silent=True) or {}
        policy = body.get("policy", {"version": 1, "etag": "ACAB", "bindings": []})
        self.state.put("crm", project_id, "iam_policy", project_id, policy)
        return jsonify(policy)
