{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "import json\n",
    "with open(\"ignore/data.json\", encoding=\"utf-8\") as f:\n",
    "    data = json.load(f)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "dict_keys(['accountEnabled', 'addIns', 'alternativeNames', 'appDescription', 'appDisplayName', 'appId', 'appOwnerOrganizationId', 'appRoleAssignmentRequired', 'appRoles', 'applicationTemplateId', 'createdDateTime', 'deletedDateTime', 'description', 'disabledByMicrosoftStatus', 'displayName', 'homepage', 'id', 'info', 'keyCredentials', 'loginUrl', 'logoutUrl', 'notes', 'notificationEmailAddresses', 'oauth2PermissionScopes', 'passwordCredentials', 'preferredSingleSignOnMode', 'preferredTokenSigningKeyThumbprint', 'replyUrls', 'resourceSpecificApplicationPermissions', 'samlSingleSignOnSettings', 'servicePrincipalNames', 'servicePrincipalType', 'signInAudience', 'tags', 'tokenEncryptionKeyId', 'verifiedPublisher'])"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "data[0].keys()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "camel_case_string\n"
     ]
    }
   ],
   "source": [
    "import re\n",
    "\n",
    "def camel_to_snake(camel_str):\n",
    "    # Add an underscore before each uppercase letter, then convert the whole string to lowercase\n",
    "    snake_str = re.sub(r'(?<!^)(?=[A-Z])', '_', camel_str).lower()\n",
    "    return snake_str\n",
    "\n",
    "# Test the function\n",
    "test_string = \"camelCaseString\"\n",
    "print(camel_to_snake(test_string))  # Outputs: camel_case_string"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(str, int, NoneType, float)"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "type(\"\"), type(1),type(None),type(0.1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "2023-05-23 12:34:56: True\n",
      "2023-05-23T12:34:56: True\n",
      "2023-05-23: True\n",
      "2023-05-23T12:34:56.789Z: True\n",
      "2021-05-31T19:13:02.252938+00:00: True\n",
      "invalid datetime: False\n"
     ]
    }
   ],
   "source": [
    "from datetime import datetime\n",
    "\n",
    "def is_datetime(string):\n",
    "    formats = [\n",
    "        \"%Y-%m-%d %H:%M:%S\",\n",
    "        \"%Y-%m-%dT%H:%M:%S\",\n",
    "        \"%Y-%m-%d\",\n",
    "        \"%Y-%m-%dT%H:%M:%S.%fZ\",\n",
    "        \"%Y-%m-%dT%H:%M:%S.%f%z\",\n",
    "        \"%Y-%m-%dT%H:%M:%S%z\"\n",
    "    ]\n",
    "    \n",
    "    for fmt in formats:\n",
    "        try:\n",
    "            datetime.strptime(string, fmt)\n",
    "            return True\n",
    "        except ValueError:\n",
    "            continue\n",
    "    return False\n",
    "\n",
    "# Example usage\n",
    "test_strings = [\n",
    "    \"2023-05-23 12:34:56\",\n",
    "    \"2023-05-23T12:34:56\",\n",
    "    \"2023-05-23\",\n",
    "    \"2023-05-23T12:34:56.789Z\",\n",
    "    \"2021-05-31T19:13:02.252938+00:00\",\n",
    "    \"invalid datetime\"\n",
    "]\n",
    "\n",
    "for test_string in test_strings:\n",
    "    print(f\"{test_string}: {is_datetime(test_string)}\")\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "123e4567-e89b-12d3-a456-426614174000: True\n",
      "123e4567-e89b-12d3-a456-42661417400Z: False\n",
      "invalid-uuid-string: False\n"
     ]
    }
   ],
   "source": [
    "import uuid\n",
    "\n",
    "def is_uuid(string):\n",
    "    try:\n",
    "        val = uuid.UUID(string, version=4)\n",
    "        return True\n",
    "    except ValueError:\n",
    "        return False\n",
    "\n",
    "# Example usage\n",
    "test_strings = [\n",
    "    \"123e4567-e89b-12d3-a456-426614174000\",\n",
    "    \"123e4567-e89b-12d3-a456-42661417400Z\",\n",
    "    \"invalid-uuid-string\"\n",
    "]\n",
    "\n",
    "for test_string in test_strings:\n",
    "    print(f\"{test_string}: {is_uuid(test_string)}\")\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "#[serde(rename = \"accountEnabled\")]\n",
      "pub account_enabled: bool,\n",
      "#[serde(rename = \"addIns\")]\n",
      "pub add_ins: None,\n",
      "#[serde(rename = \"alternativeNames\")]\n",
      "pub alternative_names: None,\n",
      "#[serde(rename = \"appDescription\")]\n",
      "pub app_description: Option<String>,\n",
      "#[serde(rename = \"appDisplayName\")]\n",
      "pub app_display_name: Option<String>,\n",
      "#[serde(rename = \"appId\")]\n",
      "pub app_id: Uuid,\n",
      "#[serde(rename = \"appOwnerOrganizationId\")]\n",
      "pub app_owner_organization_id: Option<Uuid>,\n",
      "#[serde(rename = \"appRoleAssignmentRequired\")]\n",
      "pub app_role_assignment_required: bool,\n",
      "#[serde(rename = \"appRoles\")]\n",
      "pub app_roles: None,\n",
      "#[serde(rename = \"applicationTemplateId\")]\n",
      "pub application_template_id: Option<Uuid>,\n",
      "#[serde(rename = \"createdDateTime\")]\n",
      "pub created_date_time: DateTime<Utc>,\n",
      "#[serde(rename = \"deletedDateTime\")]\n",
      "pub deleted_date_time: Option<Value>,\n",
      "pub description: Option<String>,\n",
      "#[serde(rename = \"disabledByMicrosoftStatus\")]\n",
      "pub disabled_by_microsoft_status: Option<Value>,\n",
      "#[serde(rename = \"displayName\")]\n",
      "pub display_name: String,\n",
      "pub homepage: Option<String>,\n",
      "pub id: Uuid,\n",
      "pub info: Option<Value>,\n",
      "#[serde(rename = \"keyCredentials\")]\n",
      "pub key_credentials: None,\n",
      "#[serde(rename = \"loginUrl\")]\n",
      "pub login_url: Option<Value>,\n",
      "#[serde(rename = \"logoutUrl\")]\n",
      "pub logout_url: Option<String>,\n",
      "pub notes: Option<String>,\n",
      "#[serde(rename = \"notificationEmailAddresses\")]\n",
      "pub notification_email_addresses: None,\n",
      "#[serde(rename = \"oauth2PermissionScopes\")]\n",
      "pub oauth2_permission_scopes: None,\n",
      "#[serde(rename = \"passwordCredentials\")]\n",
      "pub password_credentials: None,\n",
      "#[serde(rename = \"preferredSingleSignOnMode\")]\n",
      "pub preferred_single_sign_on_mode: Option<String>,\n",
      "#[serde(rename = \"preferredTokenSigningKeyThumbprint\")]\n",
      "pub preferred_token_signing_key_thumbprint: Option<String>,\n",
      "#[serde(rename = \"replyUrls\")]\n",
      "pub reply_urls: None,\n",
      "#[serde(rename = \"resourceSpecificApplicationPermissions\")]\n",
      "pub resource_specific_application_permissions: None,\n",
      "#[serde(rename = \"samlSingleSignOnSettings\")]\n",
      "pub saml_single_sign_on_settings: Option<Value>,\n",
      "#[serde(rename = \"servicePrincipalNames\")]\n",
      "pub service_principal_names: None,\n",
      "#[serde(rename = \"servicePrincipalType\")]\n",
      "pub service_principal_type: String,\n",
      "#[serde(rename = \"signInAudience\")]\n",
      "pub sign_in_audience: Option<String>,\n",
      "pub tags: None,\n",
      "#[serde(rename = \"tokenEncryptionKeyId\")]\n",
      "pub token_encryption_key_id: Option<Value>,\n",
      "#[serde(rename = \"verifiedPublisher\")]\n",
      "pub verified_publisher: None,\n"
     ]
    }
   ],
   "source": [
    "# #[derive(Debug, Serialize, Deserialize, PartialEq)]\n",
    "# pub struct RoleAssignment {\n",
    "#     id: RoleAssignmentId,\n",
    "#     condition: Option<Value>,\n",
    "#     #[serde(rename = \"conditionVersion\")]\n",
    "#     condition_version: Option<Value>,\n",
    "#     #[serde(rename = \"createdBy\")]\n",
    "#     created_by: String,\n",
    "#     #[serde(rename = \"createdOn\")]\n",
    "#     created_on: DateTime<Utc>,\n",
    "#     #[serde(rename = \"delega\")]\n",
    "# }\n",
    "\n",
    "\n",
    "for key in data[0].keys():\n",
    "    data_type = None\n",
    "    if all(x[key] is None for x in data):\n",
    "        data_type = \"Option<Value>\"\n",
    "    else:\n",
    "        # first pass\n",
    "        lookup = {\n",
    "            \"String\": lambda x: type(x) is str,\n",
    "            \"i32\": lambda x: type(x) is int,\n",
    "            \"f32\": lambda x: type(x) is float,\n",
    "            \"bool\": lambda x: type(x) is bool,\n",
    "        }\n",
    "        for k,v in lookup.items():\n",
    "            if all(x[key] is None or v(x[key]) for x in data):\n",
    "                if data_type is not None:\n",
    "                    raise Exception(f\"Complex type not supported for key {key}: was {data_type}, now {k}\")\n",
    "                data_type = k\n",
    "\n",
    "        # second pass\n",
    "\n",
    "        if data_type == \"String\":\n",
    "            lookup = {\n",
    "                \"Uuid\": is_uuid,\n",
    "                \"DateTime<Utc>\": is_datetime,\n",
    "            }\n",
    "            for k,v in lookup.items():\n",
    "                if all(x[key] is None or v(x[key]) for x in data):\n",
    "                    if data_type != \"String\":\n",
    "                        raise Exception(f\"Complex type not supported for key {key}: was {data_type}, now {k}\")\n",
    "                    data_type = k\n",
    "\n",
    "        optional = any(x[key] is None for x in data)\n",
    "        if optional:\n",
    "            data_type = f\"Option<{data_type or 'Value'}>\"\n",
    "    \n",
    "    rename = None if key == key.lower() else camel_to_snake(key)\n",
    "    if key == \"type\":\n",
    "        rename = \"kind\"\n",
    "    if rename is not None:\n",
    "        print(f\"#[serde(rename = \\\"{key}\\\")]\")\n",
    "        print(f\"pub {rename}: {data_type},\")\n",
    "    else:\n",
    "        print(f\"pub {key}: {data_type},\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "base",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.11.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
