<?php

namespace Vendtics\App\Repositories;

defined( "ABSPATH" ) || exit;

use Vendtics\App\Models\Tag;
use Vendtics\App\Models\ListModel;
use Vendtics\App\Models\EntityList;
use Vendtics\App\Models\EntityTag;
use Vendtics\WpMVC\Database\Query\Builder;
use Vendtics\WpMVC\Exceptions\Exception;

trait TagListEntityRepository {
    public function bulk_assign_tags( Builder $entry_query, array $ids, array $tag_ids ) {
        $ids     = array_unique( map_deep( $ids , "intval" ) );
        $tag_ids = array_unique( map_deep( $tag_ids , "intval" ) );

        $total_entries = $entry_query->where_in( 'id', $ids )->count();

        if ( count( $ids ) !== $total_entries ) {
            throw new Exception( esc_html__( "Some entries are missing, Please, refresh the page and try again", 'vendtics' ) );
        }
        
        $total_tags = Tag::query()->where_in( 'id', $tag_ids )->count();

        if ( count( $tag_ids ) !== $total_tags ) {
            throw new Exception( esc_html__( "Some tags are missing, Please, refresh the page and try again", 'vendtics' ) );
        }

        $this->bulk_unassign_tags( $ids, $tag_ids );

        $entry_tags = [];

        foreach ( $ids as $entity_id ) {
            foreach ( $tag_ids as $tag_id ) {
                $entry_tags[] = [
                    'entity_id'   => $entity_id,
                    'tag_id'      => $tag_id,
                    'entity_type' => $this->get_entity_type()
                ];
            }
        }
        return EntityTag::query()->insert( $entry_tags );
    }

    public function bulk_unassign_tags( array $ids, array $tag_ids ) {
        return EntityTag::query()->where( 'entity_type', $this->get_entity_type() )->where_in( 'entity_id', $ids )->where_in( 'tag_id', $tag_ids )->delete();
    }

    public function bulk_assign_lists( Builder $entry_query, array $ids, array $list_ids ) {
        $ids      = array_unique( map_deep( $ids , "intval" ) );
        $list_ids = array_unique( map_deep( $list_ids , "intval" ) );

        $total_entries = $entry_query->where_in( 'id', $ids )->count();

        if ( count( $ids ) !== $total_entries ) {
            throw new Exception( esc_html__( "Some entries are missing, Please, refresh the page and try again", 'vendtics' ) );
        }
        
        $total_lists = ListModel::query()->where_in( 'id', $list_ids )->count();

        if ( count( $list_ids ) !== $total_lists ) {
            throw new Exception( esc_html__( "Some lists are missing, Please, refresh the page and try again", 'vendtics' ) );
        }

        $this->bulk_unassign_lists( $ids, $list_ids );

        $entry_list = [];

        foreach ( $ids as $entity_id ) {
            foreach ( $list_ids as $list_id ) {
                $entry_list[] = [
                    'entity_id'   => $entity_id,
                    'list_id'     => $list_id,
                    'entity_type' => $this->get_entity_type()
                ];
            }
        }

        return EntityList::query()->insert( $entry_list );
    }

    public function bulk_unassign_lists( array $ids, array $list_ids ) {
        return EntityList::query()->where( 'entity_type', $this->get_entity_type() )->where_in( 'entity_id', $ids )->where_in( 'list_id', $list_ids )->delete();
    }

    public function assign_tags( int $entity_id, ?array $tags ) {
        if ( empty( $tags ) ) {
            return false;
        }

        $total_tags = Tag::query()->where_in( 'id', map_deep( $tags, 'intval' ) )->count();

        if ( count( $tags ) !== $total_tags ) {
            return false;
        }

        $entity_type = $this->get_entity_type();

        return EntityTag::query()->insert(
            array_map(
                function( $tag_id ) use( $entity_id, $entity_type ){
                    return compact( 'entity_id', 'tag_id', 'entity_type' );
                }, $tags
            )
        );
    }

    public function update_tags( int $entity_id, ?array $tags ) {
        EntityTag::query()->where( 'entity_type', $this->get_entity_type() )->where( 'entity_id', $entity_id )->delete();
        return $this->assign_tags( $entity_id, $tags );
    }

    public function assign_lists( int $entity_id, ?array $lists ) {
        if ( empty( $lists ) ) {
            return false;
        }

        $total_lists = ListModel::query()->where_in( 'id', map_deep( $lists, 'intval' ) )->count();

        if ( count( $lists ) !== $total_lists ) {
            return false;
        }

        $entity_type = $this->get_entity_type();

        return EntityList::query()->insert(
            array_map(
                function( $list_id ) use( $entity_id, $entity_type ){
                    return compact( 'entity_id', 'list_id', 'entity_type' );
                }, $lists
            )
        );
    }

    public function update_lists( int $entity_id, ?array $lists ) {
        EntityList::query()->where( 'entity_type', $this->get_entity_type() )->where( 'entity_id', $entity_id )->delete();
        return $this->assign_lists( $entity_id, $lists );
    }
}