<?php

namespace PloverCRM\Core\Api\V1;

use PloverCRM\Core\Api\AbstractEndpoint;
use PloverCRM\Common\Permissions;
use PloverCRM\Common\RoleManager;
use WP_REST_Request;

/**
 * Bulk Operations Endpoint
 * 
 * POST /wp-json/plover-crm/v1/bulk
 */
class BulkEndpoint extends AbstractEndpoint
{
    public function getRoute(): string
    {
        return '/bulk';
    }

    public function getMethod()
    {
        return 'POST';
    }

    public function handle(WP_REST_Request $request)
    {
        $crm = $this->container->get('crm');

        if (!$crm->isAvailable()) {
            return $this->error('CRM not available', 503);
        }

        $data = $request->get_json_params();
        $action = $data['action'] ?? '';
        $contact_ids = $data['contact_ids'] ?? [];

        if (empty($action) || empty($contact_ids) || !is_array($contact_ids)) {
            return $this->error('Action and contact_ids are required', 400);
        }

        switch ($action) {
            case 'delete':
                return $this->bulkDelete($crm, $contact_ids);

            case 'update_status':
                // Status only available for FluentCRM
                if ($crm->getName() !== 'FluentCRM') {
                    return $this->error('Status not available for this CRM', 400);
                }
                return $this->bulkUpdateStatus($crm, $contact_ids, $data['status'] ?? '');

            case 'add_tags':
                return $this->bulkAddTags($crm, $contact_ids, $data['tags'] ?? []);

            case 'remove_tags':
                return $this->bulkRemoveTags($crm, $contact_ids, $data['tags'] ?? []);

            case 'add_lists':
                return $this->bulkAddLists($crm, $contact_ids, $data['lists'] ?? []);

            case 'remove_lists':
                return $this->bulkRemoveLists($crm, $contact_ids, $data['lists'] ?? []);

            case 'reassign':
                return $this->bulkReassign($crm, $contact_ids, $data['owner_id'] ?? null);

            default:
                return $this->error('Invalid action', 400);
        }
    }

    /**
     * Bulk delete contacts with ownership check
     */
    private function bulkDelete($crm, array $contact_ids)
    {
        // First check if user has delete permission at all
        if (!Permissions::canDeleteContacts()) {
            return $this->error('You do not have permission to delete contacts', 403, 'delete_permission_denied');
        }

        $deleted = 0;
        $failed = 0;
        $skipped = 0;

        foreach ($contact_ids as $id) {
            $contactId = intval($id);
            $ownerId = $crm->getContactOwner($contactId);

            // Check ownership-based delete permission
            if (!Permissions::canDeleteContact($ownerId)) {
                $skipped++;
                continue;
            }

            if ($crm->deleteContact($contactId)) {
                $deleted++;
            } else {
                $failed++;
            }
        }

        return $this->success([
            'deleted' => $deleted,
            'failed' => $failed,
            'skipped' => $skipped,
        ]);
    }

    /**
     * Bulk update status with ownership check
     */
    private function bulkUpdateStatus($crm, array $contact_ids, string $status)
    {
        if (empty($status)) {
            return $this->error('Status is required', 400);
        }

        $updated = 0;
        $failed = 0;
        $skipped = 0;

        foreach ($contact_ids as $id) {
            $contactId = intval($id);
            $ownerId = $crm->getContactOwner($contactId);

            // Check ownership-based update permission
            if (!Permissions::canUpdateContact($ownerId)) {
                $skipped++;
                continue;
            }

            $contact = $crm->getContact($contactId);
            if ($contact) {
                // Only pass necessary fields for update
                $updateData = [
                    'id' => $contact['id'],
                    'email' => $contact['email'],
                    'status' => $status
                ];
                if ($crm->createOrUpdateContact($updateData)) {
                    $updated++;
                } else {
                    $failed++;
                }
            } else {
                $failed++;
            }
        }

        return $this->success([
            'updated' => $updated,
            'failed' => $failed,
            'skipped' => $skipped,
        ]);
    }

    /**
     * Bulk add tags with ownership check
     */
    private function bulkAddTags($crm, array $contact_ids, array $tags)
    {
        if (empty($tags)) {
            return $this->error('Tags are required', 400);
        }

        $updated = 0;
        $failed = 0;
        $skipped = 0;

        foreach ($contact_ids as $id) {
            $contactId = intval($id);
            $ownerId = $crm->getContactOwner($contactId);

            // Check ownership-based update permission
            if (!Permissions::canUpdateContact($ownerId)) {
                $skipped++;
                continue;
            }

            if ($this->addTagsToContact($crm, $contactId, $tags)) {
                $updated++;
            } else {
                $failed++;
            }
        }

        return $this->success([
            'updated' => $updated,
            'failed' => $failed,
            'skipped' => $skipped,
        ]);
    }

    /**
     * Bulk remove tags with ownership check
     */
    private function bulkRemoveTags($crm, array $contact_ids, array $tags)
    {
        if (empty($tags)) {
            return $this->error('Tags are required', 400);
        }

        $updated = 0;
        $failed = 0;
        $skipped = 0;

        foreach ($contact_ids as $id) {
            $contactId = intval($id);
            $ownerId = $crm->getContactOwner($contactId);

            if (!Permissions::canUpdateContact($ownerId)) {
                $skipped++;
                continue;
            }

            if ($this->removeTagsFromContact($crm, $contactId, $tags)) {
                $updated++;
            } else {
                $failed++;
            }
        }

        return $this->success([
            'updated' => $updated,
            'failed' => $failed,
            'skipped' => $skipped,
        ]);
    }

    /**
     * Bulk add lists with ownership check
     */
    private function bulkAddLists($crm, array $contact_ids, array $lists)
    {
        if (empty($lists)) {
            return $this->error('Lists are required', 400);
        }

        $updated = 0;
        $failed = 0;
        $skipped = 0;

        foreach ($contact_ids as $id) {
            $contactId = intval($id);
            $ownerId = $crm->getContactOwner($contactId);

            if (!Permissions::canUpdateContact($ownerId)) {
                $skipped++;
                continue;
            }

            if ($this->addListsToContact($crm, $contactId, $lists)) {
                $updated++;
            } else {
                $failed++;
            }
        }

        return $this->success([
            'updated' => $updated,
            'failed' => $failed,
            'skipped' => $skipped,
        ]);
    }

    /**
     * Bulk remove lists with ownership check
     */
    private function bulkRemoveLists($crm, array $contact_ids, array $lists)
    {
        if (empty($lists)) {
            return $this->error('Lists are required', 400);
        }

        $updated = 0;
        $failed = 0;
        $skipped = 0;

        foreach ($contact_ids as $id) {
            $contactId = intval($id);
            $ownerId = $crm->getContactOwner($contactId);

            if (!Permissions::canUpdateContact($ownerId)) {
                $skipped++;
                continue;
            }

            if ($this->removeListsFromContact($crm, $contactId, $lists)) {
                $updated++;
            } else {
                $failed++;
            }
        }

        return $this->success([
            'updated' => $updated,
            'failed' => $failed,
            'skipped' => $skipped,
        ]);
    }

    /**
     * Bulk reassign contacts
     */
    private function bulkReassign($crm, array $contact_ids, $newOwnerId)
    {
        $user = wp_get_current_user();

        // Validate new owner
        if ($newOwnerId !== null) {
            $newOwnerId = intval($newOwnerId);
            if (!RoleManager::userHasAccess($newOwnerId)) {
                return $this->error('The specified user does not have CRM access', 400, 'invalid_owner');
            }
        }

        $reassigned = 0;
        $failed = 0;
        $skipped = 0;

        foreach ($contact_ids as $id) {
            $contactId = intval($id);
            $ownerId = $crm->getContactOwner($contactId);

            // Check if user can reassign this contact
            if (!Permissions::canReassignContact($ownerId)) {
                $skipped++;
                continue;
            }

            if ($crm->setContactOwner($contactId, $newOwnerId)) {
                $reassigned++;
            } else {
                $failed++;
            }
        }

        return $this->success([
            'reassigned' => $reassigned,
            'failed' => $failed,
            'skipped' => $skipped,
        ]);
    }

    /**
     * Add tags to contact
     */
    private function addTagsToContact($crm, int $contact_id, array $tags): bool
    {
        if ($crm->getSelectedProviderId() === 'native_crm') {
            $existing_tags = wp_get_object_terms($contact_id, 'plover_crm_tag', ['fields' => 'slugs']);
            $all_tags = array_unique(array_merge($existing_tags, $tags));
            return !is_wp_error(wp_set_object_terms($contact_id, $all_tags, 'plover_crm_tag'));
        }

        if ($crm->getName() === 'FluentCRM') {
            try {
                $subscriber = \FluentCrmApi('contacts')->getContact($contact_id);
                if ($subscriber) {
                    $subscriber->attachTags($tags);
                    return true;
                }
            } catch (\Exception $e) {
                return false;
            }
        }

        return false;
    }

    /**
     * Remove tags from contact
     */
    private function removeTagsFromContact($crm, int $contact_id, array $tags): bool
    {
        if ($crm->getSelectedProviderId() === 'native_crm') {
            $existing_tags = wp_get_object_terms($contact_id, 'plover_crm_tag', ['fields' => 'slugs']);
            $remaining_tags = array_diff($existing_tags, $tags);
            return !is_wp_error(wp_set_object_terms($contact_id, $remaining_tags, 'plover_crm_tag'));
        }

        if ($crm->getName() === 'FluentCRM') {
            try {
                $subscriber = \FluentCrmApi('contacts')->getContact($contact_id);
                if ($subscriber) {
                    $subscriber->detachTags($tags);
                    return true;
                }
            } catch (\Exception $e) {
                return false;
            }
        }

        return false;
    }

    /**
     * Add lists to contact
     */
    private function addListsToContact($crm, int $contact_id, array $lists): bool
    {
        if ($crm->getSelectedProviderId() === 'native_crm') {
            $existing_lists = wp_get_object_terms($contact_id, 'plover_crm_list', ['fields' => 'slugs']);
            $all_lists = array_unique(array_merge($existing_lists, $lists));
            return !is_wp_error(wp_set_object_terms($contact_id, $all_lists, 'plover_crm_list'));
        }

        if ($crm->getName() === 'FluentCRM') {
            try {
                $subscriber = \FluentCrmApi('contacts')->getContact($contact_id);
                if ($subscriber) {
                    $subscriber->attachLists($lists);
                    return true;
                }
            } catch (\Exception $e) {
                return false;
            }
        }

        return false;
    }

    /**
     * Remove lists from contact
     */
    private function removeListsFromContact($crm, int $contact_id, array $lists): bool
    {
        if ($crm->getSelectedProviderId() === 'native_crm') {
            $existing_lists = wp_get_object_terms($contact_id, 'plover_crm_list', ['fields' => 'slugs']);
            $remaining_lists = array_diff($existing_lists, $lists);
            return !is_wp_error(wp_set_object_terms($contact_id, $remaining_lists, 'plover_crm_list'));
        }

        if ($crm->getName() === 'FluentCRM') {
            try {
                $subscriber = \FluentCrmApi('contacts')->getContact($contact_id);
                if ($subscriber) {
                    $subscriber->detachLists($lists);
                    return true;
                }
            } catch (\Exception $e) {
                return false;
            }
        }

        return false;
    }
}
