# Installation Guide for Gebeya Telegram OTP

This guide will walk you through installing and setting up the `gebeya-telegram-otp` package in your React application.

## Step 1: Install the NPM Package

```bash
npm install gebeya-telegram-otp
```

## Step 2: Install Peer Dependencies

The package requires several peer dependencies. Install them all at once:

```bash
npm install @supabase/supabase-js lucide-react input-otp sonner qrcode react react-dom
```

### Individual Peer Dependencies

If you prefer to install them individually or need specific versions:

```bash
# Supabase client for database operations
npm install @supabase/supabase-js

# Icons for the UI (supports versions 0.300.0 and above)
npm install lucide-react

# OTP input component
npm install input-otp

# Toast notifications
npm install sonner

# QR code generation
npm install qrcode

# React (supports React 17+ and 18+)
npm install react react-dom
```

**Note:** This package uses flexible version ranges (`>=`) to ensure compatibility with both older and newer versions of dependencies. Your existing versions should work fine if they meet the minimum requirements.

## Step 3: Set Up Tailwind CSS

The components use Tailwind CSS for styling. If you don't have Tailwind CSS set up, follow these steps:

### Install Tailwind CSS

```bash
npm install -D tailwindcss postcss autoprefixer
npx tailwindcss init -p
```

### Configure Tailwind CSS

Update your `tailwind.config.js` to include the package components:

```javascript
/** @type {import('tailwindcss').Config} */
module.exports = {
  content: [
    "./index.html",
    "./src/**/*.{js,ts,jsx,tsx}",
    "./node_modules/gebeya-telegram-verify/dist/**/*.{js,ts,jsx,tsx}",
  ],
  theme: {
    extend: {},
  },
  plugins: [],
};
```

### Add Tailwind directives

Add these directives to your main CSS file (e.g., `src/index.css`):

```css
@tailwind base;
@tailwind components;
@tailwind utilities;
```

## Step 4: Set Up Supabase

### Create a Supabase Project

1. Go to [https://supabase.com](https://supabase.com)
2. Create a new project
3. Note your project URL and anon key

### Set Up the Database

Run this SQL in your Supabase SQL editor:

```sql
-- Create verification sessions table
CREATE TABLE public.verification_sessions (
  id UUID NOT NULL DEFAULT gen_random_uuid() PRIMARY KEY,
  phone_number TEXT NOT NULL,
  telegram_user_id BIGINT,
  telegram_chat_id BIGINT,
  otp_code TEXT,
  verified BOOLEAN NOT NULL DEFAULT false,
  expires_at TIMESTAMP WITH TIME ZONE NOT NULL,
  created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now()
);

-- Enable RLS
ALTER TABLE public.verification_sessions ENABLE ROW LEVEL SECURITY;

-- Create policies
CREATE POLICY "Anyone can insert verification sessions"
  ON public.verification_sessions FOR INSERT WITH CHECK (true);

CREATE POLICY "Anyone can read verification sessions for verification process"
  ON public.verification_sessions FOR SELECT USING (true);

CREATE POLICY "Anyone can update verification sessions"
  ON public.verification_sessions FOR UPDATE USING (true);
```

### Create Supabase Client

Create a file `src/lib/supabase.js` (or `.ts` for TypeScript):

```javascript
import { createClient } from "@supabase/supabase-js";

const supabaseUrl = "YOUR_SUPABASE_URL";
const supabaseKey = "YOUR_SUPABASE_ANON_KEY";

export const supabase = createClient(supabaseUrl, supabaseKey);
```

## Step 5: Set Up Telegram Bot

1. Message [@BotFather](https://t.me/botfather) on Telegram
2. Create a new bot with `/newbot`
3. Get your bot token
4. Add the bot token to your Supabase secrets as `TELEGRAM_BOT_TOKEN`

## Step 6: Configure Edge Functions

### Add Edge Functions Configuration

In your `supabase/config.toml`, add:

```toml
[functions.telegram-webhook]
verify_jwt = false

[functions.verify-otp]
verify_jwt = false
```

### Create Edge Functions

Create these edge functions in your `supabase/functions/` directory:

#### Telegram Webhook (`supabase/functions/telegram-webhook/index.ts`)

```typescript
import { serve } from "https://deno.land/std@0.168.0/http/server.ts";
import { createClient } from "https://esm.sh/@supabase/supabase-js@2";

const corsHeaders = {
  "Access-Control-Allow-Origin": "*",
  "Access-Control-Allow-Headers":
    "authorization, x-client-info, apikey, content-type",
};

serve(async (req) => {
  if (req.method === "OPTIONS") {
    return new Response(null, { headers: corsHeaders });
  }

  try {
    const requestBody = await req.json();
    const botToken = Deno.env.get("TELEGRAM_BOT_TOKEN");
    const supabaseUrl = Deno.env.get("SUPABASE_URL");
    const supabaseKey = Deno.env.get("SUPABASE_SERVICE_ROLE_KEY");

    if (!botToken || !supabaseUrl || !supabaseKey) {
      return new Response(
        JSON.stringify({ error: "Missing required environment variables" }),
        { status: 500, headers: corsHeaders }
      );
    }

    const supabase = createClient(supabaseUrl, supabaseKey);

    // Handle webhook setup
    if (requestBody.action === "setup_webhook") {
      const webhookUrl = `${supabaseUrl}/functions/v1/telegram-webhook`;
      const telegramApiUrl = `https://api.telegram.org/bot${botToken}/setWebhook`;

      const response = await fetch(telegramApiUrl, {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ url: webhookUrl }),
      });

      const result = await response.json();
      return new Response(JSON.stringify(result), {
        headers: { ...corsHeaders, "Content-Type": "application/json" },
      });
    }

    // Handle verification session creation
    if (requestBody.phone_number && !requestBody.message) {
      const { data: session, error } = await supabase
        .from("verification_sessions")
        .insert({
          phone_number: requestBody.phone_number,
          expires_at: new Date(Date.now() + 10 * 60 * 1000).toISOString(),
        })
        .select()
        .single();

      if (error) {
        return new Response(
          JSON.stringify({ error: "Failed to create verification session" }),
          { status: 500, headers: corsHeaders }
        );
      }

      return new Response(JSON.stringify({ session_id: session.id }), {
        headers: corsHeaders,
      });
    }

    // Handle Telegram updates (messages, contacts, etc.)
    const update = requestBody;

    if (update.message?.contact) {
      const contact = update.message.contact;
      const chatId = update.message.chat.id;
      const userId = update.message.from.id;
      const phoneNumber = contact.phone_number.startsWith("+")
        ? contact.phone_number
        : "+" + contact.phone_number;

      // Generate OTP
      const otpCode = Math.floor(100000 + Math.random() * 900000).toString();

      // Update verification session
      await supabase
        .from("verification_sessions")
        .update({
          telegram_user_id: userId,
          telegram_chat_id: chatId,
          otp_code: otpCode,
          expires_at: new Date(Date.now() + 5 * 60 * 1000).toISOString(),
        })
        .eq("phone_number", phoneNumber);

      // Send OTP to user
      await fetch(`https://api.telegram.org/bot${botToken}/sendMessage`, {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({
          chat_id: chatId,
          text: `Your OTP code is: ${otpCode}`,
          reply_markup: { remove_keyboard: true },
        }),
      });
    }

    return new Response("OK", { headers: corsHeaders });
  } catch (error) {
    console.error("Webhook error:", error);
    return new Response("Internal Server Error", {
      status: 500,
      headers: corsHeaders,
    });
  }
});
```

#### OTP Verification (`supabase/functions/verify-otp/index.ts`)

```typescript
import { serve } from "https://deno.land/std@0.168.0/http/server.ts";
import { createClient } from "https://esm.sh/@supabase/supabase-js@2";

const corsHeaders = {
  "Access-Control-Allow-Origin": "*",
  "Access-Control-Allow-Headers":
    "authorization, x-client-info, apikey, content-type",
};

serve(async (req) => {
  if (req.method === "OPTIONS") {
    return new Response(null, { headers: corsHeaders });
  }

  try {
    const { phone_number, otp_code } = await req.json();

    if (!phone_number || !otp_code) {
      return new Response(
        JSON.stringify({ error: "Phone number and OTP are required" }),
        { status: 400, headers: corsHeaders }
      );
    }

    const supabaseUrl = Deno.env.get("SUPABASE_URL");
    const supabaseKey = Deno.env.get("SUPABASE_SERVICE_ROLE_KEY");

    if (!supabaseUrl || !supabaseKey) {
      return new Response(
        JSON.stringify({ error: "Server configuration error" }),
        { status: 500, headers: corsHeaders }
      );
    }

    const supabase = createClient(supabaseUrl, supabaseKey);

    // Verify OTP
    const { data: session, error } = await supabase
      .from("verification_sessions")
      .select("*")
      .eq("phone_number", phone_number)
      .eq("otp_code", otp_code)
      .eq("verified", false)
      .gt("expires_at", new Date().toISOString())
      .single();

    if (error || !session) {
      return new Response(JSON.stringify({ error: "Invalid or expired OTP" }), {
        status: 400,
        headers: corsHeaders,
      });
    }

    // Mark as verified
    await supabase
      .from("verification_sessions")
      .update({ verified: true })
      .eq("id", session.id);

    // Create or update user
    const { data: user, error: userError } =
      await supabase.auth.admin.createUser({
        phone: phone_number,
        phone_confirm: true,
        user_metadata: {
          phone_verified: true,
          telegram_user_id: session.telegram_user_id,
        },
      });

    return new Response(
      JSON.stringify({
        success: true,
        message: "Phone number verified successfully",
        user: user?.user,
      }),
      { headers: corsHeaders }
    );
  } catch (error) {
    console.error("Verification error:", error);
    return new Response(JSON.stringify({ error: "Internal server error" }), {
      status: 500,
      headers: corsHeaders,
    });
  }
});
```

## Step 7: Set Up Environment Variables

In your Supabase Dashboard > Settings > Edge Functions, add:

- `TELEGRAM_BOT_TOKEN`: Your bot token from Step 5

## Step 8: Set Up Webhook

Set your bot webhook by calling your edge function:

```bash
curl -X POST "https://YOUR_PROJECT_ID.supabase.co/functions/v1/telegram-webhook" \
  -H "Content-Type: application/json" \
  -d '{"action": "setup_webhook"}'
```

## Step 9: Integration

### Basic Setup

```tsx
// In your main App.tsx or layout file
import { TelegramVerificationProvider } from "gebeya-telegram-otp";
import { supabase } from "./lib/supabase";

function App() {
  return (
    <TelegramVerificationProvider
      supabaseClient={supabase}
      telegramConfig={{ botName: "@your_bot_name" }}
      onSuccess={(userData) => {
        console.log("Verification successful:", userData);
      }}
      onError={(error) => {
        console.error("Verification error:", error);
      }}
    >
      <YourAppContent />
    </TelegramVerificationProvider>
  );
}

export default App;
```

### Using the Verification Button

```tsx
import { TelegramVerifyButton } from "gebeya-telegram-otp";

function LoginPage() {
  return (
    <div className="flex items-center justify-center min-h-screen">
      <div className="p-8 max-w-md mx-auto">
        <h1 className="text-2xl font-bold mb-6 text-center">Sign In</h1>
        <TelegramVerifyButton
          buttonText="Verify with Telegram"
          variant="default"
          size="lg"
          className="w-full"
          onVerificationComplete={(userData) => {
            console.log("User verified:", userData);
            // Redirect to dashboard or update app state
          }}
        />
      </div>
    </div>
  );
}

export default LoginPage;
```

### TypeScript Support

The package includes full TypeScript definitions:

```tsx
import {
  TelegramVerifyButton,
  TelegramVerificationProvider,
  type TelegramVerificationData,
  type TelegramConfig,
} from "gebeya-telegram-otp";

// Types are automatically available
const config: TelegramConfig = {
  botName: "@your_bot_name",
};

const handleSuccess = (userData: TelegramVerificationData) => {
  // userData is fully typed
  console.log("User ID:", userData.user.id);
  console.log("Phone:", userData.user.phone);
};
```

## Verification Complete! 🎉

Your application should now be ready to use Telegram verification. The package will handle:

- Phone number input with country selection
- QR code generation for Telegram verification
- OTP verification process
- Success handling

## Troubleshooting

### Common Issues

1. **Missing styles**: Ensure Tailwind CSS is properly configured with the package path
2. **Supabase errors**: Check your database setup and RLS policies
3. **Telegram bot issues**: Verify your bot token and webhook setup
4. **Import errors**: Make sure all peer dependencies are installed
5. **Edge function errors**: Check your Supabase function logs for detailed error messages

### Debug Steps

1. Check Supabase edge function logs in your dashboard
2. Test webhook manually with curl
3. Verify database entries in verification_sessions table
4. Check Telegram bot settings with [@BotFather](https://t.me/botfather)
5. Ensure all environment variables are properly set

## Security Considerations

1. Never expose bot token in client-side code
2. Implement rate limiting for verification attempts
3. Set appropriate session expiry times
4. Use HTTPS for all webhook URLs
5. Validate phone numbers on both client and server

## Next Steps

- Customize styling to match your app
- Add additional security measures
- Implement user profiles
- Add multi-language support
- Set up monitoring and analytics

For more detailed setup instructions, see the [setup-guide.md](./setup-guide.md) file.
