import { query } from '../db';
import bcrypt from 'bcryptjs';
import { v4 as uuidv4 } from 'uuid';

export interface User {
  id: string;
  email: string;
  password_hash: string;
  telegram_username: string | null;
  telegram_chat_id: number | null;
  plan: 'free' | 'weekly' | 'monthly';
  role: 'user' | 'admin';
  stripe_customer_id: string | null;
  stripe_subscription_id: string | null;
  subscription_status: string;
  subscription_ends_at: Date | null;
  created_at: Date;
  updated_at: Date;
}

export async function createUser(
  email: string,
  password: string,
  telegramUsername?: string
): Promise<User> {
  const passwordHash = await bcrypt.hash(password, 10);
  const botToken = uuidv4().replace(/-/g, '').substring(0, 16);
  
  const normalizedEmail = email.toLowerCase().trim();

  const result = await query(
    `INSERT INTO sc_users (email, password_hash, telegram_username)
     VALUES ($1, $2, $3)
     RETURNING *`,
    [normalizedEmail, passwordHash, telegramUsername || null]
  );
  
  const user = result.rows[0];
  
  // Create bot token for user
  await query(
    `INSERT INTO sc_bot_tokens (user_id, token) VALUES ($1, $2)`,
    [user.id, botToken]
  );
  
  return user;
}

export async function findUserByEmail(email: string): Promise<User | null> {
  const result = await query(
    'SELECT * FROM sc_users WHERE email = $1',
    [email.toLowerCase().trim()]
  );
  return result.rows[0] || null;
}

export async function findUserById(id: string): Promise<User | null> {
  const result = await query(
    'SELECT * FROM sc_users WHERE id = $1',
    [id]
  );
  return result.rows[0] || null;
}

export async function findUserByTelegramChatId(chatId: number): Promise<User | null> {
  const result = await query(
    'SELECT * FROM sc_users WHERE telegram_chat_id = $1',
    [chatId]
  );
  return result.rows[0] || null;
}

export async function findUserByBotToken(token: string): Promise<User | null> {
  const result = await query(
    `SELECT u.* FROM sc_users u
     JOIN sc_bot_tokens bt ON u.id = bt.user_id
     WHERE bt.token = $1 AND bt.is_active = true`,
    [token]
  );
  return result.rows[0] || null;
}

export async function updateUserTelegram(
  userId: string,
  telegramUsername: string,
  telegramChatId: number
): Promise<void> {
  await query(
    `UPDATE sc_users 
     SET telegram_username = $1, telegram_chat_id = $2, updated_at = NOW()
     WHERE id = $3`,
    [telegramUsername, telegramChatId, userId]
  );
}

export async function updateUserPlan(
  userId: string,
  plan: 'free' | 'weekly' | 'monthly',
  stripeCustomerId?: string,
  stripeSubscriptionId?: string,
  subscriptionEndsAt?: Date
): Promise<void> {
  await query(
    `UPDATE sc_users 
     SET plan = $1, stripe_customer_id = $2, stripe_subscription_id = $3, 
         subscription_ends_at = $4, subscription_status = 'active', updated_at = NOW()
     WHERE id = $5`,
    [plan, stripeCustomerId || null, stripeSubscriptionId || null, subscriptionEndsAt || null, userId]
  );
}

export async function getUserBotToken(userId: string): Promise<string | null> {
  const result = await query(
    'SELECT token FROM sc_bot_tokens WHERE user_id = $1 AND is_active = true LIMIT 1',
    [userId]
  );
  return result.rows[0]?.token || null;
}

export async function findUserByStripeSubscriptionId(subscriptionId: string): Promise<User | null> {
  const result = await query(
    'SELECT * FROM sc_users WHERE stripe_subscription_id = $1',
    [subscriptionId]
  );
  return result.rows[0] || null;
}

export async function downgradeUser(userId: string): Promise<void> {
  await query(
    `UPDATE sc_users
     SET plan = 'free', stripe_customer_id = NULL, stripe_subscription_id = NULL,
         subscription_status = 'none', subscription_ends_at = NULL, updated_at = NOW()
     WHERE id = $1`,
    [userId]
  );
}

export async function updateSubscriptionStatus(userId: string, status: string): Promise<void> {
  await query(
    `UPDATE sc_users SET subscription_status = $1, updated_at = NOW() WHERE id = $2`,
    [status, userId]
  );
}

export async function updateSubscriptionPeriod(userId: string, endsAt: Date): Promise<void> {
  await query(
    `UPDATE sc_users
     SET subscription_ends_at = $1, subscription_status = 'active', updated_at = NOW()
     WHERE id = $2`,
    [endsAt, userId]
  );
}

export async function verifyPassword(user: User, password: string): Promise<boolean> {
  return bcrypt.compare(password, user.password_hash);
}

export async function getAllUsers(): Promise<User[]> {
  const result = await query(
    `SELECT id, email, telegram_username, telegram_chat_id, plan, role,
            subscription_status, subscription_ends_at, created_at, updated_at
     FROM sc_users ORDER BY created_at DESC`
  );
  return result.rows;
}

export async function updateUserRole(userId: string, role: 'user' | 'admin'): Promise<void> {
  await query(
    `UPDATE sc_users SET role = $1, updated_at = NOW() WHERE id = $2`,
    [role, userId]
  );
}

export async function freezeUser(userId: string, frozen: boolean): Promise<void> {
  await query(
    `UPDATE sc_users SET subscription_status = $1, updated_at = NOW() WHERE id = $2`,
    [frozen ? 'frozen' : 'active', userId]
  );
}

export async function getAdminUsers(): Promise<User[]> {
  const result = await query(
    `SELECT * FROM sc_users WHERE role = 'admin'`
  );
  return result.rows;
}
