"""
Cloud SQL Admin API emulator.

Handles SQL instances and databases for Terraform's
google_sql_database_instance and google_sql_database resources.
"""

from flask import Blueprint, jsonify, request as flask_request

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

SVC = "sqladmin"


class CloudSQLService(GCPService):
    service_name = "sqladmin"
    api_prefix = SQLADMIN_API_PREFIX

    def register_routes(self, bp: Blueprint) -> None:
        p = self.api_prefix

        # --- Instances ---
        bp.add_url_rule(
            f"{p}/projects/<project>/instances",
            "list_sql_instances", self.list_instances, methods=["GET"],
        )
        bp.add_url_rule(
            f"{p}/projects/<project>/instances",
            "create_sql_instance", self.create_instance, methods=["POST"],
        )
        bp.add_url_rule(
            f"{p}/projects/<project>/instances/<instance>",
            "get_sql_instance", self.get_instance, methods=["GET"],
        )
        bp.add_url_rule(
            f"{p}/projects/<project>/instances/<instance>",
            "delete_sql_instance", self.delete_instance, methods=["DELETE"],
        )
        bp.add_url_rule(
            f"{p}/projects/<project>/instances/<instance>",
            "patch_sql_instance", self.patch_instance, methods=["PATCH", "PUT"],
        )

        # --- Databases ---
        bp.add_url_rule(
            f"{p}/projects/<project>/instances/<instance>/databases",
            "list_sql_databases", self.list_databases, methods=["GET"],
        )
        bp.add_url_rule(
            f"{p}/projects/<project>/instances/<instance>/databases",
            "create_sql_database", self.create_database, methods=["POST"],
        )
        bp.add_url_rule(
            f"{p}/projects/<project>/instances/<instance>/databases/<database>",
            "get_sql_database", self.get_database, methods=["GET"],
        )
        bp.add_url_rule(
            f"{p}/projects/<project>/instances/<instance>/databases/<database>",
            "delete_sql_database", self.delete_database, methods=["DELETE"],
        )

        # --- Users ---
        bp.add_url_rule(
            f"{p}/projects/<project>/instances/<instance>/users",
            "list_sql_users", self.list_users, methods=["GET"],
        )
        bp.add_url_rule(
            f"{p}/projects/<project>/instances/<instance>/users",
            "create_sql_user", self.create_user, methods=["POST"],
        )
        bp.add_url_rule(
            f"{p}/projects/<project>/instances/<instance>/users",
            "delete_sql_user", self.delete_user, methods=["DELETE"],
        )

        # --- Operations ---
        bp.add_url_rule(
            f"{p}/projects/<project>/operations/<operation>",
            "get_sql_operation", self.get_operation, methods=["GET"],
        )

    # ── Instances ──────────────────────────────────────────────────────

    def list_instances(self, project: str):
        items = self.state.list(SVC, project, "instances")
        return jsonify({"kind": "sql#instancesList", "items": items})

    def create_instance(self, project: str):
        body = flask_request.get_json(silent=True) or {}
        name = body.get("name", f"sql-{gcp_id()[:8]}")

        instance = {
            "kind": "sql#instance",
            "name": name,
            "project": project,
            "state": "RUNNABLE",
            "databaseVersion": body.get("databaseVersion", "MYSQL_8_0"),
            "region": body.get("region", "us-central1"),
            "settings": body.get("settings", {
                "tier": "db-f1-micro",
                "kind": "sql#settings",
                "activationPolicy": "ALWAYS",
                "dataDiskSizeGb": "10",
                "dataDiskType": "PD_SSD",
                "pricingPlan": "PER_USE",
                "storageAutoResize": True,
                "ipConfiguration": {
                    "ipv4Enabled": True,
                    "authorizedNetworks": [],
                },
            }),
            "connectionName": f"{project}:{body.get('region', 'us-central1')}:{name}",
            "ipAddresses": [
                {"type": "PRIMARY", "ipAddress": "10.0.0.100"},
            ],
            "serverCaCert": {
                "kind": "sql#sslCert",
                "certSerialNumber": "0",
                "cert": "MOCK_CA_CERT",
                "commonName": "gcplocal",
                "sha1Fingerprint": "mock-fingerprint",
                "instance": name,
                "createTime": timestamp_now(),
                "expirationTime": "2030-01-01T00:00:00Z",
            },
            "selfLink": f"https://sqladmin.googleapis.com/sql/v1beta4/projects/{project}/instances/{name}",
            "createTime": timestamp_now(),
            "etag": "MOCK_ETAG",
        }

        self.state.put(SVC, project, "instances", name, instance)

        operation = {
            "kind": "sql#operation",
            "name": f"op-{gcp_id()[:8]}",
            "status": "DONE",
            "operationType": "CREATE",
            "targetProject": project,
            "targetId": name,
            "insertTime": timestamp_now(),
            "startTime": timestamp_now(),
            "endTime": timestamp_now(),
        }

        return jsonify(operation)

    def get_instance(self, project: str, instance: str):
        inst = self.state.get(SVC, project, "instances", instance)
        if not inst:
            return error_response(404, f"SQL instance {instance} not found")
        return jsonify(inst)

    def delete_instance(self, project: str, instance: str):
        if not self.state.delete(SVC, project, "instances", instance):
            return error_response(404, f"SQL instance {instance} not found")
        return jsonify({
            "kind": "sql#operation",
            "name": f"op-{gcp_id()[:8]}",
            "status": "DONE",
            "operationType": "DELETE",
        })

    def patch_instance(self, project: str, instance: str):
        existing = self.state.get(SVC, project, "instances", instance)
        if not existing:
            return error_response(404, f"SQL instance {instance} not found")
        body = flask_request.get_json(silent=True) or {}
        if "settings" in body:
            existing.setdefault("settings", {}).update(body["settings"])
        for k, v in body.items():
            if k != "settings":
                existing[k] = v
        self.state.put(SVC, project, "instances", instance, existing)
        return jsonify({
            "kind": "sql#operation",
            "name": f"op-{gcp_id()[:8]}",
            "status": "DONE",
            "operationType": "UPDATE",
        })

    # ── Databases ──────────────────────────────────────────────────────

    def list_databases(self, project: str, instance: str):
        dbs = self.state.list(SVC, project, f"databases/{instance}")
        return jsonify({"kind": "sql#databasesList", "items": dbs})

    def create_database(self, project: str, instance: str):
        body = flask_request.get_json(silent=True) or {}
        name = body.get("name", f"db-{gcp_id()[:8]}")
        db = {
            "kind": "sql#database",
            "name": name,
            "instance": instance,
            "project": project,
            "charset": body.get("charset", "utf8"),
            "collation": body.get("collation", "utf8_general_ci"),
            "selfLink": f"https://sqladmin.googleapis.com/sql/v1beta4/projects/{project}/instances/{instance}/databases/{name}",
            "etag": "MOCK_ETAG",
        }
        self.state.put(SVC, project, f"databases/{instance}", name, db)
        return jsonify({
            "kind": "sql#operation",
            "name": f"op-{gcp_id()[:8]}",
            "status": "DONE",
            "operationType": "CREATE_DATABASE",
        })

    def get_database(self, project: str, instance: str, database: str):
        db = self.state.get(SVC, project, f"databases/{instance}", database)
        if not db:
            return error_response(404, f"Database {database} not found")
        return jsonify(db)

    def delete_database(self, project: str, instance: str, database: str):
        if not self.state.delete(SVC, project, f"databases/{instance}", database):
            return error_response(404, f"Database {database} not found")
        return jsonify({
            "kind": "sql#operation",
            "name": f"op-{gcp_id()[:8]}",
            "status": "DONE",
            "operationType": "DELETE_DATABASE",
        })

    # ── Users ──────────────────────────────────────────────────────────

    def list_users(self, project: str, instance: str):
        users = self.state.list(SVC, project, f"users/{instance}")
        return jsonify({"kind": "sql#usersList", "items": users})

    def create_user(self, project: str, instance: str):
        body = flask_request.get_json(silent=True) or {}
        name = body.get("name", "root")
        user = {
            "kind": "sql#user",
            "name": name,
            "instance": instance,
            "project": project,
            "host": body.get("host", "%"),
            "type": body.get("type", "BUILT_IN"),
        }
        self.state.put(SVC, project, f"users/{instance}", name, user)
        return jsonify({
            "kind": "sql#operation",
            "name": f"op-{gcp_id()[:8]}",
            "status": "DONE",
            "operationType": "CREATE_USER",
        })

    def delete_user(self, project: str, instance: str):
        name = flask_request.args.get("name", "root")
        host = flask_request.args.get("host", "%")
        self.state.delete(SVC, project, f"users/{instance}", name)
        return jsonify({
            "kind": "sql#operation",
            "name": f"op-{gcp_id()[:8]}",
            "status": "DONE",
            "operationType": "DELETE_USER",
        })

    # ── Operations ─────────────────────────────────────────────────────

    def get_operation(self, project: str, operation: str):
        return jsonify({
            "kind": "sql#operation",
            "name": operation,
            "status": "DONE",
        })
