import { describe, it, expect, vi, beforeEach } from 'vitest';

// Mock apiClient
vi.mock('../client', () => ({
  default: {
    get: vi.fn(),
    post: vi.fn(),
    delete: vi.fn(),
  },
}));

import {
  getCustomDomains,
  addCustomDomain,
  deleteCustomDomain,
  verifyCustomDomain,
  setPrimaryDomain,
} from '../customDomains';
import apiClient from '../client';

describe('customDomains API', () => {
  beforeEach(() => {
    vi.clearAllMocks();
  });

  describe('getCustomDomains', () => {
    it('fetches all custom domains for the current business', async () => {
      const mockDomains = [
        {
          id: 1,
          domain: 'example.com',
          is_verified: true,
          ssl_provisioned: true,
          is_primary: true,
          verification_token: 'token123',
          dns_txt_record: 'smoothschedule-verify=token123',
          dns_txt_record_name: '_smoothschedule.example.com',
          created_at: '2024-01-01T00:00:00Z',
          verified_at: '2024-01-02T00:00:00Z',
        },
        {
          id: 2,
          domain: 'custom.com',
          is_verified: false,
          ssl_provisioned: false,
          is_primary: false,
          verification_token: 'token456',
          dns_txt_record: 'smoothschedule-verify=token456',
          dns_txt_record_name: '_smoothschedule.custom.com',
          created_at: '2024-01-03T00:00:00Z',
        },
      ];
      vi.mocked(apiClient.get).mockResolvedValue({ data: mockDomains });

      const result = await getCustomDomains();

      expect(apiClient.get).toHaveBeenCalledWith('/business/domains/');
      expect(result).toEqual(mockDomains);
      expect(result).toHaveLength(2);
    });

    it('returns empty array when no domains exist', async () => {
      vi.mocked(apiClient.get).mockResolvedValue({ data: [] });

      const result = await getCustomDomains();

      expect(apiClient.get).toHaveBeenCalledWith('/business/domains/');
      expect(result).toEqual([]);
      expect(result).toHaveLength(0);
    });
  });

  describe('addCustomDomain', () => {
    it('adds a new custom domain with lowercase and trimmed domain', async () => {
      const mockDomain = {
        id: 1,
        domain: 'example.com',
        is_verified: false,
        ssl_provisioned: false,
        is_primary: false,
        verification_token: 'token123',
        dns_txt_record: 'smoothschedule-verify=token123',
        dns_txt_record_name: '_smoothschedule.example.com',
        created_at: '2024-01-01T00:00:00Z',
      };
      vi.mocked(apiClient.post).mockResolvedValue({ data: mockDomain });

      const result = await addCustomDomain('Example.com');

      expect(apiClient.post).toHaveBeenCalledWith('/business/domains/', {
        domain: 'example.com',
      });
      expect(result).toEqual(mockDomain);
    });

    it('transforms domain to lowercase before sending', async () => {
      const mockDomain = {
        id: 1,
        domain: 'uppercase.com',
        is_verified: false,
        ssl_provisioned: false,
        is_primary: false,
        verification_token: 'token123',
        dns_txt_record: 'smoothschedule-verify=token123',
        dns_txt_record_name: '_smoothschedule.uppercase.com',
        created_at: '2024-01-01T00:00:00Z',
      };
      vi.mocked(apiClient.post).mockResolvedValue({ data: mockDomain });

      await addCustomDomain('UPPERCASE.COM');

      expect(apiClient.post).toHaveBeenCalledWith('/business/domains/', {
        domain: 'uppercase.com',
      });
    });

    it('trims whitespace from domain before sending', async () => {
      const mockDomain = {
        id: 1,
        domain: 'trimmed.com',
        is_verified: false,
        ssl_provisioned: false,
        is_primary: false,
        verification_token: 'token123',
        dns_txt_record: 'smoothschedule-verify=token123',
        dns_txt_record_name: '_smoothschedule.trimmed.com',
        created_at: '2024-01-01T00:00:00Z',
      };
      vi.mocked(apiClient.post).mockResolvedValue({ data: mockDomain });

      await addCustomDomain('  trimmed.com  ');

      expect(apiClient.post).toHaveBeenCalledWith('/business/domains/', {
        domain: 'trimmed.com',
      });
    });

    it('transforms domain with both uppercase and whitespace', async () => {
      const mockDomain = {
        id: 1,
        domain: 'mixed.com',
        is_verified: false,
        ssl_provisioned: false,
        is_primary: false,
        verification_token: 'token123',
        dns_txt_record: 'smoothschedule-verify=token123',
        dns_txt_record_name: '_smoothschedule.mixed.com',
        created_at: '2024-01-01T00:00:00Z',
      };
      vi.mocked(apiClient.post).mockResolvedValue({ data: mockDomain });

      await addCustomDomain('  MiXeD.COM  ');

      expect(apiClient.post).toHaveBeenCalledWith('/business/domains/', {
        domain: 'mixed.com',
      });
    });
  });

  describe('deleteCustomDomain', () => {
    it('deletes a custom domain by ID', async () => {
      vi.mocked(apiClient.delete).mockResolvedValue({});

      await deleteCustomDomain(1);

      expect(apiClient.delete).toHaveBeenCalledWith('/business/domains/1/');
    });

    it('returns void on successful deletion', async () => {
      vi.mocked(apiClient.delete).mockResolvedValue({});

      const result = await deleteCustomDomain(42);

      expect(result).toBeUndefined();
    });
  });

  describe('verifyCustomDomain', () => {
    it('verifies a custom domain and returns verification status', async () => {
      const mockResponse = {
        verified: true,
        message: 'Domain verified successfully',
      };
      vi.mocked(apiClient.post).mockResolvedValue({ data: mockResponse });

      const result = await verifyCustomDomain(1);

      expect(apiClient.post).toHaveBeenCalledWith('/business/domains/1/verify/');
      expect(result).toEqual(mockResponse);
      expect(result.verified).toBe(true);
      expect(result.message).toBe('Domain verified successfully');
    });

    it('returns failure status when verification fails', async () => {
      const mockResponse = {
        verified: false,
        message: 'DNS records not found. Please check your configuration.',
      };
      vi.mocked(apiClient.post).mockResolvedValue({ data: mockResponse });

      const result = await verifyCustomDomain(2);

      expect(apiClient.post).toHaveBeenCalledWith('/business/domains/2/verify/');
      expect(result.verified).toBe(false);
      expect(result.message).toContain('DNS records not found');
    });

    it('handles different domain IDs correctly', async () => {
      const mockResponse = {
        verified: true,
        message: 'Success',
      };
      vi.mocked(apiClient.post).mockResolvedValue({ data: mockResponse });

      await verifyCustomDomain(999);

      expect(apiClient.post).toHaveBeenCalledWith('/business/domains/999/verify/');
    });
  });

  describe('setPrimaryDomain', () => {
    it('sets a custom domain as primary', async () => {
      const mockDomain = {
        id: 1,
        domain: 'example.com',
        is_verified: true,
        ssl_provisioned: true,
        is_primary: true,
        verification_token: 'token123',
        dns_txt_record: 'smoothschedule-verify=token123',
        dns_txt_record_name: '_smoothschedule.example.com',
        created_at: '2024-01-01T00:00:00Z',
        verified_at: '2024-01-02T00:00:00Z',
      };
      vi.mocked(apiClient.post).mockResolvedValue({ data: mockDomain });

      const result = await setPrimaryDomain(1);

      expect(apiClient.post).toHaveBeenCalledWith('/business/domains/1/set-primary/');
      expect(result).toEqual(mockDomain);
      expect(result.is_primary).toBe(true);
    });

    it('returns updated domain with is_primary flag', async () => {
      const mockDomain = {
        id: 5,
        domain: 'newprimary.com',
        is_verified: true,
        ssl_provisioned: true,
        is_primary: true,
        verification_token: 'token789',
        dns_txt_record: 'smoothschedule-verify=token789',
        dns_txt_record_name: '_smoothschedule.newprimary.com',
        created_at: '2024-01-05T00:00:00Z',
        verified_at: '2024-01-06T00:00:00Z',
      };
      vi.mocked(apiClient.post).mockResolvedValue({ data: mockDomain });

      const result = await setPrimaryDomain(5);

      expect(apiClient.post).toHaveBeenCalledWith('/business/domains/5/set-primary/');
      expect(result.id).toBe(5);
      expect(result.domain).toBe('newprimary.com');
      expect(result.is_primary).toBe(true);
    });
  });
});
