<?php

namespace App\Services;

use Illuminate\Support\Facades\Log;

/**
 * Mock service to simulate Microsoft Graph API calls during dry-run
 */
class MockMicrosoftGraphService
{
    private $mockUsers = [];
    private $mockGroups = [];
    private $mockContactFolders = [];
    private $mockContacts = [];

    /**
     * Simulate getting a user by email
     */
    public function get(string $endpoint): object
    {
        Log::info("🧪 MOCK: GET {$endpoint}");

        // Simulate Members folder search
        if (str_contains($endpoint, "contactFolders?\$filter=displayName eq 'Members'")) {
            // Simulate Members folder exists
            return (object) [
                'value' => [
                    (object) [
                        'id' => 'mock-members-folder-' . uniqid(),
                        'displayName' => 'Members'
                    ]
                ]
            ];
        }

        // Simulate contact folder operations
        if (str_contains($endpoint, '/contactFolders/')) {
            if (str_contains($endpoint, '/contacts')) {
                // Simulate many existing contacts to test pagination
                $mockContacts = [];
                for ($i = 1; $i <= 25; $i++) { // Simulate 25 contacts (more than typical page size of 10)
                    $mockContacts[] = (object) [
                        'id' => "mock-contact-{$i}",
                        'displayName' => "Existing Contact {$i}",
                        'emailAddresses' => [
                            (object) ['address' => "existing{$i}@example.com"]
                        ]
                    ];
                }

                // Check if this is a paginated request (contains skiptoken or skip)
                if (str_contains($endpoint, '$skip=') || str_contains($endpoint, 'skiptoken=')) {
                    // Return second page (contacts 11-20)
                    $secondPageContacts = array_slice($mockContacts, 10, 10);
                    return (object) [
                        'value' => $secondPageContacts
                        // No @odata.nextLink for second page (end of results)
                    ];
                } else {
                    // Return first page (contacts 1-10) with nextLink
                    $firstPageContacts = array_slice($mockContacts, 0, 10);
                    return (object) [
                        'value' => $firstPageContacts,
                        '@odata.nextLink' => str_replace('/contacts', '/contacts?$skip=10', $endpoint)
                    ];
                }
            }
            // Getting a specific contact folder
            return (object) [
                'id' => 'mock-contactfolder-' . uniqid(),
                'displayName' => 'Mock Contact Folder',
                'parentFolderId' => 'mock-members-folder'
            ];
        }

        // Simulate user not found response
        if (str_contains($endpoint, '/users/')) {
            return (object) [
                'error' => (object) [
                    'code' => 'Request_ResourceNotFound',
                    'message' => 'User not found (mock response)'
                ]
            ];
        }

        // Simulate group operations
        if (str_contains($endpoint, '/groups')) {
            if (str_contains($endpoint, '/members')) {
                // Simulate many group members to test pagination
                $mockMembers = [];
                for ($i = 1; $i <= 15; $i++) { // Simulate 15 members (more than typical page size)
                    $mockMembers[] = (object) [
                        'id' => "mock-member-{$i}",
                        'displayName' => "Member {$i}",
                        'userPrincipalName' => "member{$i}@example.com"
                    ];
                }

                // Check if this is a paginated request
                if (str_contains($endpoint, '$skip=') || str_contains($endpoint, 'skiptoken=')) {
                    // Return second page (members 11-15)
                    $secondPageMembers = array_slice($mockMembers, 10, 5);
                    return (object) [
                        'value' => $secondPageMembers
                        // No @odata.nextLink for second page (end of results)
                    ];
                } else {
                    // Return first page (members 1-10) with nextLink
                    $firstPageMembers = array_slice($mockMembers, 0, 10);
                    return (object) [
                        'value' => $firstPageMembers,
                        '@odata.nextLink' => str_replace('/members', '/members?$skip=10', $endpoint)
                    ];
                }
            } else {
                // Group search by filter - return empty (group not found)
                return (object) [
                    'value' => []
                ];
            }
        }

        return (object) [];
    }

    /**
     * Simulate creating a user in Microsoft Graph
     */
    public function post(string $endpoint, array $data): object
    {
        Log::info("🧪 MOCK: POST {$endpoint}", $data);

        // Simulate creating contact folders and child folders
        if (str_contains($endpoint, '/contactFolders')) {
            $mockId = 'mock-contactfolder-' . uniqid();

            // Check if this is a child folder creation
            if (str_contains($endpoint, '/childFolders')) {
                // Extract parent folder ID from endpoint for childFolders
                Log::info("🧪 MOCK: Creating child folder under parent", [
                    'endpoint' => $endpoint,
                    'displayName' => $data['displayName']
                ]);
                $mockId = 'mock-childfolder-' . uniqid();
            }

            $this->mockContactFolders[$data['displayName']] = $mockId;

            return (object) [
                'id' => $mockId,
                'displayName' => $data['displayName'],
                'parentFolderId' => $data['parentFolderId'] ?? null
            ];
        }

        // Simulate creating contacts
        if (str_contains($endpoint, '/contacts')) {
            $mockId = 'mock-contact-' . uniqid();
            $contactKey = $data['emailAddresses'][0]['address'] ?? 'unknown';
            $this->mockContacts[$contactKey] = $mockId;

            return (object) [
                'id' => $mockId,
                'displayName' => $data['displayName'],
                'emailAddresses' => $data['emailAddresses']
            ];
        }

        if (str_contains($endpoint, '/users')) {
            $mockId = 'mock-user-' . uniqid();
            $this->mockUsers[$data['userPrincipalName']] = $mockId;

            return (object) [
                'id' => $mockId,
                'userPrincipalName' => $data['userPrincipalName'],
                'displayName' => $data['displayName']
            ];
        }

        if (str_contains($endpoint, '/groups')) {
            $mockId = 'mock-group-' . uniqid();
            $this->mockGroups[$data['displayName']] = $mockId;

            return (object) [
                'id' => $mockId,
                'displayName' => $data['displayName'],
                'mailNickname' => $data['mailNickname']
            ];
        }

        return (object) ['id' => 'mock-' . uniqid()];
    }

    /**
     * Simulate updating a resource
     */
    public function patch(string $endpoint, array $data): object
    {
        Log::info("🧪 MOCK: PATCH {$endpoint}", $data);

        // Return mock updated object with ID for contact folders and contacts
        if (str_contains($endpoint, '/contactFolders/') || str_contains($endpoint, '/contacts/')) {
            return (object) [
                'id' => 'mock-updated-' . uniqid(),
                'success' => true
            ];
        }

        return (object) ['success' => true];
    }

    /**
     * Simulate deleting a resource
     */
    public function delete(string $endpoint): object
    {
        Log::info("🧪 MOCK: DELETE {$endpoint}");

        // Simulate different types of deletions
        if (str_contains($endpoint, '/contacts/')) {
            Log::info("🧪 MOCK: Deleting contact");
        } elseif (str_contains($endpoint, '/contactFolders/')) {
            Log::info("🧪 MOCK: Deleting contact folder");
        }

        // Simulate successful deletion
        return (object) ['success' => true];
    }

    /**
     * Simula agregar un miembro a un grupo
     */
    public function addGroupMember(string $groupId, string $userId): object
    {
        Log::info("🧪 MOCK: Adding user {$userId} to group {$groupId}");
        return (object) ['success' => true];
    }

    /**
     * Verifica si el servicio está conectado (siempre true para mock)
     */
    public function isConnected(): bool
    {
        return true;
    }
}
