# Copyright (c) IBM Corporation
# SPDX-License-Identifier: MIT

"""This module contains resource instance models

The resource template models are kept in config"""

import datetime
import enum

import pydantic


class CoreResourceKinds(enum.Enum):
    RESOURCE = "resource"
    OPERATION = "operation"
    RESULT = "result"
    DISCOVERYSPACE = "discoveryspace"
    # ACTUATOR = "actuator" AP - REMOVING IT AS REPLACED BY ACTUATORCONFIGURATION
    ACTUATORCONFIGURATION = "actuatorconfiguration"
    OPERATOR = "operator"
    SAMPLESTORE = "samplestore"
    DATACONTAINER = "datacontainer"


def VersionIsGreaterThan(v1: str, v2: str):
    """Returns True if resource version v1 is greater than resource version v2"""

    return int(v1[1:]) > int(v2[1:])


class ADOResourceEventEnum(enum.Enum):
    """Events in resources lifecycle"""

    CREATED = "created"
    ADDED = "added"
    UPDATED = "updated"


class ADOResourceStatus(pydantic.BaseModel):
    """Records information on the status of a resource - in the base case a life-cycle event that occurred

    Creation, Addition to DB, Update in DB. Other resources may have custom events or other status fields
    """

    message: str | None = pydantic.Field(
        default=None,
        description="An optional message giving information about this status",
    )
    recorded_at: datetime.datetime = pydantic.Field(
        default_factory=lambda: datetime.datetime.now(datetime.timezone.utc),
        description="When this status was recorded",
    )
    event: ADOResourceEventEnum = pydantic.Field(
        description="An event that happened to a resource: created, added or updated"
    )


class ADOResource(pydantic.BaseModel):

    version: str = "v1"
    kind: CoreResourceKinds = CoreResourceKinds.RESOURCE
    created: datetime.datetime = pydantic.Field(
        default_factory=lambda: datetime.datetime.now(datetime.timezone.utc),
        description="When the resource was created",
    )
    identifier: str | None = pydantic.Field(
        default=None,
        description="The resources unique identifier. Autogenerated based on kind if not provided",
    )
    status: list[ADOResourceStatus] = pydantic.Field(
        default_factory=lambda: [ADOResourceStatus(event=ADOResourceEventEnum.CREATED)],
        description="A list of status objects. A status object describes something notable that happened to the resource",
    )
    metadata: dict = pydantic.Field(default={}, description="Metadata dictionary")

    model_config = pydantic.ConfigDict(extra="forbid")


def warn_deprecated_resource_model_in_use(
    affected_resource: CoreResourceKinds,
    deprecated_from_ado_version: str,
    removed_from_ado_version: str,
    deprecated_fields: str | list[str] | None = None,
    latest_format_documentation_url: str | None = None,
):
    from rich.console import Console

    # AP: some resources have a slightly different name in the CLI
    mapping = {k: k.value for k in CoreResourceKinds}
    overrides = {CoreResourceKinds.DISCOVERYSPACE: "space"}
    mapping.update(overrides)
    resource_name = mapping.get(affected_resource)
    doc_url = (
        f": {latest_format_documentation_url}"
        if latest_format_documentation_url
        else ""
    )

    if deprecated_fields is not None:
        fields_causing_issues = f"fields [b magenta]{deprecated_fields}[/b magenta]"
        if isinstance(deprecated_fields, str):
            fields_causing_issues = f"field [b magenta]{deprecated_fields}[/b magenta]"
        elif isinstance(deprecated_fields, list) and len(deprecated_fields) == 1:
            fields_causing_issues = (
                f"field [b magenta]{deprecated_fields[0]}[/b magenta]"
            )

        warning_preamble = (
            f"{resource_name.title()}s containing the {fields_causing_issues} "
            f"are deprecated as of ado [b cyan]{deprecated_from_ado_version}[/b cyan] "
            f"and no longer supported."
        )
    else:
        warning_preamble = (
            f"{resource_name.title()}s have been updated "
            f"as of ado [b cyan]{deprecated_from_ado_version}[/b cyan] "
            f"and the previous version is no longer supported."
        )

    autoupgrade_notice = (
        "They are being temporarily auto-upgraded to the latest version."
    )
    autoupgrade_removal_warning = (
        f"[b]This fallback will be removed with ado "
        f"[b cyan]{removed_from_ado_version}[/b cyan][/b]."
    )
    manual_upgrade_hint = (
        f"Run [b cyan]ado upgrade {resource_name}s[/b cyan] to upgrade the stored {resource_name}s. "
        f"Update your {resource_name} YAML files to use the latest format{doc_url}."
    )

    Console(stderr=True).print(
        f"[b yellow]WARN[/b yellow]:\t{warning_preamble}\n\t"
        f"{autoupgrade_notice}\n\t{autoupgrade_removal_warning}\n"
        f"[b magenta]HINT[/b magenta]:\t{manual_upgrade_hint}",
        overflow="ignore",
        crop=False,
    )
