# Copyright (c) 2024 CloudZero - ALL RIGHTS RESERVED - PROPRIETARY AND CONFIDENTIAL
# Unauthorized copying of this file and/or project, via any medium is strictly prohibited.
# Direct all questions to legal@cloudzero.com

from dataclasses import dataclass
from time import sleep
from typing import Any

from pulumi import Input, Output, ResourceOptions
from pulumi.dynamic import CreateResult, Resource, ResourceProvider, UpdateResult
from pydantic import Field

from czpulumi.sumo_logic.context_managers import TemporarySumoFolder
from czpulumi.sumo_logic.folders import get_folder, update_folder
from czpulumi.sumo_logic.sumo_client import (
    JobType,
    delete_content,
    get_sumo_client,
    wait_on_job,
)


@dataclass
class SumoAppInstallArgs:
    uuid: Input[str] = Field(..., description='The UUID of the app to install. This can be found on the Sumo Logic UI')
    name: Input[str] = Field(..., description='The name of the app')
    description: Input[str] = Field(..., description='The description of the app')
    parent_folder_id: Input[str] = Field(..., description='The ID of the parent folder to install the app in')
    data_source_values: Input[dict] = Field(
        ...,
        description="The data source values for the app. These are key value pairs that are used to overwrite portions of the app's configuration. For example, the GitHub app uses a data source value to set the source category for the logs it collects.",
    )


class SumoAppInstallProvider(ResourceProvider):
    def create(self, args: dict) -> CreateResult:
        folder_id = self._install_app(
            uuid=args['uuid'],
            name=args['name'],
            description=args['description'],
            parent_folder_id=args['parent_folder_id'],
            data_source_values=args['data_source_values'],
        )
        return CreateResult(id_=folder_id, outs={**args, 'folder_id': folder_id})

    def update(self, resource_id, previous_args, new_args):
        client = get_sumo_client()
        # Change folder name / description
        if previous_args['name'] != new_args['name'] or previous_args['description'] != new_args['description']:
            update_folder(resource_id, {'name': new_args['name'], 'description': new_args['description']})

        # Move folder
        if previous_args['parent_folder_id'] != new_args['parent_folder_id']:
            client.move_content(content_id=resource_id, destination_folder=new_args['parent_folder_id'])

        # Change data source values
        if previous_args['data_source_values'] != new_args['data_source_values']:
            with TemporarySumoFolder() as temp_folder:
                self._install_app(
                    uuid=new_args['uuid'],
                    name=new_args['name'],
                    description=new_args['description'],
                    parent_folder_id=temp_folder['id'],
                    data_source_values=new_args['data_source_values'],
                )
                active_folder_children = get_folder(folder_id=resource_id)['children']
                for child in active_folder_children:
                    delete_content(content_id=child['id'])
                temp_folder_child_id = get_folder(folder_id=temp_folder['id'])['children'][0]['id']
                temp_folder_child = get_folder(folder_id=temp_folder_child_id)
                for item in temp_folder_child['children']:
                    client.move_content(content_id=item['id'], destination_folder=resource_id)
                    sleep(1)  # sleep for a second to avoid rate limiting
        return UpdateResult(outs=new_args)

    def delete(self, resource_id, _args):
        delete_content(content_id=resource_id)

    def _install_app(self, uuid: str, name: str, description: str, parent_folder_id: str, data_source_values: dict[str, Any]):
        client = get_sumo_client()
        res = client.install_app(
            app_id=uuid,
            content={
                'name': name,
                'description': description,
                'destinationFolderId': parent_folder_id,
                'dataSourceValues': data_source_values,
            },
        )
        install_app_job_id = res.json()['id']
        wait_on_job(job_id=install_app_job_id, job_type=JobType.APP_INSTALL)
        personal_folder_res = get_folder(folder_id=parent_folder_id)
        folder_id = ''
        for folder in personal_folder_res['children']:
            if folder['name'] == name:
                folder_id = folder['id']
                break
        if not folder_id:
            raise Exception(f'Could not find folder with name: {name}')
        return folder_id


class SumoAppInstallResource(Resource):
    uuid: Output[str]
    name: Output[str]
    description: Output[str]
    parent_folder_id: Output[str]

    def __init__(self, resource_name: str, args: SumoAppInstallArgs, opts: ResourceOptions | None = None):
        suffix = f'{args.uuid}'[:8]
        super().__init__(SumoAppInstallProvider(), f'{resource_name}_{suffix}', {'parent_folder_id': '', **vars(args)}, opts)
