# -*- 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/>.
#
################################################################################
"""
Quick Form for "Eggs"
"""

import json

import colander
from deform.widget import SelectWidget

from farmOS.subrequests import Action, Subrequest, SubrequestsBlueprint, Format

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

from wuttafarm.web.views.quick import QuickFormView


class EggsQuickForm(QuickFormView):
    """
    Use this form to record an egg harvest. A harvest log will be
    created with standard details filled in.
    """

    form_title = "Eggs"
    route_slug = "eggs"
    url_slug = "eggs"

    _layer_assets = None

    # TODO: make this configurable?
    unit_name = "egg(s)"

    def make_quick_form(self):
        f = self.make_form(
            fields=[
                "timestamp",
                "count",
                "asset",
                "notes",
            ],
            labels={
                "timestamp": "Date",
                "count": "Quantity",
                "asset": "Layer Asset",
            },
        )

        # timestamp
        f.set_node("timestamp", WuttaDateTime())
        f.set_widget("timestamp", WuttaDateTimeWidget(self.request))
        f.set_default("timestamp", self.app.make_utc())

        # count
        f.set_node("count", colander.Integer())

        # asset
        assets = self.get_layer_assets()
        values = [(a["uuid"], a["name"]) for a in assets]
        f.set_widget("asset", SelectWidget(values=values))
        if len(assets) == 1:
            f.set_default("asset", assets[0]["uuid"])

        # notes
        f.set_widget("notes", "notes")
        f.set_required("notes", False)

        return f

    def get_layer_assets(self):
        if self._layer_assets is not None:
            return self._layer_assets

        if self.app.is_farmos_wrapper():
            assets = self.get_layer_assets_from_farmos()
        else:
            assets = self.get_layer_assets_from_wuttafarm()

        assets.sort(key=lambda a: a["name"])
        self._layer_assets = assets
        return assets

    def get_layer_assets_from_wuttafarm(self):
        model = self.app.model
        session = self.Session()
        assets = []

        def normalize(asset):
            asset_type = asset.__wutta_hint__["farmos_asset_type"]
            return {
                "uuid": str(asset.farmos_uuid),
                "name": asset.asset_name,
                "type": f"asset--{asset_type}",
            }

        query = (
            session.query(model.AnimalAsset)
            .join(model.Asset)
            .filter(model.AnimalAsset.produces_eggs == True)
            .order_by(model.Asset.asset_name)
        )
        assets.extend([normalize(a) for a in query])

        query = (
            session.query(model.GroupAsset)
            .join(model.Asset)
            .filter(model.GroupAsset.produces_eggs == True)
            .order_by(model.Asset.asset_name)
        )
        assets.extend([normalize(a) for a in query])

        return assets

    def get_layer_assets_from_farmos(self):
        assets = []
        params = {
            "filter[produces_eggs]": 1,
            "sort": "name",
        }

        def normalize(asset):
            return {
                "uuid": asset["id"],
                "name": asset["attributes"]["name"],
                "type": asset["type"],
            }

        result = self.farmos_client.asset.get("animal", params=params)
        assets.extend([normalize(a) for a in result["data"]])

        result = self.farmos_client.asset.get("group", params=params)
        assets.extend([normalize(a) for a in result["data"]])

        return assets

    def save_quick_form(self, form):

        if self.app.is_farmos_wrapper():
            return self.save_to_farmos(form)

        return self.save_to_wuttafarm(form)

    def save_to_farmos(self, form):
        data = form.validated

        assets = self.get_layer_assets()
        assets = {a["uuid"]: a for a in assets}
        asset = assets[data["asset"]]

        # TODO: make this configurable?
        unit_name = self.unit_name

        unit = {"data": {"type": "taxonomy_term--unit"}}
        new_unit = None

        result = self.farmos_client.resource.get(
            "taxonomy_term",
            "unit",
            params={
                "filter[name]": unit_name,
            },
        )
        if result["data"]:
            unit["data"]["id"] = result["data"][0]["id"]
        else:
            payload = dict(unit)
            payload["data"]["attributes"] = {"name": unit_name}
            new_unit = Subrequest(
                action=Action.create,
                requestId="create-unit",
                endpoint="api/taxonomy_term/unit",
                body=payload,
            )
            unit["data"]["id"] = "{{create-unit.body@$.data.id}}"

        quantity = {
            "data": {
                "type": "quantity--standard",
                "attributes": {
                    "measure": "count",
                    "value": {
                        "numerator": data["count"],
                        "denominator": 1,
                    },
                },
                "relationships": {
                    "units": unit,
                },
            },
        }

        kw = {}
        if new_unit:
            kw["waitFor"] = ["create-unit"]
        new_quantity = Subrequest(
            action=Action.create,
            requestId="create-quantity",
            endpoint="api/quantity/standard",
            body=quantity,
            **kw,
        )

        notes = None
        if data["notes"]:
            notes = {"value": data["notes"]}

        log = {
            "data": {
                "type": "log--harvest",
                "attributes": {
                    "name": f"Collected {data['count']} {unit_name}",
                    "timestamp": self.app.localtime(data["timestamp"]).timestamp(),
                    "notes": notes,
                    "quick": ["eggs"],
                },
                "relationships": {
                    "asset": {
                        "data": [
                            {
                                "id": asset["uuid"],
                                "type": asset["type"],
                            },
                        ],
                    },
                    "quantity": {
                        "data": [
                            {
                                "id": "{{create-quantity.body@$.data.id}}",
                                "type": "quantity--standard",
                            },
                        ],
                    },
                },
            },
        }

        new_log = Subrequest(
            action=Action.create,
            requestId="create-log",
            waitFor=["create-quantity"],
            endpoint="api/log/harvest",
            body=log,
        )

        blueprints = [new_quantity, new_log]
        if new_unit:
            blueprints.insert(0, new_unit)
        blueprint = SubrequestsBlueprint.parse_obj(blueprints)
        response = self.farmos_client.subrequests.send(blueprint, format=Format.json)

        log = json.loads(response["create-log#body{0}"]["body"])

        if self.app.is_farmos_mirror():
            if new_unit:
                unit = json.loads(response["create-unit"]["body"])
                self.app.auto_sync_from_farmos(
                    unit["data"], "Unit", client=self.farmos_client
                )
            quantity = json.loads(response["create-quantity"]["body"])
            self.app.auto_sync_from_farmos(
                quantity["data"], "StandardQuantity", client=self.farmos_client
            )
            self.app.auto_sync_from_farmos(
                log["data"], "HarvestLog", client=self.farmos_client
            )

        return log

    def save_to_wuttafarm(self, form):
        model = self.app.model
        session = self.Session()
        data = form.validated

        asset = (
            session.query(model.Asset)
            .filter(model.Asset.farmos_uuid == data["asset"])
            .one()
        )

        # TODO: make this configurable?
        unit_name = self.unit_name

        new_unit = False
        unit = session.query(model.Unit).filter(model.Unit.name == unit_name).first()
        if not unit:
            unit = model.Unit(name=unit_name)
            session.add(unit)
            new_unit = True

        quantity = model.StandardQuantity(
            quantity_type_id="standard",
            measure_id="count",
            value_numerator=data["count"],
            value_denominator=1,
            units=unit,
        )
        session.add(quantity)

        log = model.HarvestLog(
            log_type="harvest",
            message=f"Collected {data['count']} {unit_name}",
            timestamp=self.app.make_utc(data["timestamp"]),
            notes=data["notes"] or None,
            quick="eggs",
            status="done",
        )
        session.add(log)
        log.assets.append(asset)
        log.quantities.append(quantity.quantity)
        log.owners.append(self.request.user)
        session.flush()

        if self.app.is_farmos_mirror():
            if new_unit:
                self.app.auto_sync_to_farmos(unit, client=self.farmos_client)
            self.app.auto_sync_to_farmos(quantity, client=self.farmos_client)
            self.app.auto_sync_to_farmos(log, client=self.farmos_client)

        return log

    def redirect_after_save(self, log):
        model = self.app.model

        if isinstance(log, model.HarvestLog):
            return self.redirect(
                self.request.route_url("logs_harvest.view", uuid=log.uuid)
            )

        return self.redirect(
            self.request.route_url("farmos_logs_harvest.view", uuid=log["data"]["id"])
        )


def includeme(config):
    EggsQuickForm.defaults(config)
