# -*- coding: utf-8; -*-
################################################################################
#
#  WuttaFarm --Web app to integrate with and extend farmOS
#  Copyright © 2026 Lance Edgar
#
#  This file is part of WuttaFarm.
#
#  WuttaFarm is free software: you can redistribute it and/or modify it under
#  the terms of the GNU General Public License as published by the Free Software
#  Foundation, either version 3 of the License, or (at your option) any later
#  version.
#
#  WuttaFarm is distributed in the hope that it will be useful, but WITHOUT ANY
#  WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
#  A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
#
#  You should have received a copy of the GNU General Public License along with
#  WuttaFarm.  If not, see <http://www.gnu.org/licenses/>.
#
################################################################################
"""
Model definition for Logs
"""

import sqlalchemy as sa
from sqlalchemy import orm
from sqlalchemy.ext.declarative import declared_attr
from sqlalchemy.ext.associationproxy import association_proxy

from wuttjamaican.db import model


class LogType(model.Base):
    """
    Represents a "log type" from farmOS
    """

    __tablename__ = "log_type"
    __versioned__ = {}
    __wutta_hint__ = {
        "model_title": "Log Type",
        "model_title_plural": "Log Types",
    }

    uuid = model.uuid_column()

    name = sa.Column(
        sa.String(length=100),
        nullable=False,
        unique=True,
        doc="""
        Name of the log type.
        """,
    )

    description = sa.Column(
        sa.String(length=255),
        nullable=True,
        doc="""
        Optional description for the log type.
        """,
    )

    farmos_uuid = sa.Column(
        model.UUID(),
        nullable=True,
        unique=True,
        doc="""
        UUID for the log type within farmOS.
        """,
    )

    drupal_id = sa.Column(
        sa.String(length=50),
        nullable=True,
        unique=True,
        doc="""
        Drupal internal ID for the log type.
        """,
    )

    def __str__(self):
        return self.name or ""


class Log(model.Base):
    """
    Represents a base log record from farmOS
    """

    __tablename__ = "log"
    __versioned__ = {}
    __wutta_hint__ = {
        "model_title": "Log",
        "model_title_plural": "All Logs",
    }

    uuid = model.uuid_column()

    log_type = sa.Column(
        sa.String(length=100),
        sa.ForeignKey("log_type.drupal_id"),
        nullable=False,
    )

    message = sa.Column(
        sa.String(length=255),
        nullable=False,
        doc="""
        Message text for the log.
        """,
    )

    timestamp = sa.Column(
        sa.DateTime(),
        nullable=False,
        doc="""
        Date and time when the log event occurred / will occur.
        """,
    )

    is_movement = sa.Column(
        sa.Boolean(),
        nullable=True,
        doc="""
        Whether the log represents a movement to new location.
        """,
    )

    is_group_assignment = sa.Column(
        sa.Boolean(),
        nullable=True,
        doc="""
        Whether the log represents a group assignment.
        """,
    )

    status = sa.Column(
        sa.String(length=20),
        nullable=False,
        doc="""
        Current status of the log event.
        """,
    )

    notes = sa.Column(
        sa.Text(),
        nullable=True,
        doc="""
        Arbitrary notes for the log event.
        """,
    )

    quick = sa.Column(
        sa.String(length=20),
        nullable=True,
        doc="""
        Identifier of quick form used to create the log, if
        applicable.
        """,
    )

    farmos_uuid = sa.Column(
        model.UUID(),
        nullable=True,
        unique=True,
        doc="""
        UUID for the log within farmOS.
        """,
    )

    drupal_id = sa.Column(
        sa.Integer(),
        nullable=True,
        unique=True,
        doc="""
        Drupal internal ID for the log.
        """,
    )

    _assets = orm.relationship(
        "LogAsset",
        cascade="all, delete-orphan",
        cascade_backrefs=False,
        back_populates="log",
    )

    assets = association_proxy(
        "_assets",
        "asset",
        creator=lambda asset: LogAsset(asset=asset),
    )

    _groups = orm.relationship(
        "LogGroup",
        cascade="all, delete-orphan",
        cascade_backrefs=False,
        back_populates="log",
    )

    groups = association_proxy(
        "_groups",
        "asset",
        creator=lambda asset: LogGroup(asset=asset),
    )

    _locations = orm.relationship(
        "LogLocation",
        cascade="all, delete-orphan",
        cascade_backrefs=False,
        back_populates="log",
    )

    locations = association_proxy(
        "_locations",
        "asset",
        creator=lambda asset: LogLocation(asset=asset),
    )

    _quantities = orm.relationship(
        "LogQuantity",
        cascade="all, delete-orphan",
        cascade_backrefs=False,
        back_populates="log",
    )

    quantities = association_proxy(
        "_quantities",
        "quantity",
        creator=lambda quantity: LogQuantity(quantity=quantity),
    )

    _owners = orm.relationship(
        "LogOwner",
        cascade="all, delete-orphan",
        cascade_backrefs=False,
        back_populates="log",
    )

    owners = association_proxy(
        "_owners",
        "user",
        creator=lambda user: LogOwner(user=user),
    )

    def __str__(self):
        return self.message or ""


class LogMixin:

    uuid = model.uuid_fk_column("log.uuid", nullable=False, primary_key=True)

    @declared_attr
    def log(cls):
        return orm.relationship(
            Log,
            single_parent=True,
            cascade="all, delete-orphan",
            cascade_backrefs=False,
        )

    def __str__(self):
        return self.message or ""


def add_log_proxies(subclass):
    Log.make_proxy(subclass, "log", "farmos_uuid")
    Log.make_proxy(subclass, "log", "drupal_id")
    Log.make_proxy(subclass, "log", "log_type")
    Log.make_proxy(subclass, "log", "message")
    Log.make_proxy(subclass, "log", "timestamp")
    Log.make_proxy(subclass, "log", "is_movement")
    Log.make_proxy(subclass, "log", "is_group_assignment")
    Log.make_proxy(subclass, "log", "status")
    Log.make_proxy(subclass, "log", "notes")
    Log.make_proxy(subclass, "log", "quick")
    Log.make_proxy(subclass, "log", "assets")
    Log.make_proxy(subclass, "log", "groups")
    Log.make_proxy(subclass, "log", "locations")
    Log.make_proxy(subclass, "log", "quantities")
    Log.make_proxy(subclass, "log", "owners")


class LogAsset(model.Base):
    """
    Represents a "log's asset relationship" from farmOS.
    """

    __tablename__ = "log_asset"
    __versioned__ = {}

    uuid = model.uuid_column()

    log_uuid = model.uuid_fk_column("log.uuid", nullable=False)
    log = orm.relationship(
        Log,
        foreign_keys=log_uuid,
        back_populates="_assets",
    )

    asset_uuid = model.uuid_fk_column("asset.uuid", nullable=False)
    asset = orm.relationship(
        "Asset",
        foreign_keys=asset_uuid,
    )


class LogGroup(model.Base):
    """
    Represents a "log's group relationship" from farmOS.
    """

    __tablename__ = "log_group"
    __versioned__ = {}

    uuid = model.uuid_column()

    log_uuid = model.uuid_fk_column("log.uuid", nullable=False)
    log = orm.relationship(
        Log,
        foreign_keys=log_uuid,
        back_populates="_groups",
    )

    asset_uuid = model.uuid_fk_column("asset.uuid", nullable=False)
    asset = orm.relationship(
        "Asset",
        foreign_keys=asset_uuid,
    )


class LogLocation(model.Base):
    """
    Represents a "log's location relationship" from farmOS.
    """

    __tablename__ = "log_location"
    __versioned__ = {}

    uuid = model.uuid_column()

    log_uuid = model.uuid_fk_column("log.uuid", nullable=False)
    log = orm.relationship(
        Log,
        foreign_keys=log_uuid,
        back_populates="_locations",
    )

    asset_uuid = model.uuid_fk_column("asset.uuid", nullable=False)
    asset = orm.relationship(
        "Asset",
        foreign_keys=asset_uuid,
    )


class LogQuantity(model.Base):
    """
    Represents a "log's quantity relationship" from farmOS.
    """

    __tablename__ = "log_quantity"
    __versioned__ = {}

    uuid = model.uuid_column()

    log_uuid = model.uuid_fk_column("log.uuid", nullable=False)
    log = orm.relationship(
        Log,
        foreign_keys=log_uuid,
        back_populates="_quantities",
    )

    quantity_uuid = model.uuid_fk_column("quantity.uuid", nullable=False)
    quantity = orm.relationship(
        "Quantity",
        foreign_keys=quantity_uuid,
        back_populates="_log",
    )


class LogOwner(model.Base):
    """
    Represents a "log's owner relationship" from farmOS.
    """

    __tablename__ = "log_owner"
    __versioned__ = {}

    uuid = model.uuid_column()

    log_uuid = model.uuid_fk_column("log.uuid", nullable=False)
    log = orm.relationship(
        Log,
        foreign_keys=log_uuid,
        back_populates="_owners",
    )

    user_uuid = model.uuid_fk_column("user.uuid", nullable=False)
    user = orm.relationship(
        model.User,
        foreign_keys=user_uuid,
    )
