package router

import (
	"fmt"
	"time"

	"github.com/labstack/echo/v5"
	"github.com/pocketbase/pocketbase/apis"
	"github.com/pocketbase/pocketbase/core"
	"github.com/pocketbase/pocketbase/forms"
	"github.com/pocketbase/pocketbase/models"
)

const timezone = "Europe/Moscow"

func (r *RouterContainer) bootstrapTransactionRoute() {
	r.PB.OnBeforeServe().Add(func(e *core.ServeEvent) error {
		e.Router.POST("/transaction", func(c echo.Context) error {
			requestData := struct {
				Phone                    string `json:"phone"`
				Tx                       string `json:"tx" `
				TxBuyType                string `json:"buy"`
				TxSellType               string `json:"sell"`
				TxBuyDate                string `json:"buy_date"`
				TxSellDate               string `json:"sell_date"`
				Feedback                 string `json:"feedback"`
				EvergrowQuantityPurchase string `json:"evergrow_quantity_purchase"`
				EvergrowQuantitySale     string `json:"evergrow_quantity_sale"`
				DistributorName          string `json:"distributor_name"`
			}{}
			if err := c.Bind(&requestData); err != nil {
				return apis.NewBadRequestError("Failed to read request data", err)
			}

			initiatorRecord, err := r.PB.Dao().FindFirstRecordByData("users", "phone", requestData.Phone)
			if err != nil {
				return apis.NewNotFoundError("Initiator not registered", err)
			}

			txCollection, err := r.PB.Dao().FindCollectionByNameOrId("transactions")
			if err != nil {
				return err
			}

			txRecord := models.NewRecord(txCollection)
			txForm := forms.NewRecordUpsert(r.PB, txRecord)

			txData := map[string]any{
				"initiator": initiatorRecord.Id,
				"tx_type":   requestData.Tx,
				"feedback":  requestData.Feedback,
				"completed": false,
			}

			if requestData.Tx == "buy" {
				counterpartyRecord, err := r.PB.Dao().FindFirstRecordByData("users", "phone", requestData.TxBuyType)
				if err != nil {
					return apis.NewNotFoundError("Counterparty not registered", err)
				}

				if counterpartyRecord.GetString("participant_type") != "distributor" {
					return apis.NewNotFoundError("Counterparty is not registered as a distributor", err)
				}

				distributorRecord, err := r.PB.Dao().FindFirstRecordByData("distributor_base", "user", counterpartyRecord.Id)
				if err != nil {
					return apis.NewNotFoundError("Counterparty not found in distributors record", err)
				}

				if distributorRecord.GetString("distributor_name") != requestData.DistributorName {
					return apis.NewNotFoundError(fmt.Sprintf("Counterparty is not registered to %s", requestData.DistributorName), err)
				}

				incorrectDate, err := isFutureDate(requestData.TxBuyDate)
				if err != nil {
					return apis.NewBadRequestError("Incorrect date format", err)
				}
				if incorrectDate {
					return apis.NewBadRequestError("Date cannot be in the future", err)
				}

				txData["evergrow_quantity"] = requestData.EvergrowQuantityPurchase
				txData["distributor_name"] = requestData.DistributorName
				txData["counterparty"] = counterpartyRecord.Id
				txData["tx_date"] = requestData.TxBuyDate
			}

			if requestData.Tx == "sell" {
				counterpartyRecord, err := r.PB.Dao().FindFirstRecordByData("users", "phone", requestData.TxSellType)
				if err != nil {
					return apis.NewNotFoundError("", err)
				}

				if counterpartyRecord.GetString("participant_type") != "farmer" {
					return apis.NewNotFoundError("Counterparty is not registered as a farmer", err)
				}

				incorrectDate, err := isFutureDate(requestData.TxSellDate)
				if err != nil {
					return apis.NewBadRequestError("Incorrect date format", err)
				}
				if incorrectDate {
					return apis.NewBadRequestError("Date cannot be in the future", err)
				}

				txData["evergrow_quantity"] = requestData.EvergrowQuantitySale
				txData["counterparty"] = counterpartyRecord.Id
				txData["tx_date"] = requestData.TxSellDate
			}

			txForm.LoadData(txData)

			if err := txForm.Submit(); err != nil {
				return apis.NewBadRequestError("Failed to submit tx details", err)
			}

			c.JSON(200, map[string]any{"ok": "true"})

			return nil
		})

		return nil
	})
}

func isFutureDate(inputDate string) (bool, error) {
	parsedDate, err := time.Parse("2006-01-02", inputDate)
	if err != nil {
		return false, err
	}

	location, err := time.LoadLocation(timezone)
	if err != nil {
		return false, err
	}

	parsedDate = parsedDate.In(location)

	currentDate := time.Now().In(location)
	fmt.Println(currentDate)

	return parsedDate.After(currentDate), nil
}