<?php

namespace PloverCRM\Core\CRM;

/**
 * CRM Provider Interface
 * 
 * Contract that all CRM providers must implement
 */
interface CRMProviderInterface
{
    /**
     * Check if the CRM provider is available/active
     * 
     * @return bool
     */
    public function isAvailable(): bool;

    /**
     * Get provider name
     * 
     * @return string
     */
    public function getName(): string;

    /**
     * Get a contact by ID
     * 
     * @param int $id Contact ID
     * @return array|null Contact data or null if not found
     */
    public function getContact(int $id): ?array;

    /**
     * Get a contact by email
     * 
     * @param string $email Contact email
     * @return array|null Contact data or null if not found
     */
    public function getContactByEmail(string $email): ?array;

    /**
     * Create or update a contact
     * 
     * @param array $data Contact data (must include 'email')
     * @return array|null Created/updated contact data or null on failure
     */
    public function createOrUpdateContact(array $data): ?array;

    /**
     * Get contact's custom field values
     * 
     * @param array $contact Contact data
     * @return array Custom field key-value pairs
     */
    public function getContactCustomFields(array $contact): array;

    /**
     * Get all custom fields definitions
     * 
     * @return array Array of custom field definitions
     */
    public function getAllCustomFields(): array;

    /**
     * Create or update custom fields
     * 
     * @param array $fields Array of field definitions
     * @return bool Success status
     */
    public function createOrUpdateCustomFields(array $fields): bool;

    /**
     * Get options for a specific custom field
     * 
     * @param string $slug Field slug
     * @return array Field options or empty array
     */
    public function getCustomFieldOptions(string $slug): array;

    /**
     * Get all lists
     * 
     * @return array Array of lists
     */
    public function getAllLists(): array;

    /**
     * Create a new list
     * 
     * @param array $data List data (title, slug, description)
     * @return array|null Created list or null on failure
     */
    public function createList(array $data): ?array;

    /**
     * Delete a list
     * 
     * @param int $id List ID
     * @return bool Success status
     */
    public function deleteList(int $id): bool;

    /**
     * Update a list
     * 
     * @param int $id List ID
     * @param array $data List data (title, slug, description)
     * @return array|null Updated list or null on failure
     */
    public function updateList(int $id, array $data): ?array;

    /**
     * Get lists for a specific contact
     * 
     * @param array $contact Contact data
     * @return array Array of lists
     */
    public function getContactLists(array $contact): array;

    /**
     * Get contact tags
     * 
     * @param array $contact Contact data
     * @return array Array of tags
     */
    public function getContactTags(array $contact): array;

    /**
     * Get all tags
     * 
     * @return array Array of tags
     */
    public function getAllTags(): array;

    /**
     * Create a new tag
     * 
     * @param array $data Tag data (title, slug, description)
     * @return array|null Created tag or null on failure
     */
    public function createTag(array $data): ?array;

    /**
     * Delete a tag
     * 
     * @param int $id Tag ID
     * @return bool Success status
     */
    public function deleteTag(int $id): bool;

    /**
     * Update a tag
     * 
     * @param int $id Tag ID
     * @param array $data Tag data (title, slug, description)
     * @return array|null Updated tag or null on failure
     */
    public function updateTag(int $id, array $data): ?array;

    /**
     * Get all contacts with pagination
     * 
     * @param array $args Query arguments (page, per_page, search)
     * @return array ['contacts' => array, 'total' => int]
     */
    public function getAllContacts(array $args = []): array;

    /**
     * Search contacts with advanced filters
     * 
     * @param array $args Search arguments:
     *   - query: Search term
     *   - page: Page number (default: 1)
     *   - per_page: Items per page (default: 20)
     *   - list_ids: Array of list IDs to filter by
     *   - tag_ids: Array of tag IDs to filter by
     *   - fields: Array of standard field names to search in
     *   - custom_fields: Array of custom field slugs to search in
     *   - search_mode: 'or' or 'and' (default: 'or')
     *   - statuses: Array of contact statuses to filter by
     *   - stages: Array of stage names to filter by (exact match on stage custom field)
     * @return array ['contacts' => array, 'total' => int, 'total_pages' => int]
     */
    public function searchContacts(array $args = []): array;

    /**
     * Delete a contact
     * 
     * @param int $id Contact ID
     * @return bool Success status
     */
    public function deleteContact(int $id): bool;

    /**
     * Get notes for a contact
     * 
     * @param int $contact_id Contact ID
     * @param array $args Optional pagination args (page, per_page)
     * @return array Array with 'notes' and 'total' keys
     */
    public function getContactNotes(int $contact_id, array $args = []): array;

    /**
     * Add a note to a contact
     * 
     * @param int $contact_id Contact ID
     * @param array $data Note data (type, title, description)
     * @return int|false Note ID or false on failure
     */
    public function addContactNote(int $contact_id, array $data);

    /**
     * Update a note
     * 
     * @param int $note_id Note ID
     * @param array $data Note data (type, title, description)
     * @return bool Success status
     */
    public function updateNote(int $note_id, array $data): bool;

    /**
     * Delete a note
     * 
     * @param int $note_id Note ID
     * @param array $data Optional data (e.g., contact_id for validation)
     * @return bool Success status
     */
    public function deleteNote(int $note_id, array $data = []): bool;

    /**
     * Get CRM option/setting
     * 
     * @param string $key Option key
     * @param mixed $default Default value if not found
     * @return mixed Option value
     */
    public function getOption(string $key, $default = null);

    /**
     * Update CRM option/setting
     * 
     * @param string $key Option key
     * @param mixed $value Option value
     * @return bool Success status
     */
    public function updateOption(string $key, $value): bool;

    /**
     * Get standard contact field mappings
     * 
     * @return array Field key => label pairs
     */
    public function getStandardFields(): array;

    /**
     * Sanitize contact data before save
     * 
     * @param array $data Contact data
     * @return array Sanitized data
     */
    public function sanitizeContactData(array $data): array;

    /**
     * Register hooks for this provider
     * 
     * @return void
     */
    public function registerHooks(): void;

    /**
     * Get available activity/note types
     * 
     * @return array Array of activity types with id, label, icon, library
     */
    public function getActivityTypes(): array;

    /**
     * Get the required unique identifier field for contacts
     * 
     * @return array ['field' => string, 'label' => string, 'is_custom_field' => bool]
     */
    public function getRequiredUniqueField(): array;

    /**
     * Validate contact data before creation
     * Returns validation result with any errors
     * 
     * @param array $data Contact data to validate
     * @return array ['valid' => bool, 'error_code' => string|null, 'error_message' => string|null]
     */
    public function validateContactData(array $data): array;

    /**
     * Get contact owner user ID
     * 
     * @param int $contactId Contact ID
     * @return int|null Owner user ID or null if unassigned
     */
    public function getContactOwner(int $contactId): ?int;

    /**
     * Set contact owner
     * 
     * @param int $contactId Contact ID
     * @param int|null $userId Owner user ID (null to unassign)
     * @return bool Success status
     */
    public function setContactOwner(int $contactId, ?int $userId): bool;

    /**
     * Get contacts filtered by owner
     * 
     * @param array $args Query arguments including 'owner_id' filter
     * @return array ['contacts' => array, 'total' => int]
     */
    public function getContactsByOwner(array $args = []): array;

    /**
     * Update custom field value for all contacts that have a specific value
     * Used for cascade updates when renaming field options
     * 
     * @param string $fieldSlug The custom field slug
     * @param string $oldValue The old value to find
     * @param string $newValue The new value to set
     * @return int Number of contacts updated
     */
    public function updateCustomFieldValue(string $fieldSlug, string $oldValue, string $newValue): int;

    /**
     * Count contacts that have a specific custom field value
     * Used to check if a field option is in use before deletion
     * 
     * @param string $fieldSlug The custom field slug
     * @param string $value The value to count
     * @return int Number of contacts with this value
     */
    public function countContactsWithCustomFieldValue(string $fieldSlug, string $value): int;
    /**
     * Count contacts that do NOT have a specific custom field set
     * (no meta row exists for the field slug)
     *
     * @param string $fieldSlug The custom field slug
     * @return int Number of contacts without this field
     */
    public function countContactsWithoutCustomField(string $fieldSlug): int;

    /**
     * Get the admin menu parent slug for this CRM
     * Used by modules to register submenus under the CRM's menu
     * 
     * @return string Admin menu parent slug (e.g., 'edit.php?post_type=plover_crm_contact' or 'fluentcrm-admin')
     */
    public function getAdminMenuParent(): string;
}
