<?php

// src/Controller/ProductController.php

namespace App\Service;

use Doctrine\DBAL\DBALException;
use Doctrine\ORM\ORMException;
use PDOException;
use Exception;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\Uid\Uuid;
use Doctrine\DBAL\Connection;
use App\Entity\Location;
use League\Csv\Reader;

//use App\Utils\StringTools;

/**
 * Members
 *
 * Data class for interacting with Member data from the DB
 */
class HandleLocations
{
    private $session;
    private $entityManager;
    private $conn;
    private $limit = 9;

    public function __construct(
        Connection $connection,
        EntityManagerInterface $entityManager,
        RequestStack $requestStack
    ) {
        $this->connection    = $connection;
        $this->entityManager = $entityManager;
        $this->session       = $requestStack->getSession();
    }

    public function searchLocations(string $terms)
    {
        $errorMessage = null;
        $response     = null;
        //$utils        = new StringTools();
        //$term = $utils->removeCommonWords($terms);
        $rawSearch = $terms;
        $terms     = str_replace(",", "", $terms);
        $terms     = str_replace(" ", "|", $terms);

        try {
            $search = $this->connection->fetchAllAssociative("SELECT * FROM searchlocations('$terms')");
            $active = [];
            foreach ($search as $item) {
                if ($item["active"] == true) {
                    array_push($active, $item);
                }
            }
        } catch (PDOException $error) {
            $errorMessage = $error->getMessage();
        } catch (DBALException $error) {
            $errorMessage = $error->getMessage();
        } catch (ORMException $error) {
            $errorMessage = $error->getMessage();
        } catch (Exception $error) {
            $errorMessage = $error->getMessage();
        } catch (SyntaxErrorException $error) {
            $errorMessage = $error->getMessage();
        }

        if ($errorMessage != null) {
            $response = [
                "status"  => false,
                "message" => $errorMessage,
            ];
        } else {
            $response = [
                "status"  => true,
                "message" => "Good Reqeust",
                "items"   => $active,
                "terms"   => $rawSearch,
            ];
        }

        return $response;
    }

    public function getActiveLocations()
    {
        $listings  = $this->entityManager->getRepository(Location::class);
        $locations = $listings->findBy(["active" => true]);

        return $locations;
    }

    public function getLocationByUUID(string $uuid)
    {
        return $this->entityManager->getRepository(Location::class)->findBy(["uuid" => $uuid]);
    }

    public function getLocationsPage(int $page, string $active = "all")
    {
        $locations = $this->entityManager->getRepository(Location::class);
        if ($active == "true" || $active == "false") {
            $list = $locations->findBy(["active" => $active], ["id" => "ASC"]);
        } else {
            $list = $locations->findBy([], ["id" => "ASC"]);
        }

        $count      = ceil(count($list) / $this->limit);
        $totalCount = count($list);

        $shelf = [];
        $range = $page * $this->limit - $this->limit;
        for ($i = 0; $i <= $this->limit; $i++) {
            try {
                array_push($shelf, $list[$i + $range]);
            } catch (Exception $error) {
            }
        }

        return [
            "locations"      => $shelf,
            "total"          => $count,
            "totalLocations" => $totalCount,
        ];
    }

    /**
     * Add new location to db
     *
     * @param Request $request object containing posted data
     * @return JSON
     */
    public function modifyLocation($request, $memberId, $action, $uuid = 0)
    {
        $errorMessage = null;
        if ($action == "add") {
            $location = new Location();
        } else {
            $location = $this->entityManager->getRepository(Location::class)->findOneBy(["uuid" => $uuid]);
        }

        //submitted values
        $name = $request->request->get("loc_name");
        $location->setName($name);
        $url = $request->request->get("loc_url");
        $location->setUrl($url);
        $desc = $request->request->get("loc_desc");
        $location->setDescription($desc);
        $tags = $request->request->get("loc_tags");
        $location->setTags($tags);
        $rating = $request->request->get("rating");
        $location->setRating($rating);
        //get images
        $files = $request->files->get("loc_examples");
        if (!empty($files)) {
            $examples = [];
            for ($i = 0; $i < count($files); $i++) {
                $path = $files[$i]->getClientOriginalName();
                array_push($examples, ["image_index" => $i, "path" => urlencode($path)]);
            }
            $location->setImages($examples);
        }

        //set defaults
        $location->setUpdatedAt(new \DateTimeImmutable());
        if ($action == "add") {
            $location->setUuid(Uuid::v4());
            $location->setActive(false);
            $location->setCreatedAt(new \DateTimeImmutable());
            $location->setAddedBy($memberId);
            $this->entityManager->persist($location);
        } else {
            $active = ($request->request->get("active") == "true" ? true : false);
            $location->setActive($active);
        }

        try {
            $this->entityManager->flush();
        } catch (PDOException $error) {
            $errorMessage = $error->getMessage();
        } catch (DBALException $error) {
            $errorMessage = $error->getMessage();
        } catch (ORMException $error) {
            $errorMessage = $error->getMessage();
        } catch (Exception $error) {
            $errorMessage = $error->getMessage();
        } catch (SyntaxErrorException $e) {
            $errorMessage = $error->getMessage();
        }
        // return result status
        if ($errorMessage == null) {
            $message = "";
            if ($action == "add") {
                $message = "New location added. Woohoo!";
            } else {
                $message = "Location Updated! Water break!";
            }
            return $response = [
                "status"  => true,
                "message" => $message,
            ];
        } else {
            return $response = ["status" => false, "message" => $errorMessage];
        }
    }

    /**
     * Add new location to db
     *
     * @param Request $file object containing posted data
     * @return Object
     */
    public function addMultipleLocations($file, $memberId)
    {
        //read csv
        $csv = Reader::createFromPath($file, "r");
        $csv->setHeaderOffset(0);
        $records      = $csv->getRecords();
        $recordCount  = count($csv);
        $duplicates   = 0;
        $errorMessage = null;
        // Save image

        //extract data row by row

        //TODO: set name to lowercase for comparison
        foreach ($records as $offset => $row) {
            $name     = $row["Name"];
            $url      = $row["Url"];
            $images   = $row["Images"];
            $desc     = $row["Description"];
            $tags     = $row["Tags"];
            $ratings  = $row["Rating"];
            $imgs     = explode(',', $images);
            $examples = [];

            //check to see if location already exists
            $list  = $this->entityManager->getRepository(Location::class);
            $entry = $list->findOneBy(["name" => $name]);
            if ($entry) {
                ++$duplicates;
            } else {
                $errorMessage = null;
                $location     = new Location();

                $location->setName($name);
                $location->setUrl($url);
                $location->setDescription($desc);
                $location->setTags($tags);
                $location->setRating($ratings);

                //grab images, move them to dir and set image array
                foreach ($imgs as $key => $img) {
                    $imageName = uniqid() . ".jpg";
                    $path      = "../public/assets/images/examples/" . $imageName;
                    array_push($examples, ["image_index" => $key, "path" => urlencode($imageName)]);
                    file_put_contents($path, file_get_contents(trim($img)));
                }
                $location->setImages($examples);

                //set defaults
                $location->setUuid(Uuid::v4());
                $location->setActive(false);
                $location->setCreatedAt(new \DateTimeImmutable());
                $location->setUpdatedAt(new \DateTimeImmutable());
                $location->setAddedBy($memberId);

                $this->entityManager->persist($location);
            }
        }

        try {
            $this->entityManager->flush();
        } catch (PDOException $error) {
            $errorMessage = $error->getMessage();
        } catch (DBALException $error) {
            $errorMessage = $error->getMessage();
        } catch (ORMException $error) {
            $errorMessage = $error->getMessage();
        } catch (Exception $error) {
            $errorMessage = $error->getMessage();
        } catch (SyntaxErrorException $e) {
            $errorMessage = $error->getMessage();
        }

        if ($duplicates > 0) {
            $message = $duplicates . " of " . $recordCount . " location entries  were duplicates";
        } else {
            $message = "Locations Added. Nice Job!";
        }
        // return result status
        if ($errorMessage == null) {
            return $response = [
                "status"  => true,
                "message" => $message,
            ];
        } else {
            return $response = ["status" => false, "message" => $errorMessage];
        }
    }
}
