# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements.  See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership.  The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License.  You may obtain a copy of the License at
#
#   http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied.  See the License for the
# specific language governing permissions and limitations
# under the License.

from abc import ABC, abstractmethod
from typing import Dict, List, Optional


class Types:
    FILE = "file"
    SQL = "sql"
    LAMBDA = "lambda"


class FunctionFileResource:
    """Represents a file resource for a function."""

    def __init__(self, resource_type: str, uri: str):
        self.resource_type = resource_type
        self.uri = uri

    def to_dict(self) -> Dict:
        return {
            "resourceType": self.resource_type,
            "uri": self.uri,
        }

    @classmethod
    def from_dict(cls, data: Dict) -> "FunctionFileResource":
        return cls(
            resource_type=data.get("resourceType"),
            uri=data.get("uri"),
        )

    def __eq__(self, other):
        if not isinstance(other, FunctionFileResource):
            return False
        return self.resource_type == other.resource_type and self.uri == other.uri

    def __hash__(self):
        return hash((self.resource_type, self.uri))


class FunctionDefinition(ABC):
    """Base class for function definitions."""

    @staticmethod
    def file(
        file_resources: List[FunctionFileResource],
        language: str,
        class_name: str,
        function_name: str,
    ) -> "FunctionDefinition":
        return FileFunctionDefinition(file_resources, language, class_name, function_name)

    @staticmethod
    def sql(body: str) -> "FunctionDefinition":
        return SQLFunctionDefinition(body)

    @staticmethod
    def lambda_def(definition: str, language: str) -> "FunctionDefinition":
        return LambdaFunctionDefinition(definition, language)

    @abstractmethod
    def to_dict(self) -> Dict:
        """Convert to dict for JSON serialization."""

    @staticmethod
    def from_dict(data: Dict) -> Optional["FunctionDefinition"]:
        if data is None:
            return None
        defn_type = data.get("type")
        if defn_type == Types.FILE:
            file_resources = data.get("fileResources")
            if file_resources is not None:
                file_resources = [
                    FunctionFileResource.from_dict(r) if isinstance(r, dict) else r
                    for r in file_resources
                ]
            return FileFunctionDefinition(
                file_resources=file_resources,
                language=data.get("language"),
                class_name=data.get("className"),
                function_name=data.get("functionName"),
            )
        elif defn_type == Types.SQL:
            return SQLFunctionDefinition(definition=data.get("definition"))
        elif defn_type == Types.LAMBDA:
            return LambdaFunctionDefinition(
                definition=data.get("definition"),
                language=data.get("language"),
            )
        else:
            raise ValueError(f"Unknown function definition type: {defn_type}")


class FileFunctionDefinition(FunctionDefinition):

    def __init__(
        self,
        file_resources: List[FunctionFileResource],
        language: str,
        class_name: str,
        function_name: str,
    ):
        self.file_resources = file_resources
        self.language = language
        self.class_name = class_name
        self.function_name = function_name

    def to_dict(self) -> Dict:
        return {
            "type": Types.FILE,
            "fileResources": [
                r.to_dict() if isinstance(r, FunctionFileResource) else r
                for r in self.file_resources
            ] if self.file_resources else None,
            "language": self.language,
            "className": self.class_name,
            "functionName": self.function_name,
        }

    def __eq__(self, other):
        if not isinstance(other, FileFunctionDefinition):
            return False
        return (self.file_resources == other.file_resources
                and self.language == other.language
                and self.class_name == other.class_name
                and self.function_name == other.function_name)

    def __hash__(self):
        return hash((
            tuple(self.file_resources) if self.file_resources else (),
            self.language,
            self.class_name,
            self.function_name,
        ))


class SQLFunctionDefinition(FunctionDefinition):

    def __init__(self, definition: str):
        self.definition = definition

    def to_dict(self) -> Dict:
        return {
            "type": Types.SQL,
            "definition": self.definition,
        }

    def __eq__(self, other):
        if not isinstance(other, SQLFunctionDefinition):
            return False
        return self.definition == other.definition

    def __hash__(self):
        return hash(self.definition)


class LambdaFunctionDefinition(FunctionDefinition):

    def __init__(self, definition: str, language: str):
        self.definition = definition
        self.language = language

    def to_dict(self) -> Dict:
        return {
            "type": Types.LAMBDA,
            "definition": self.definition,
            "language": self.language,
        }

    def __eq__(self, other):
        if not isinstance(other, LambdaFunctionDefinition):
            return False
        return self.definition == other.definition and self.language == other.language

    def __hash__(self):
        return hash((self.definition, self.language))
