/**
 * Xtream Codes API Implementation
 * Provides compatibility with Xtream Codes protocol for music streaming clients
 * Endpoints: /api/xtream/player_api.php, /api/xtream/get.php
 */

import { Router, Request, Response } from 'express';
import {
  getXtreamUserByUsername,
  getXtreamUserStatus,
  listStreamCategories,
  listMusicTracksByCategory,
  createActiveConnection,
  getActiveConnectionsByUserId,
  countActiveConnectionsByUserId,
  deleteActiveConnection,
  updateConnectionActivity,
} from './db';
import { nanoid } from 'nanoid';

const xtreamRouter = Router();

// Utility function to generate session token
function generateSessionToken(): string {
  return nanoid(32);
}

// Utility function to get client IP
function getClientIp(req: Request): string {
  const forwarded = req.headers['x-forwarded-for'];
  if (typeof forwarded === 'string') {
    return forwarded.split(',')[0].trim();
  }
  return req.socket.remoteAddress || 'unknown';
}

// Utility function to validate user credentials and check expiration
async function validateUserCredentials(
  username: string,
  password: string
): Promise<{ valid: boolean; user?: any; error?: string }> {
  const user = await getXtreamUserByUsername(username);

  if (!user) {
    return { valid: false, error: 'Invalid username or password' };
  }

  if (!user.isActive) {
    return { valid: false, error: 'User account is disabled' };
  }

  // Simple password check (in production, use bcrypt or similar)
  if (user.password !== password) {
    return { valid: false, error: 'Invalid username or password' };
  }

  // Check expiration
  const now = new Date();
  if (user.expirationDate && user.expirationDate < now) {
    return { valid: false, error: 'User account has expired' };
  }

  return { valid: true, user };
}

// Utility function to check connection limit
async function checkConnectionLimit(
  userId: number,
  maxConnections: number
): Promise<{ allowed: boolean; error?: string }> {
  const activeCount = await countActiveConnectionsByUserId(userId);

  if (activeCount >= maxConnections) {
    return {
      allowed: false,
      error: `Maximum concurrent connections (${maxConnections}) reached`,
    };
  }

  return { allowed: true };
}

/**
 * GET /api/xtream/player_api.php
 * Main authentication and data retrieval endpoint
 * Parameters:
 * - username: Client username
 * - password: Client password
 * - action: 'get_live_categories', 'get_vod_categories', 'get_series_categories', 'get_live_streams', etc.
 * - category_id: Category ID for filtering
 */
xtreamRouter.get('/player_api.php', async (req: Request, res: Response) => {
  try {
    const { username, password, action, category_id } = req.query;

    // Validate required parameters
    if (!username || !password) {
      return res.status(401).json({
        user_info: {
          status: 'error',
          message: 'Missing username or password',
        },
      });
    }

    // Validate credentials
    const validation = await validateUserCredentials(
      String(username),
      String(password)
    );

    if (!validation.valid) {
      return res.status(401).json({
        user_info: {
          status: 'error',
          message: validation.error,
        },
      });
    }

    const user = validation.user!;

    // Check connection limit
    const connCheck = await checkConnectionLimit(user.id, user.maxConnections);
    if (!connCheck.allowed) {
      return res.status(429).json({
        user_info: {
          status: 'error',
          message: connCheck.error,
        },
      });
    }

    // Create or update session
    const sessionToken = generateSessionToken();
    const clientIp = getClientIp(req);
    const userAgent = req.headers['user-agent'] || 'unknown';

    await createActiveConnection({
      userId: user.id,
      sessionToken,
      ipAddress: clientIp,
      userAgent,
    });

    // Handle different actions
    if (action === 'get_live_categories' || action === 'get_vod_categories' || action === 'get_series_categories') {
      const categories = await listStreamCategories();
      const filtered = categories.filter((cat) => {
        if (action === 'get_live_categories') return cat.categoryType === 'live';
        if (action === 'get_vod_categories') return cat.categoryType === 'vod';
        if (action === 'get_series_categories') return cat.categoryType === 'series';
        return true;
      });

      return res.json(filtered);
    }

    if (action === 'get_live_streams' || action === 'get_vod_streams') {
      const catId = Number(category_id);
      if (!catId) {
        return res.status(400).json({ error: 'Missing category_id' });
      }

      const tracks = await listMusicTracksByCategory(catId);
      const formatted = tracks.map((track) => ({
        num: track.id,
        name: track.title,
        stream_type: 'music',
        stream_id: track.id,
        stream_icon: track.thumbnailUrl || '',
        epg_channel_id: '',
        added: track.createdAt.toISOString(),
        category_id: track.categoryId,
        custom_sid: '',
        tv_archive: 0,
        direct_source: '',
        bitrate: 0,
      }));

      return res.json(formatted);
    }

    // Default: return user info
    const userStatus = await getXtreamUserStatus(user.id);
    res.json({
      user_info: {
        username: user.username,
        max_connections: user.maxConnections,
        active_connections: await countActiveConnectionsByUserId(user.id),
        expiration_date: user.expirationDate
          ? Math.floor(user.expirationDate.getTime() / 1000)
          : 0,
        is_trial: 0,
        is_active: user.isActive ? 1 : 0,
        status: 'Active',
      },
      server_info: {
        name: 'Xtream Music System',
        version: '1.0.0',
        api_version: '1.0',
      },
    });
  } catch (error) {
    console.error('[Xtream API] Error:', error);
    res.status(500).json({
      user_info: {
        status: 'error',
        message: 'Internal server error',
      },
    });
  }
});

/**
 * GET /api/xtream/get.php
 * Stream URL retrieval endpoint
 * Parameters:
 * - username: Client username
 * - password: Client password
 * - type: 'live', 'vod', 'series', 'music'
 * - stream_id: Stream/Track ID
 */
xtreamRouter.get('/get.php', async (req: Request, res: Response) => {
  try {
    const { username, password, type, stream_id } = req.query;

    // Validate required parameters
    if (!username || !password || !stream_id) {
      return res.status(400).json({ error: 'Missing required parameters' });
    }

    // Validate credentials
    const validation = await validateUserCredentials(
      String(username),
      String(password)
    );

    if (!validation.valid) {
      return res.status(401).json({ error: validation.error });
    }

    const user = validation.user!;

    // Update connection activity
    const connections = await getActiveConnectionsByUserId(user.id);
    if (connections.length > 0) {
      await updateConnectionActivity(connections[0].sessionToken);
    }

    // For now, redirect to the stream URL stored in database
    // In production, you might want to add additional security or proxying
    res.json({
      status: 'success',
      stream_id: stream_id,
      type: type || 'music',
      // The actual stream URL should be fetched from the database
      // and potentially proxied through your server for security
    });
  } catch (error) {
    console.error('[Xtream API] Error:', error);
    res.status(500).json({ error: 'Internal server error' });
  }
});

/**
 * GET /api/xtream/logout.php
 * Logout endpoint to close session
 */
xtreamRouter.get('/logout.php', async (req: Request, res: Response) => {
  try {
    const { username, password, session_id } = req.query;

    if (!session_id) {
      return res.status(400).json({ error: 'Missing session_id' });
    }

    await deleteActiveConnection(String(session_id));

    res.json({ status: 'success', message: 'Logged out successfully' });
  } catch (error) {
    console.error('[Xtream API] Error:', error);
    res.status(500).json({ error: 'Internal server error' });
  }
});

export default xtreamRouter;
