# -*- 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/>.
#
################################################################################
"""
Master view for Farm Animals
"""

import datetime

import colander
from webhelpers2.html import tags

from wuttaweb.forms.schema import WuttaDateTime, WuttaDictEnum
from wuttaweb.forms.widgets import WuttaDateTimeWidget

from wuttafarm.web.views.farmos.assets import AssetMasterView
from wuttafarm.web.grids import (
    SimpleSorter,
    StringFilter,
    BooleanFilter,
    NullableBooleanFilter,
    DateTimeFilter,
)
from wuttafarm.web.forms.schema import FarmOSRef


class AnimalView(AssetMasterView):
    """
    Master view for Farm Animals
    """

    model_name = "farmos_animal_assets"
    model_title = "farmOS Animal Asset"
    model_title_plural = "farmOS Animal Assets"

    route_prefix = "farmos_animal_assets"
    url_prefix = "/farmOS/assets/animal"

    farmos_asset_type = "animal"
    farmos_refurl_path = "/assets/animal"

    labels = {
        "animal_type": "Species / Breed",
        "animal_type_name": "Species / Breed",
        "is_sterile": "Sterile",
    }

    grid_columns = [
        "thumbnail",
        "drupal_id",
        "name",
        "produces_eggs",
        "animal_type_name",
        "birthdate",
        "is_sterile",
        "sex",
        "groups",
        "owners",
        "locations",
        "archived",
    ]

    form_fields = [
        "name",
        "animal_type",
        "birthdate",
        "produces_eggs",
        "sex",
        "is_sterile",
        "notes",
        "asset_type_name",
        "owners",
        "locations",
        "groups",
        "archived",
        "thumbnail_url",
        "image_url",
        "thumbnail",
        "image",
    ]

    def get_farmos_api_includes(self):
        includes = super().get_farmos_api_includes()
        includes.update(["animal_type"])
        return includes

    def configure_grid(self, grid):
        g = grid
        super().configure_grid(g)
        enum = self.app.enum

        # produces_eggs
        g.set_renderer("produces_eggs", "boolean")
        g.set_sorter("produces_eggs", SimpleSorter("produces_eggs"))
        g.set_filter("produces_eggs", NullableBooleanFilter)

        # animal_type_name
        if self.farmos_style_grid_links:
            g.set_renderer("animal_type_name", self.render_animal_type_for_grid)
        else:
            g.set_link("animal_type_name")
        g.set_sorter("animal_type_name", SimpleSorter("animal_type.name"))
        g.set_filter("animal_type_name", StringFilter, path="animal_type.name")

        # birthdate
        g.set_renderer("birthdate", "date")
        g.set_sorter("birthdate", SimpleSorter("birthdate"))
        g.set_filter("birthdate", DateTimeFilter)

        # sex
        g.set_enum("sex", enum.ANIMAL_SEX)
        g.set_sorter("sex", SimpleSorter("sex"))
        g.set_filter("sex", StringFilter)

        # is_sterile
        g.set_renderer("is_sterile", "boolean")
        g.set_sorter("is_sterile", SimpleSorter("is_sterile"))
        g.set_filter("is_sterile", BooleanFilter)

    def render_animal_type_for_grid(self, animal, field, value):
        uuid = animal["animal_type"]["uuid"]
        url = self.request.route_url("farmos_animal_types.view", uuid=uuid)
        return tags.link_to(value, url)

    def get_instance(self):

        data = super().get_instance()

        if relationships := self.raw_json["data"].get("relationships"):

            # add animal type
            if not data.get("animal_type"):
                if animal_type := relationships.get("animal_type"):
                    if animal_type["data"]:
                        animal_type = self.farmos_client.resource.get_id(
                            "taxonomy_term", "animal_type", animal_type["data"]["id"]
                        )
                        data["animal_type"] = {
                            "uuid": animal_type["data"]["id"],
                            "name": animal_type["data"]["attributes"]["name"],
                        }

        return data

    def normalize_asset(self, animal, included):
        normal = super().normalize_asset(animal, included)

        birthdate = animal["attributes"]["birthdate"]
        if birthdate:
            birthdate = datetime.datetime.fromisoformat(birthdate)
            birthdate = self.app.localtime(birthdate)

        sterile = None
        if self.farmos_4x:
            sterile = animal["attributes"]["is_sterile"]
        else:
            sterile = animal["attributes"]["is_castrated"]

        animal_type_object = None
        if relationships := animal.get("relationships"):

            if animal_type := relationships.get("animal_type"):
                if animal_type := included.get(animal_type["data"]["id"]):
                    animal_type_object = {
                        "uuid": animal_type["id"],
                        "name": animal_type["attributes"]["name"],
                    }

        normal.update(
            {
                "animal_type": animal_type_object,
                "animal_type_uuid": animal_type_object["uuid"],
                "animal_type_name": animal_type_object["name"],
                "birthdate": birthdate,
                "sex": animal["attributes"]["sex"] or colander.null,
                "is_sterile": sterile,
                "produces_eggs": animal["attributes"].get("produces_eggs"),
            }
        )

        return normal

    def get_animal_types(self):
        animal_types = []
        result = self.farmos_client.resource.get(
            "taxonomy_term", "animal_type", params={"sort": "name"}
        )
        for animal_type in result["data"]:
            animal_types.append((animal_type["id"], animal_type["attributes"]["name"]))
        return animal_types

    def configure_form(self, form):
        f = form
        super().configure_form(f)
        enum = self.app.enum
        animal = f.model_instance

        # animal_type
        f.set_node(
            "animal_type",
            FarmOSRef(
                self.request, "farmos_animal_types", values=self.get_animal_types
            ),
        )

        # produces_eggs
        f.set_node("produces_eggs", colander.Boolean())

        # birthdate
        f.set_node("birthdate", WuttaDateTime())
        f.set_widget("birthdate", WuttaDateTimeWidget(self.request))
        f.set_required("birthdate", False)

        # sex
        if not (self.creating or self.editing) and not animal["sex"]:
            pass  # TODO: dict enum widget does not handle null values well
        else:
            f.set_node("sex", WuttaDictEnum(self.request, enum.ANIMAL_SEX))
            f.set_required("sex", False)

        # is_sterile
        f.set_node("is_sterile", colander.Boolean())

    def get_api_payload(self, animal):
        payload = super().get_api_payload(animal)

        birthdate = None
        if animal["birthdate"]:
            birthdate = self.app.localtime(animal["birthdate"]).timestamp()

        attrs = {
            "sex": animal["sex"] or None,
            "is_sterile": animal["is_sterile"],
            "produces_eggs": animal["produces_eggs"],
            "birthdate": birthdate,
        }

        rels = {
            "animal_type": {
                "data": {
                    "id": animal["animal_type"],
                    "type": "taxonomy_term--animal_type",
                }
            }
        }

        payload["attributes"].update(attrs)
        payload.setdefault("relationships", {}).update(rels)
        return payload

    def get_xref_buttons(self, animal):
        buttons = super().get_xref_buttons(animal)

        if self.app.is_farmos_mirror():
            model = self.app.model
            session = self.Session()

            if wf_animal := (
                session.query(model.Asset)
                .filter(model.Asset.farmos_uuid == animal["uuid"])
                .first()
            ):
                buttons.append(
                    self.make_button(
                        f"View {self.app.get_title()} record",
                        primary=True,
                        url=self.request.route_url(
                            "animal_assets.view", uuid=wf_animal.uuid
                        ),
                        icon_left="eye",
                    )
                )

        return buttons


def defaults(config, **kwargs):
    base = globals()

    AnimalView = kwargs.get("AnimalView", base["AnimalView"])
    AnimalView.defaults(config)


def includeme(config):
    defaults(config)
