"""
GitHub Application on Microsoft Entra.
It allows to deploy an application on Azure WebApplication using GitHub Actions.
"""
from dataclasses import dataclass
from typing import Optional
from weblodge.config import Item as ConfigItem
from weblodge._azure import AzureService

from .build import BuildConfig
from .deploy import DeploymentConfig


@dataclass
class GitHubWorkflow:
    """
    GitHub workflow.
    """
    # The branch that triggers the workflow.
    branch: str
    # Workflow content.
    content: str
    # Application credentials to put in GitHub secrets.
    client_id: str
    tenant_id: str
    subscription_id: str


class GitHubConfig:
    """
    GitHub Application configuration.
    Handle deployment and build configuration.
    """
    # Configurable items of the build.
    items = [
        ConfigItem(
            name='username',
            description='The GitHub username/organisation.',
        ),
        ConfigItem(
            name='repository',
            description='The GitHub repository.',
        ),
        ConfigItem(
            name='branch',
            description='The deployment branch.',
        ),
        ConfigItem(
            name='delete',
            description='Delete the deployment application.',
            attending_value=False,
        ),
        *BuildConfig.items,
        *DeploymentConfig.items
    ]

    # pylint: disable=too-many-arguments
    def __init__(
        self,
        subdomain: str,
        branch: str,
        username: str,
        repository: str,
        location: str,
        delete: bool,
        *_args,
        **_kwargs
    ):
        self.subdomain = subdomain
        self.branch = branch
        self.username = username
        self.repository = repository
        self.location = location
        self.delete = delete


def github(service: AzureService, config: GitHubConfig) -> Optional[GitHubWorkflow]:
    """
    Create a GitHub Application on Microsoft Entra.

    :param service: The Azure service.
    :param config: The GitHub Application configuration.
    :return: The GitHub workflow or None if the GitHub workflow has been deleted.
    """
    rg_created = False
    resource_group = service.resource_groups(config.subdomain)

    if not resource_group.exists():
        rg_created = True
        resource_group.create(config.location)

    entra_application = service.entra.github_application(
        name=config.subdomain,
        branch=config.branch,
        username=config.username,
        repository=config.repository,
        resource_group=resource_group
    )

    if config.delete:
        entra_application.delete()
        if rg_created:
            # The resource group may have been deleted before requesting the application's deletion.
            # In this case, we've recreated it to be able to find the application,
            # and we need to delete it again.
            resource_group.delete()
        return None

    return GitHubWorkflow(
        branch=config.branch,
        content=_github_workflow(config),
        client_id=entra_application.client_id,
        tenant_id=entra_application.tenant_id,
        subscription_id=entra_application.subscription_id,
    )


def _github_workflow(config: GitHubConfig) -> str:
    """
    GitHub workflow.
    """
    return f"""\
# This file is generated by weblodge.
# Please do not edit it manually.
name: Weblodge deploy.
on:
  push:
    branches:
      - {config.branch}

permissions:
  id-token: write
  contents: read

jobs:
  build-and-deploy:
    timeout-minutes: 20
    runs-on: ubuntu-latest
    steps:
      - name: 'Az CLI login'
        uses: azure/login@v1
        with:
          client-id: ${{{{ secrets.AZURE_CLIENT_ID }}}}
          tenant-id: ${{{{ secrets.AZURE_TENANT_ID }}}}
          subscription-id: ${{{{ secrets.AZURE_SUBSCRIPTION_ID }}}}

      - uses: actions/checkout@v4

      - name: 'Install WebLodge.'
        run: |
          pip install weblodge

      - name: 'Build and deploy.'
        run: |
          weblodge deploy --build
"""
