<?php

namespace FluentCrm\App\Http\Controllers;

use FluentCrm\App\Models\Tag;
use FluentCrm\App\Services\Helper;
use FluentCrm\Framework\Support\Arr;
use FluentCrm\Framework\Http\Request\Request;

/**
 *  TagsController - REST API Handler Class
 *
 *  REST API Handler
 *
 * @package FluentCrm\App\Http
 *
 * @version 1.0.0
 */
class TagsController extends Controller
{
    /**
     * Get all of the tags
     * @param \FluentCrm\Framework\Http\Request\Request $request
     * @return \WP_REST_Response | array
     */
    public function index(Request $request)
    {
        $order = [
            'by'    => $request->getSafe('sort_by', 'sanitize_sql_orderby', 'id'),
            'order' => $request->getSafe('sort_order', 'sanitize_sql_orderby', 'DESC')
        ];

        $tags = Tag::orderBy($order['by'], $order['order'])
            ->searchBy($request->getSafe('search'))
            ->paginate();

        if (!$request->get('exclude_counts')) {
            // One grouped pivot-join count for the whole page instead of a
            // JOIN + COUNT query per tag.
            $tagIds = [];
            foreach ($tags as $tag) {
                $tagIds[] = $tag->id;
            }

            $counts = [];
            if ($tagIds) {
                $countRows = fluentCrmDb()->table('fc_subscriber_pivot')
                    ->where('fc_subscriber_pivot.object_type', 'FluentCrm\App\Models\Tag')
                    ->whereIn('fc_subscriber_pivot.object_id', $tagIds)
                    ->join('fc_subscribers', 'fc_subscribers.id', '=', 'fc_subscriber_pivot.subscriber_id')
                    ->where('fc_subscribers.status', 'subscribed')
                    ->groupBy('fc_subscriber_pivot.object_id')
                    ->select([
                        'fc_subscriber_pivot.object_id',
                        fluentCrmDb()->raw('COUNT(*) as total')
                    ])
                    ->get();

                foreach ($countRows as $countRow) {
                    $counts[$countRow->object_id] = (int)$countRow->total;
                }
            }

            foreach ($tags as $tag) {
                $tag->subscribersCount = isset($counts[$tag->id]) ? $counts[$tag->id] : 0;
            }
        }

        $data = [
            'tags' => $tags
        ];

        if ($request->get('all_tags')) {
            $allTags = Tag::get();
            $formattedTags = [];
            foreach ($allTags as $tag) {
                $formattedTags[] = [
                    'id'          => strval($tag->id),
                    'title'       => $tag->title,
                    'slug'        => $tag->slug,
                    'description' => $tag->description
                ];
            }
            $data['all_tags'] = $formattedTags;
        }

        return $data;
    }

    /**
     * Find a tag.
     */
    public function find($id)
    {
        return $this->send([
            'tag' => Tag::find($id)
        ]);
    }

    /**
     * Store a tag.
     * @param \FluentCrm\Framework\Http\Request\Request $request
     * @return \WP_REST_Response
     */
    public function create(Request $request)
    {
        $allData = $request->all();

        if (empty($allData['slug'])) {
            $allData['slug'] = Helper::slugify($allData['title']);
        } else {
            $allData['slug'] = sanitize_text_field($allData['slug']);
        }

        $allData = $this->validate($allData, [
            'title' => 'required',
            'slug'  => "required|unique:fc_tags,slug"
        ]);

        $tag = Tag::create([
            'title'       => sanitize_text_field($allData['title']),
            'slug'        => $allData['slug'],
            'description' => sanitize_textarea_field(Arr::get($allData, 'description'))
        ]);

        do_action('fluentcrm_tag_created', $tag->id);

        do_action('fluent_crm/tag_created', $tag);

        return $this->sendSuccess([
            'lists'   => $tag,
            'item'    => $tag,
            'message' => __('Successfully saved the tag.', 'fluent-crm')
        ]);
    }

    /**
     * Store a tag.
     * @param \FluentCrm\Framework\Http\Request\Request $request
     * @param $id int Tag ID
     * @return \WP_REST_Response
     */
    public function store(Request $request, $id)
    {
        $allData = $this->validate($request->all(), [
            'title' => 'required'
        ]);

        if (empty($allData['slug'])) {
            $allData['slug'] = Helper::slugify($allData['title']);
        }

        if ($id == 0 && $request->get('update_by') == 'slug' && !empty($allData['slug'])) {

            $tag = Tag::where('slug', $allData['slug'])->first();
            if (!$tag) {
                return $this->sendError([
                    'message' => __('Tag could not be found', 'fluent-crm')
                ]);
            }
            $id = $tag->id;
        } else {
            $tag = Tag::findOrFail($id);
            if (empty($allData['slug'])) {
                $allData['slug'] = $tag->slug;
            }
        }

        if (Tag::where('slug', $allData['slug'])->where('id', '!=', $id)->first()) {
            return $this->sendError([
                'message' => __('Provided slug already exists in another tag', 'fluent-crm')
            ]);
        }

        $tag = Tag::where('id', $id)->update([
            'title'       => sanitize_text_field($allData['title']),
            'slug'        => $allData['slug'],
            'description' => sanitize_textarea_field(Arr::get($allData, 'description')),
        ]);

        do_action('fluentcrm_tag_updated', $id);

        do_action('fluent_crm/tag_updated', $tag);

        return $this->sendSuccess([
            'lists'   => $tag,
            'message' => __('Successfully saved the tag.', 'fluent-crm')
        ]);
    }

    /**
     * Store a tag.
     */
    public function storeBulk()
    {
        $tags = $this->request->get('tags', []);

        if (!$tags) {
            $tags = $this->request->get('items', []);
        }

        $createdIds = [];

        foreach ($tags as $tag) {
            if (empty($tag['title'])) {
                continue;
            }

            if (empty($tag['slug'])) {
                $tag['slug'] = Helper::slugify($tag['title']);
            }

            $tag = Tag::updateOrCreate(
                ['slug' => sanitize_title($tag['slug'], 'display')],
                ['title' => sanitize_text_field($tag['title'])]
            );

            $createdIds[] = $tag->id;

            if ($tag->wasRecentlyCreated) {
                do_action('fluentcrm_tag_created', $tag->id);
                do_action('fluent_crm/tag_created', $tag);
            } else {
                do_action('fluentcrm_tag_updated', $tag->id);
                do_action('fluent_crm/tag_updated', $tag);
            }

        }

        return $this->sendSuccess([
            'message' => __('Successfully saved the tags.', 'fluent-crm'),
            'ids'     => $createdIds
        ]);
    }

    /**
     * Delete a tag by id
     *
     * @param \FluentCrm\Framework\Http\Request\Request $request
     * @param $tagId
     * @return \WP_REST_Response $object
     */
    public function remove(Request $request, $tagId)
    {
        $tag = Tag::find($tagId);

        if (!$tag) {
            return $this->sendError([
                'message' => __('Tag not found', 'fluent-crm')
            ], 404);
        }

        $tag->delete();

        do_action('fluentcrm_tag_deleted', $tagId);
        do_action('fluent_crm/tag_deleted', $tagId);

        return $this->sendSuccess([
            'message' => __('Successfully removed the tag.', 'fluent-crm')
        ]);
    }


    public function handleBulkAction(Request $request)
    {
        $tagIds = array_map('intval', (array)$request->get('tagIds', []));

        $tagIds = array_unique(array_filter($tagIds));

        if ($tagIds) {
            foreach ($tagIds as $tagId) {
                Tag::where('id', $tagId)->delete();
                do_action('fluentcrm_tag_deleted', $tagId);

                do_action('fluent_crm/tag_deleted', $tagId);
            }
        }

        return $this->sendSuccess([
            'message' => __('Selected Tags have been removed permanently', 'fluent-crm'),
        ]);

    }
}
