# Medos SDK

[![npm version](https://img.shields.io/npm/v/medos-sdk.svg)](https://www.npmjs.com/package/medos-sdk)
[![License](https://img.shields.io/badge/license-UNLICENSED-red.svg)](LICENSE)
[![TypeScript](https://img.shields.io/badge/TypeScript-5.9%2B-blue.svg)](https://www.typescriptlang.org/)

A JavaScript/TypeScript SDK for integrating healthcare appointment booking into your applications. Built for clinics, hospitals, and healthcare platforms.

## ✨ Features

- 🎨 **Powerful Theming System** - Customize appearance with built-in themes or create your own
- ⚛️ **React & Vanilla JS** - Works with React or pure JavaScript
- 🔒 **Secure Authentication** - API key and session token support
- 📱 **Responsive Design** - Mobile-first, works on all screen sizes
- 🎯 **TypeScript-First** - Full type safety and IntelliSense support
- ♿ **Accessible** - WCAG compliant components

## Installation

```bash
npm install medos-sdk
```

## Table of Contents

- [Quick Start](#quick-start)
- [Getting Started](#getting-started)
- [Usage](#usage)
- [React Integration](#react-integration)
- [Vanilla JavaScript](#vanilla-javascript--html-integration)
  - [Installation Options](#installation-options)
  - [Appointment Booking Widget](#appointment-booking-widget)
  - [Enquiry Form Widget](#enquiry-form-widget)
  - [Widget Step Flow](#widget-step-flow)
  - [Configuration Options](#configuration-options)
  - [Authentication Methods](#authentication-methods)
  - [Server-Side Integration Examples](#server-side-integration-examples)
  - [Multiple Widgets on Same Page](#multiple-widgets-on-same-page)
  - [Global API Reference](#global-api-reference)
  - [Widget Lifecycle Management](#widget-lifecycle-management)
  - [Theme Customization](#theme-customization)
  - [Troubleshooting Guide](#troubleshooting-guide)
- [TypeScript](#typescript)
- [API Reference](#api-reference)
- [Error Handling](#error-handling)
- [Examples and Documentation](#examples-and-documentation)
- [Requirements](#requirements)

## Quick Start

### React

```tsx
import { MedosThemeProvider, AppointmentCalender } from "medos-sdk/react";

function App() {
  return (
    <MedosThemeProvider theme="modern">
      <AppointmentCalender onError={(err) => console.error(err)} />
    </MedosThemeProvider>
  );
}
```

### Vanilla JavaScript

```javascript
import { initAppointmentCalendar } from "medos-sdk/vanilla";

initAppointmentCalendar({
  containerId: "appointment-widget",
  apiKey: "your-api-key",
  theme: "modern", // or 'default'
});
```

### HTML/CSS/JS

```html
<!DOCTYPE html>
<html>
  <head>
    <link rel="stylesheet" href="path/to/widget.css" />
  </head>
  <body>
    <div id="appointment-calendar"></div>
    <script src="path/to/widget.js"></script>
    <script>
      window.MedosAppointmentCalendar.init({
        containerId: "appointment-calendar",
        apiKey: "your-api-key",
      });
    </script>
  </body>
</html>
```

## Getting Started

### Authentication

The SDK supports two authentication methods:

#### Server-Side (API Key)

Use this method for backend services and server-side rendering.

```javascript
import { MedosClient } from "medos-sdk";

await MedosClient.init({
  apiKey: "your-api-key",
});
```

#### Client-Side (Session Token)

Use this method for frontend applications. Obtain the session token from your backend.

```javascript
import { MedosClient } from "medos-sdk";

await MedosClient.initWithSession({
  sessionToken: "user-session-token",
});
```

## Usage

### Fetch Clinic Addresses and Doctors

Retrieve all available clinic locations with their associated doctors.

```javascript
const result = await MedosClient.fetchAllAddressesAndDoctors();
```

**Response:**

```javascript
{
  totalAddresses: 5,
  totalDoctors: 12,
  workspaceId: "workspace-123",
  addresses: [
    {
      id: "addr-1",
      completeAddress: "123 Medical Center, New York, NY 10001",
      addressLine1: "123 Medical Center",
      city: "New York",
      state: "NY",
      country: "USA",
      zipcode: "10001",
      doctors: [
        {
          id: "doc-1",
          name: "Dr. John Smith",
          email: "john.smith@example.com",
          specialty: "Cardiology"
        }
      ]
    }
  ]
}
```

### Fetch Available Slots

Get available appointment time slots for a specific doctor.

```javascript
const slots = await MedosClient.fetchAppointments(
  "workspace-123", // workspaceId
  "addr-1", // addressId
  "doc-1", // doctorId
  "2025-11-16" // appointmentDate (YYYY-MM-DD)
);
```

**Response:**

```javascript
[
  {
    start: "2025-11-16T10:00:00",
    end: "2025-11-16T10:30:00",
    id: "slot-1",
  },
  {
    start: "2025-11-16T11:00:00",
    end: "2025-11-16T11:30:00",
    id: "slot-2",
  },
];
```

### Book an Appointment

Create a new appointment booking.

```javascript
import { AppointmentService } from "medos-sdk";

const appointment = await AppointmentService.createAppointment({
  workspaceAddressId: "addr-1",
  doctorId: "doc-1",
  mode: "OFFLINE",
  appointmentDate: "2025-11-16",
  fromDateTimeTs: "10:00",
  toDateTimeTs: "10:30",
  consultationCharge: "100",
  type: "CONSULTATION",
  source: "SDK_POWERED_WEBSITE",
  patientPayload: {
    firstName: "Jane",
    lastName: "Doe",
    email: "jane.doe@example.com",
    countryCode: "+1",
    phoneNumber: "5551234567",
    age: 30,
    gender: "FEMALE",
  },
  patientAddress: {
    addressLine1: "456 Patient Street",
    city: "New York",
    state: "NY",
    country: "USA",
    zipcode: "10001",
    landmark: "Near Central Park",
  },
});
```

**Optional Fields:**

| Field                | Default Value           | Description                                  |
| -------------------- | ----------------------- | -------------------------------------------- |
| `mode`               | `"OFFLINE"`             | Consultation mode: `"OFFLINE"` or `"ONLINE"` |
| `consultationCharge` | `"0"`                   | Consultation fee as string                   |
| `type`               | `"CONSULTATION"`        | Appointment type                             |
| `source`             | `"SDK_POWERED_WEBSITE"` | Source identifier                            |

### Phone Verification

Implement OTP-based phone number verification for patients.

#### Send OTP

```javascript
await MedosClient.sendPhoneVerificationOtp({
  countryCode: "+1",
  phoneNumber: "5551234567",
});
```

#### Verify OTP

```javascript
const result = await MedosClient.verifyPhoneVerificationOtp({
  countryCode: "+1",
  phoneNumber: "5551234567",
  otp: "123456",
});
```

## TypeScript

The SDK is written in TypeScript and provides comprehensive type definitions.

```typescript
import {
  MedosClient,
  AppointmentService,
  BookAppointmentPayload,
  AddressesResponse,
  PatientPayload,
  PatientAddressPayload,
} from "medos-sdk";

const payload: BookAppointmentPayload = {
  workspaceAddressId: "addr-1",
  doctorId: "doc-1",
  appointmentDate: "2025-11-16",
  fromDateTimeTs: "10:00",
  toDateTimeTs: "10:30",
  patientPayload: {
    firstName: "John",
    lastName: "Doe",
    countryCode: "+1",
    phoneNumber: "5551234567",
  },
  patientAddress: {
    addressLine1: "123 Main Street",
    city: "New York",
    state: "NY",
    country: "USA",
    zipcode: "10001",
  },
};

const appointment = await AppointmentService.createAppointment(payload);
```

### Type Definitions

#### `BookAppointmentPayload`

```typescript
{
  workspaceAddressId: string | number;
  doctorId: string | number;
  appointmentDate: string;           // Format: "YYYY-MM-DD"
  fromDateTimeTs: string;            // Format: "HH:MM"
  toDateTimeTs: string;              // Format: "HH:MM"
  mode?: "OFFLINE" | "ONLINE";       // Default: "OFFLINE"
  consultationCharge?: string;       // Default: "0"
  type?: "CONSULTATION" | string;    // Default: "CONSULTATION"
  source?: string;                   // Default: "SDK_POWERED_WEBSITE"
  patientPayload: PatientPayload;
  patientAddress: PatientAddressPayload;  // Required
}
```

#### `PatientPayload`

```typescript
{
  firstName: string;
  lastName: string;
  countryCode: string;
  phoneNumber: string;
  email?: string;
  age?: number;
  gender?: "MALE" | "FEMALE" | "OTHER";
}
```

#### `PatientAddressPayload`

```typescript
{
  addressLine1?: string;
  city?: string;
  state?: string;
  country?: string;
  zipcode?: string;
  landmark?: string;
}
```

## React Integration

Pre-built appointment calendar component for React applications.

```jsx
import { AppointmentCalender } from "medos-sdk";

function BookingPage() {
  return <AppointmentCalender />;
}
```

The component automatically uses the initialized `MedosClient` instance.

### Using React-specific exports

For better tree-shaking and to avoid React dependency conflicts:

```jsx
import { AppointmentCalender } from "medos-sdk/react";
```

## Vanilla JavaScript / HTML Integration

For websites using plain HTML, CSS, and JavaScript (no React), use the vanilla widget. The SDK provides two widgets: **Appointment Booking** and **Enquiry Form**.

### Installation Options

#### Option 1: NPM Package (Recommended)

```bash
npm install medos-sdk
```

After building, you'll find the widget files in:

- `dist/vanilla/widget.js` - JavaScript bundle (UMD format)
- `dist/vanilla/widget.css` - Base stylesheet
- `dist/vanilla/widget-themed.css` - Advanced theming stylesheet

#### Option 2: CDN Integration

Load directly from CDN (replace with actual CDN URL when available):

```html
<!-- CSS -->
<link
  rel="stylesheet"
  href="https://cdn.jsdelivr.net/npm/medos-sdk@latest/dist/vanilla/widget.css"
/>

<!-- JavaScript -->
<script src="https://cdn.jsdelivr.net/npm/medos-sdk@latest/dist/vanilla/widget.js"></script>
```

### Appointment Booking Widget

#### Basic Usage

```html
<!DOCTYPE html>
<html>
  <head>
    <link rel="stylesheet" href="path/to/widget.css" />
  </head>
  <body>
    <div id="appointment-calendar"></div>

    <script src="path/to/widget.js"></script>
    <script>
      // Method 1: Global API (Recommended)
      window.MedosAppointmentCalendar.init({
        containerId: "appointment-calendar",
        apiKey: "your-api-key",
        onError: (err) => {
          console.error("Error:", err);
          alert("An error occurred. Please try again.");
        },
        onSuccess: () => {
          console.log("Appointment booked successfully!");
        },
      });

      // Method 2: Class-based API (Alternative)
      // const widget = new window.MedosAppointmentWidget('appointment-calendar', {
      //   apiKey: 'your-api-key'
      // });
    </script>
  </body>
</html>
```

#### CDN Integration Example

```html
<!DOCTYPE html>
<html>
  <head>
    <link
      rel="stylesheet"
      href="https://cdn.jsdelivr.net/npm/medos-sdk@latest/dist/vanilla/widget.css"
    />
  </head>
  <body>
    <div id="appointment-widget"></div>

    <script src="https://cdn.jsdelivr.net/npm/medos-sdk@latest/dist/vanilla/widget.js"></script>
    <script>
      window.MedosAppointmentCalendar.init({
        containerId: "appointment-widget",
        sessionToken: "your-session-token", // Obtained from your server
        baseURL: "https://api.medos.one/v1",
        onError: (err) => console.error(err),
        onSuccess: () => console.log("Success!"),
      });
    </script>
  </body>
</html>
```

### Enquiry Form Widget

#### Basic Usage

```html
<!DOCTYPE html>
<html>
  <head>
    <link rel="stylesheet" href="path/to/widget.css" />
  </head>
  <body>
    <div id="enquiry-form"></div>

    <script src="path/to/widget.js"></script>
    <script>
      // Method 1: Global API (Recommended)
      window.MedosEnquiryForm.init({
        containerId: "enquiry-form",
        apiKey: "your-api-key",
        onError: (err) => console.error(err),
        onSuccess: (enquiry) => {
          console.log("Enquiry submitted:", enquiry);
          alert("Thank you! Your enquiry has been submitted.");
        },
      });

      // Method 2: Class-based API (Alternative)
      // const widget = new window.MedosEnquiryWidget('enquiry-form', {
      //   apiKey: 'your-api-key'
      // });
    </script>
  </body>
</html>
```

### Widget Step Flow

#### Appointment Booking Steps

The appointment widget follows this exact step sequence (matching React component):

1. **Step 0: Phone Verification** - Country code selection, phone input, OTP verification
2. **Step 1: Booking Option Selection** - Session packs vs. new appointment (auto-skipped if no packages)
3. **Step 2: Location & Doctor Selection** - Address and doctor selection with chief complaint
4. **Step 3: Date & Time Selection** - Calendar, consultation mode, and time slot selection
5. **Step 4: Patient Selection** - Choose existing patient or create new
6. **Step 5: Patient Details Form** - Patient information and address (for new patients)
7. **Step 6: Appointment Summary** - Review all details and cost breakdown
8. **Step 7: Success Confirmation** - Confirmation with appointment details

#### Enquiry Form Steps

1. **Step 1: Contact Information** - Name, email, phone number
2. **Step 2: Inquiry Details** - Subject and detailed message
3. **Step 3: Contact Preference** - Preferred contact method (email, phone, both)
4. **Step 4: Success Confirmation** - Submission confirmation

### Configuration Options

Complete API reference for widget initialization:

```typescript
interface WidgetOptions {
  containerId: string; // Required: ID of container element
  apiKey?: string; // Optional: API key for authentication
  sessionToken?: string; // Optional: Session token (alternative to apiKey)
  baseURL?: string; // Optional: API base URL (default: https://api.medos.one/v1)
  onError?: (error: Error) => void; // Optional: Error callback
  onSuccess?: (data?: any) => void; // Optional: Success callback
  onStepChange?: (step: number) => void; // Optional: Step change callback
  theme?: "default" | "modern" | string; // Optional: Theme selection
}
```

#### Configuration Examples

**Basic Configuration:**

```javascript
window.MedosAppointmentCalendar.init({
  containerId: "appointment-widget",
  apiKey: "your-api-key",
});
```

**Advanced Configuration with Callbacks:**

```javascript
window.MedosAppointmentCalendar.init({
  containerId: "appointment-widget",
  sessionToken: "user-session-token",
  baseURL: "https://api.medos.one/v1",
  theme: "modern",
  onError: (error) => {
    console.error("Widget error:", error);
    // Show user-friendly error message
    document.getElementById("error-message").textContent =
      "Unable to load appointment booking. Please try again.";
    document.getElementById("error-message").style.display = "block";
  },
  onSuccess: (appointment) => {
    console.log("Appointment booked successfully", appointment);
    // Redirect or show success message
    window.location.href = "/appointment-confirmation";
  },
  onStepChange: (step) => {
    console.log("Current step:", step);
    // Track user progress for analytics
    if (typeof analytics !== "undefined") {
      analytics.track("appointment_step_change", { step });
    }
  },
});
```

**Environment-Specific Configuration:**

```javascript
const isProduction = window.location.hostname !== "localhost";
const config = {
  containerId: "appointment-widget",
  baseURL: isProduction
    ? "https://api.medos.one/v1"
    : "https://dev-api.medos.one/v1",
  sessionToken: await getSessionToken(), // Fetch from your backend
  onError: (error) => handleWidgetError(error),
};

window.MedosAppointmentCalendar.init(config);
```

### Authentication Methods

#### Using Session Token (Recommended for Production)

For better security, obtain the session token server-side:

```javascript
// Fetch session token from your backend
async function initializeWidget() {
  try {
    const response = await fetch("/api/get-session-token");
    const { sessionToken } = await response.json();

    window.MedosAppointmentCalendar.init({
      containerId: "appointment-calendar",
      sessionToken: sessionToken,
      baseURL: "https://api.medos.one/v1",
      onError: (err) => console.error(err),
    });
  } catch (error) {
    console.error("Failed to get session token:", error);
  }
}

initializeWidget();
```

#### Using API Key (Development Only)

```javascript
window.MedosAppointmentCalendar.init({
  containerId: "appointment-calendar",
  apiKey: "your-api-key", // Only for development/testing
  onError: (err) => console.error(err),
});
```

### Server-Side Integration Examples

#### PHP Integration

```php
<?php
// Get session token from your backend
function getSessionTokenFromBackend() {
    // Your implementation to get session token
    // This should call your backend API that exchanges API key for session token
    $apiKey = 'your-api-key';
    $response = file_get_contents('https://api.medos.one/v1/auth/session', false, stream_context_create([
        'http' => [
            'method' => 'POST',
            'header' => "Authorization: Bearer $apiKey\r\nContent-Type: application/json\r\n",
            'content' => json_encode(['apiKey' => $apiKey])
        ]
    ]));
    $data = json_decode($response, true);
    return $data['sessionToken'];
}

$sessionToken = getSessionTokenFromBackend();
?>
<!DOCTYPE html>
<html>
<head>
    <link rel="stylesheet" href="path/to/widget.css">
</head>
<body>
    <div id="appointment-calendar"></div>
    <script src="path/to/widget.js"></script>
    <script>
        window.MedosAppointmentCalendar.init({
            containerId: 'appointment-calendar',
            sessionToken: '<?php echo htmlspecialchars($sessionToken); ?>',
            onError: function(err) {
                console.error('Error:', err);
                alert('An error occurred. Please try again.');
            },
            onSuccess: function() {
                console.log('Appointment booked successfully!');
                // Redirect to confirmation page
                window.location.href = '/appointment-confirmation.php';
            }
        });
    </script>
</body>
</html>
```

#### Node.js/Express Integration

```javascript
// Backend route to get session token
app.get("/api/session-token", async (req, res) => {
  try {
    const response = await axios.post("https://api.medos.one/v1/auth/session", {
      apiKey: process.env.MEDOS_API_KEY,
    });
    res.json({ sessionToken: response.data.sessionToken });
  } catch (error) {
    res.status(500).json({ error: "Failed to get session token" });
  }
});
```

```html
<!-- Frontend HTML -->
<!DOCTYPE html>
<html>
  <head>
    <link rel="stylesheet" href="/dist/vanilla/widget.css" />
  </head>
  <body>
    <div id="appointment-widget"></div>
    <script src="/dist/vanilla/widget.js"></script>
    <script>
      fetch("/api/session-token")
        .then((response) => response.json())
        .then((data) => {
          window.MedosAppointmentCalendar.init({
            containerId: "appointment-widget",
            sessionToken: data.sessionToken,
            onError: (err) => console.error(err),
            onSuccess: () => console.log("Success!"),
          });
        })
        .catch((error) => console.error("Failed to initialize widget:", error));
    </script>
  </body>
</html>
```

### Multiple Widgets on Same Page

You can use multiple widgets independently on the same page:

```html
<!DOCTYPE html>
<html>
  <head>
    <link rel="stylesheet" href="path/to/widget.css" />
  </head>
  <body>
    <!-- Appointment Widget -->
    <div id="appointment-widget"></div>

    <!-- Enquiry Widget -->
    <div id="enquiry-widget"></div>

    <script src="path/to/widget.js"></script>
    <script>
      // Initialize appointment widget
      window.MedosAppointmentCalendar.init({
        containerId: "appointment-widget",
        apiKey: "your-api-key",
        onSuccess: () => console.log("Appointment booked!"),
      });

      // Initialize enquiry widget
      window.MedosEnquiryForm.init({
        containerId: "enquiry-widget",
        apiKey: "your-api-key",
        onSuccess: (enquiry) => console.log("Enquiry submitted:", enquiry),
      });
    </script>
  </body>
</html>
```

### Global API Reference

After loading the widget script, these global objects are available:

```javascript
// Global initialization functions
window.MedosAppointmentCalendar.init(options); // Appointment widget
window.MedosEnquiryForm.init(options); // Enquiry form widget

// Widget classes for advanced usage
window.MedosAppointmentWidget; // Appointment widget class
window.MedosEnquiryWidget; // Enquiry widget class
```

### Widget Lifecycle Management

#### Destroying Widgets

```javascript
// For class-based initialization
const widget = new window.MedosAppointmentWidget("container", options);
// Later...
widget.destroy(); // Clean up event listeners and DOM

// For global API initialization
// Widgets are automatically cleaned up when container is removed from DOM
```

#### Reinitializing Widgets

```javascript
// Clear container and reinitialize
const container = document.getElementById("appointment-widget");
container.innerHTML = ""; // Clear existing widget

window.MedosAppointmentCalendar.init({
  containerId: "appointment-widget",
  apiKey: "your-api-key",
});
```

### Theme Customization

The SDK provides comprehensive theming capabilities through CSS variables. Choose between two CSS files based on your customization needs:

#### Basic Theming (`widget.css`)

For simple customization with minimal variables:

```html
<link rel="stylesheet" href="dist/vanilla/widget.css" />
<style>
  .my-theme {
    --medos-primary-color: #7c3aed;
    --medos-primary-color-hover: #6d28d9;
    --medos-bg-color: #ffffff;
    --medos-text-color: #1f2937;
  }
</style>
<div id="widget" class="my-theme"></div>
```

#### Advanced Theming (`widget-themed.css`)

For comprehensive design system customization:

```html
<link rel="stylesheet" href="dist/vanilla/widget-themed.css" />
<style>
  .my-advanced-theme {
    /* Colors */
    --medos-color-primary: #7c3aed;
    --medos-color-background: #ffffff;
    --medos-color-text: #1f2937;

    /* Typography */
    --medos-typography-font-family: "Georgia", serif;
    --medos-typography-font-size-md: 18px;

    /* Spacing & Layout */
    --medos-spacing-md: 16px;
    --medos-radius-md: 20px;
    --medos-shadow-lg: 0 20px 40px rgba(124, 58, 237, 0.15);
  }
</style>
<div id="widget" class="my-advanced-theme"></div>
```

#### Dynamic Theme Switching

```javascript
// Apply theme programmatically
const container = document.getElementById("widget-container");

// Method 1: CSS classes
container.classList.add("dark-theme");

// Method 2: Direct CSS variables
container.style.setProperty("--medos-color-primary", "#7c3aed");
container.style.setProperty("--medos-color-background", "#1f2937");

// Method 3: Theme objects
const themes = {
  purple: {
    "--medos-color-primary": "#7c3aed",
    "--medos-color-secondary": "#a855f7",
  },
  green: {
    "--medos-color-primary": "#10b981",
    "--medos-color-secondary": "#34d399",
  },
};

function applyTheme(themeName) {
  const theme = themes[themeName];
  Object.entries(theme).forEach(([property, value]) => {
    container.style.setProperty(property, value);
  });
}
```

#### Theme Examples

Explore comprehensive theming examples in the `examples/` directory:

- `theme-customization-basic.html` - Basic CSS variable overrides
- `theme-customization-advanced.html` - Multiple theme comparisons
- `theme-customization-javascript.html` - Dynamic theme switching
- `theme-comparison.html` - Side-by-side CSS file comparison
- `enquiry-form-theming.html` - Enquiry form specific themes

#### Available CSS Variables

**Basic Variables (widget.css):**

- `--medos-primary-color`, `--medos-primary-color-hover`
- `--medos-bg-color`, `--medos-bg-color-secondary`
- `--medos-text-color`, `--medos-text-color-secondary`
- `--medos-border-color`, `--medos-border-radius`

**Complete Variables (widget-themed.css):**

- **Colors:** 15+ color tokens for comprehensive theming
- **Typography:** Font family, sizes, weights
- **Spacing:** Consistent spacing scale (xs, sm, md, lg, xl)
- **Layout:** Border radius, shadows, transitions

See `examples/README-THEME-CUSTOMIZATION.md` for complete documentation.

### Troubleshooting Guide

#### Common Issues and Solutions

**1. Widget Not Loading**

_Problem:_ Widget container remains empty, no errors in console.

_Solutions:_

```javascript
// Check if widget script loaded
if (typeof window.MedosAppointmentCalendar === "undefined") {
  console.error("Widget script not loaded. Check script src path.");
}

// Ensure container exists
const container = document.getElementById("your-container-id");
if (!container) {
  console.error("Container element not found. Check containerId.");
}

// Wait for DOM ready
document.addEventListener("DOMContentLoaded", function () {
  window.MedosAppointmentCalendar.init({
    containerId: "appointment-widget",
    apiKey: "your-api-key",
  });
});
```

**2. Authentication Errors**

_Problem:_ "Invalid API key" or "Authentication failed" errors.

_Solutions:_

```javascript
// Verify API key format
const apiKey = "your-api-key";
if (!apiKey || apiKey === "your-api-key") {
  console.error("Please replace with your actual API key");
}

// Use session token for production
window.MedosAppointmentCalendar.init({
  containerId: "widget",
  sessionToken: "your-session-token", // More secure
  baseURL: "https://api.medos.one/v1",
});

// Check API endpoint
fetch("https://api.medos.one/v1/health")
  .then((response) => console.log("API accessible:", response.ok))
  .catch((error) => console.error("API not accessible:", error));
```

**3. CSS Styling Issues**

_Problem:_ Widget appears unstyled or has layout issues.

_Solutions:_

```html
<!-- Ensure CSS is loaded before JavaScript -->
<link rel="stylesheet" href="path/to/widget.css" />
<script src="path/to/widget.js"></script>

<!-- Check for CSS conflicts -->
<style>
  /* Ensure widget container has proper styling */
  #appointment-widget {
    width: 100%;
    max-width: 800px;
    margin: 0 auto;
  }

  /* Reset any conflicting styles */
  .medos-appointment-container * {
    box-sizing: border-box;
  }
</style>
```

**4. Network/CORS Errors**

_Problem:_ "CORS policy" or network request failures.

_Solutions:_

```javascript
// Check baseURL configuration
window.MedosAppointmentCalendar.init({
  containerId: "widget",
  apiKey: "your-api-key",
  baseURL: "https://api.medos.one/v1", // Ensure correct URL
  onError: (error) => {
    if (error.message.includes("CORS")) {
      console.error("CORS error: Ensure your domain is whitelisted");
    }
    if (error.message.includes("Network")) {
      console.error("Network error: Check internet connection and API status");
    }
  },
});

// Test API connectivity
async function testAPIConnection() {
  try {
    const response = await fetch("https://api.medos.one/v1/health");
    console.log("API Status:", response.status);
  } catch (error) {
    console.error("Cannot reach API:", error);
  }
}
```

**5. Multiple Widget Conflicts**

_Problem:_ Multiple widgets interfering with each other.

_Solutions:_

```javascript
// Use unique container IDs
window.MedosAppointmentCalendar.init({
  containerId: "appointment-widget-1", // Unique ID
  apiKey: "your-api-key",
});

window.MedosEnquiryForm.init({
  containerId: "enquiry-widget-1", // Different unique ID
  apiKey: "your-api-key",
});

// Clean up widgets when needed
const widget = new window.MedosAppointmentWidget("container", options);
// Later...
widget.destroy(); // Prevents memory leaks
```

**6. Mobile/Responsive Issues**

_Problem:_ Widget doesn't display properly on mobile devices.

_Solutions:_

```html
<!-- Ensure viewport meta tag -->
<meta name="viewport" content="width=device-width, initial-scale=1.0" />

<style>
  /* Responsive container */
  .widget-container {
    width: 100%;
    max-width: 100vw;
    padding: 10px;
    box-sizing: border-box;
  }

  /* Mobile-specific adjustments */
  @media (max-width: 768px) {
    .widget-container {
      padding: 5px;
    }
  }
</style>
```

**7. Theme Not Applying**

_Problem:_ Custom CSS variables not taking effect.

_Solutions:_

```css
/* Ensure proper CSS specificity */
.my-theme .medos-appointment-container {
  --medos-color-primary: #7c3aed !important;
}

/* Or apply to widget container directly */
#appointment-widget {
  --medos-color-primary: #7c3aed;
  --medos-color-background: #ffffff;
}
```

```javascript
// Apply theme programmatically
const container = document.getElementById("appointment-widget");
container.style.setProperty("--medos-color-primary", "#7c3aed");

// Verify theme variables are applied
const computedStyle = getComputedStyle(container);
const primaryColor = computedStyle.getPropertyValue("--medos-color-primary");
console.log("Applied primary color:", primaryColor);
```

#### Debugging Tips

**Enable Debug Mode:**

```javascript
// Add debug logging
window.MedosAppointmentCalendar.init({
  containerId: "widget",
  apiKey: "your-api-key",
  debug: true, // Enable debug mode if available
  onError: (error) => {
    console.error("Widget Error Details:", {
      message: error.message,
      stack: error.stack,
      timestamp: new Date().toISOString(),
    });
  },
  onStepChange: (step) => {
    console.log("Step changed to:", step);
  },
});
```

**Check Widget State:**

```javascript
// Inspect widget instance
const container = document.getElementById("appointment-widget");
const widgetInstance = container._medosWidget; // Internal reference
if (widgetInstance) {
  console.log("Widget state:", widgetInstance.getState());
}

// Check global objects
console.log("Available globals:", {
  MedosAppointmentCalendar: typeof window.MedosAppointmentCalendar,
  MedosEnquiryForm: typeof window.MedosEnquiryForm,
  MedosAppointmentWidget: typeof window.MedosAppointmentWidget,
  MedosEnquiryWidget: typeof window.MedosEnquiryWidget,
});
```

**Network Debugging:**

```javascript
// Monitor API calls
const originalFetch = window.fetch;
window.fetch = function (...args) {
  console.log("API Request:", args[0]);
  return originalFetch
    .apply(this, args)
    .then((response) => {
      console.log("API Response:", response.status, response.url);
      return response;
    })
    .catch((error) => {
      console.error("API Error:", error);
      throw error;
    });
};
```

#### Performance Optimization

**Lazy Loading:**

```javascript
// Load widget only when needed
function loadWidget() {
  if (!document.getElementById("widget-script")) {
    const script = document.createElement("script");
    script.id = "widget-script";
    script.src = "path/to/widget.js";
    script.onload = () => {
      window.MedosAppointmentCalendar.init({
        containerId: "appointment-widget",
        apiKey: "your-api-key",
      });
    };
    document.head.appendChild(script);
  }
}

// Load on user interaction
document
  .getElementById("book-appointment-btn")
  .addEventListener("click", loadWidget);
```

**Resource Optimization:**

```html
<!-- Preload critical resources -->
<link rel="preload" href="path/to/widget.css" as="style" />
<link rel="preload" href="path/to/widget.js" as="script" />

<!-- Use appropriate CSS file for your needs -->
<!-- widget.css for basic theming (smaller file) -->
<link rel="stylesheet" href="dist/vanilla/widget.css" />

<!-- widget-themed.css for advanced theming (larger file) -->
<link rel="stylesheet" href="dist/vanilla/widget-themed.css" />
```

#### Getting Help

If you encounter issues not covered in this guide:

1. **Check Browser Console:** Look for error messages and warnings
2. **Verify Network Tab:** Check if API requests are successful
3. **Test with Examples:** Compare with working examples in `examples/` directory
4. **Check Version Compatibility:** Ensure you're using compatible versions
5. **Review Documentation:** Check `docs/VANILLA_WIDGET.md` for additional details

**Common Error Messages:**

- `"Container element not found"` → Check `containerId` parameter
- `"Invalid API key"` → Verify API key or use session token
- `"Network request failed"` → Check internet connection and API status
- `"Widget already initialized"` → Clear container before reinitializing
- `"Theme variables not applied"` → Check CSS specificity and variable names

### Package Exports

The SDK provides multiple entry points for different use cases:

- `medos-sdk` - Default export (includes React components)
- `medos-sdk/react` - React-specific exports
- `medos-sdk/vanilla` - Vanilla JS exports (ES modules)
- `medos-sdk/core` - Core services only (no framework dependencies)
- `medos-sdk/widget` - Widget bundle with CSS

### Examples and Documentation

Comprehensive examples and documentation are available:

#### HTML Examples (`examples/` directory)

- **`vanilla-appointment-booking.html`** - Basic appointment widget with local files
- **`cdn-appointment-booking.html`** - CDN integration example with fallback strategies
- **`enquiry-form.html`** - Enquiry form widget with both local and CDN options
- **`theme-customization-basic.html`** - Basic CSS variable overrides and theming
- **`theme-customization-advanced.html`** - Advanced theming with multiple theme comparisons
- **`theme-customization-javascript.html`** - Dynamic theme switching and programmatic theming
- **`theme-comparison.html`** - Side-by-side comparison of CSS files
- **`enquiry-form-theming.html`** - Enquiry form specific theming examples

#### Documentation (`docs/` directory)

- **`VANILLA_WIDGET.md`** - Comprehensive vanilla widget documentation
- **`CDN_INTEGRATION.md`** - Complete CDN integration guide with best practices
- **`BUILD.md`** - Build system and development setup
- **`IMPLEMENTATION_STATUS.md`** - Current implementation status and roadmap

#### Theme Documentation

- **`examples/README-THEME-CUSTOMIZATION.md`** - Complete theming guide with examples
- CSS variable reference for both `widget.css` and `widget-themed.css`
- Dynamic theme switching examples and best practices

## API Reference

### MedosClient

#### `init(config)`

Initialize the SDK with an API key (server-side).

**Parameters:**

- `config.apiKey` (string, required) - Your Medos API key
- `config.baseURL` (string, optional) - API base URL. Defaults to dev environment

**Returns:** `Promise<void>`

---

#### `initWithSession(config)`

Initialize the SDK with a session token (client-side).

**Parameters:**

- `config.sessionToken` (string, required) - Session token
- `config.baseURL` (string, optional) - API base URL. Defaults to dev environment

**Returns:** `Promise<void>`

---

#### `fetchAllAddressesAndDoctors()`

Fetch all clinic addresses and their associated doctors.

**Returns:** `Promise<AddressesResponse>`

**Response Type:**

```typescript
{
  totalAddresses?: number;
  totalDoctors?: number;
  workspaceId?: number | string;
  addresses: Array<{
    id: string;
    completeAddress?: string;
    addressLine1?: string;
    city?: string;
    state?: string;
    country?: string;
    zipcode?: string;
    doctors?: Array<{
      id: string;
      name: string;
      email?: string;
      specialty?: string;
    }>;
  }>;
}
```

---

#### `fetchAppointments(workspaceId, addressId, doctorId, appointmentDate)`

Fetch available appointment slots for a specific doctor.

**Parameters:**

- `workspaceId` (string | number) - Workspace identifier
- `addressId` (string | number) - Address identifier
- `doctorId` (string | number) - Doctor identifier
- `appointmentDate` (string) - Date in YYYY-MM-DD format

**Returns:** `Promise<Slot[]>`

**Response Type:**

```typescript
Array<{
  start: string; // ISO datetime format
  end: string; // ISO datetime format
  id?: string;
}>;
```

---

#### `sendPhoneVerificationOtp(payload)`

Send OTP to a phone number for verification.

**Parameters:**

- `payload.countryCode` (string) - Country code with + prefix (e.g., "+1")
- `payload.phoneNumber` (string) - Phone number without country code

**Returns:** `Promise<any>`

---

#### `verifyPhoneVerificationOtp(payload)`

Verify OTP for a phone number.

**Parameters:**

- `payload.countryCode` (string) - Country code with + prefix
- `payload.phoneNumber` (string) - Phone number without country code
- `payload.otp` (string) - OTP code received

**Returns:** `Promise<any>`

---

### AppointmentService

#### `createAppointment(payload)`

Create a new appointment booking.

**Parameters:**

- `payload` (BookAppointmentPayload) - Appointment details

**Returns:** `Promise<any>`

## Error Handling

All SDK methods return Promises and should be wrapped in try-catch blocks.

```javascript
try {
  await MedosClient.init({ apiKey: "your-api-key" });
  const addresses = await MedosClient.fetchAllAddressesAndDoctors();
} catch (error) {
  console.error("Failed to fetch addresses:", error.message);
}
```

## Requirements

- **Node.js:** v14 or higher
- **Browsers:** Modern browsers with ES6+ support
- **React:** v19 or higher (only required for React components, not for vanilla widget)
- **TypeScript:** v5 or higher (optional)

## Support

For bug reports and feature requests, please visit our [GitHub Issues](https://github.com/MediLaunch/medos-sdk-react/issues).

## License

UNLICENSED

## Author

Pooranjoy Bhattacharya

---

**Built for healthcare providers worldwide.**
