<?php

    namespace Icing\ORM;

    use Cake\Datasource\Exception\RecordNotFoundException;
    use Cake\Datasource\RepositoryInterface;
    use Cake\ORM\Association\BelongsTo;

    trait LazyLoadEntityTrait
    {

        use \JeremyHarris\LazyLoad\ORM\LazyLoadEntityTrait;

        protected function _lazyLoad($property)
        {
            // check if the property has been unset at some point
            if (in_array($property, $this->_unsetProperties)) {
                return null;
            }

            // check if the property was set as null to begin with
            if (array_key_exists($property, $this->_fields)) {
                return $this->_fields[$property];
            }


            $repository = $this->_repository();
            if (!($repository instanceof RepositoryInterface)) {
                return null;
            }

            $association = $repository->associations()->getByProperty($property);
            if ($association === null) {
                return null;
            }

            if ($association instanceof BelongsTo) {

                $foreignKeys = (array)$association->getForeignKey();

                $isMissingBelongsToFK = c($foreignKeys)->some(fn($field) => !isset($this->_fields[$field]));
                if ($isMissingBelongsToFK) {
                    return null;
                }

                $bindingKeys = (array)$association->getBindingKey();
                $keys        = array_combine($foreignKeys, $bindingKeys);

                if (!$keys) {
                    return null;
                }

                $query = $association->find();
                foreach ($keys as $foreignKey => $bindingKey) {
                    $query->where([$association->aliasField($bindingKey) => $this->_fields[$foreignKey]]);
                }

                try {
                    $this->set($property, $query->firstOrFail());
                    return $this->_fields[$property] ?? null;
                } catch (RecordNotFoundException $e) {
                    return null;
                }
            } else {

                $isMissingPK = c($association->getPrimaryKey())->some(fn($field) => !isset($this->_fields[$field]));
                if ($isMissingPK) {
                    return null;
                }

                $repository->loadInto($this, [$association->getName()]);
            }

            // check if the association didn't exist and therefore didn't load
            if (!isset($this->_fields[$property])) {
                return null;
            }

            return $this->_fields[$property];

        }


    }
