import { Pool, QueryResult } from 'pg';

// ==================================================
// Coolify PostgreSQL Connection
// ==================================================

const DATABASE_URL = process.env.DATABASE_URL || 
  process.env.POSTGRES_URL ||
  'postgresql://vibn_user:password@vibn-postgres:5432/vibn';

let pool: Pool | null = null;

// Internal Docker network connections (Coolify) don't use SSL.
// Only enable SSL for external/RDS/cloud DB connections.
function getSslConfig() {
  const url = DATABASE_URL;
  if (!url) return undefined;
  // Internal Docker hostnames never use SSL
  if (url.includes('localhost') || url.includes('127.0.0.1') || 
      /postgresql:\/\/[^@]+@[a-z0-9_-]+:\d+\//.test(url)) {
    return undefined;
  }
  // External cloud DBs (RDS, AlloyDB, etc.) need SSL
  if (process.env.DB_SSL === 'true') {
    return { rejectUnauthorized: false };
  }
  return undefined;
}

export function getPool() {
  if (!pool) {
    pool = new Pool({
      connectionString: DATABASE_URL,
      ssl: getSslConfig(),
      max: 20,
      idleTimeoutMillis: 30000,
      connectionTimeoutMillis: 2000,
    });

    pool.on('error', (err) => {
      console.error('Unexpected error on idle client', err);
    });
  }
  return pool;
}

export async function query<T = any>(text: string, params?: any[]): Promise<T[]> {
  const pool = getPool();
  const result = await pool.query(text, params);
  return result.rows;
}

export async function queryOne<T = any>(text: string, params?: any[]): Promise<T | null> {
  const rows = await query<T>(text, params);
  return rows[0] || null;
}

// ==================================================
// User operations (replaces Firebase auth.ts)
// ==================================================

export interface User {
  id: number;
  uid: string;
  email: string;
  display_name?: string;
  photo_url?: string;
  workspace: string;
  created_at: Date;
  updated_at: Date;
}

export async function createUser(data: {
  email: string;
  password_hash?: string;
  display_name?: string;
  photo_url?: string;
  workspace: string;
  google_id?: string;
  github_id?: string;
}): Promise<User> {
  const uid = `user-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
  
  const result = await query<User>(`
    INSERT INTO users (uid, email, password_hash, display_name, photo_url, workspace, google_id, github_id)
    VALUES ($1, $2, $3, $4, $5, $6, $7, $8)
    RETURNING *
  `, [uid, data.email, data.password_hash, data.display_name, data.photo_url, data.workspace, data.google_id, data.github_id]);
  
  return result[0];
}

export async function getUserByEmail(email: string): Promise<User | null> {
  return await queryOne<User>('SELECT * FROM users WHERE email = $1', [email]);
}

export async function getUserByUid(uid: string): Promise<User | null> {
  return await queryOne<User>('SELECT * FROM users WHERE uid = $1', [uid]);
}

export async function getUserById(id: number): Promise<User | null> {
  return await queryOne<User>('SELECT * FROM users WHERE id = $1', [id]);
}

export async function updateUser(id: number, data: Partial<User>): Promise<User | null> {
  const fields = Object.keys(data).filter(k => k !== 'id' && k !== 'uid' && k !== 'created_at');
  const values = fields.map((_, i) => `$${i + 2}`);
  const setClause = fields.map((f, i) => `${f} = ${values[i]}`).join(', ');
  
  const result = await query<User>(`
    UPDATE users 
    SET ${setClause}, updated_at = NOW()
    WHERE id = $1
    RETURNING *
  `, [id, ...fields.map(f => (data as any)[f])]);
  
  return result[0] || null;
}

// ==================================================
// Project operations (replaces Firebase collections.ts)
// ==================================================

export interface Project {
  id: number;
  firebase_id?: string;
  client_id?: number;
  user_id: number;
  name: string;
  slug: string;
  workspace: string;
  product_name: string;
  product_vision?: string;
  status: string;
  current_phase: string;
  phase_status: string;
  github_repo?: string;
  chatgpt_project_id?: string;
  gitea_repo_url?: string;
  coolify_app_id?: string;
  deployment_url?: string;
  phase_data: any;
  created_at: Date;
  updated_at: Date;
}

export async function createProject(data: Omit<Project, 'id' | 'created_at' | 'updated_at'>): Promise<Project> {
  const result = await query<Project>(`
    INSERT INTO projects (
      user_id, name, slug, workspace, product_name, product_vision, 
      status, current_phase, phase_status, phase_data
    )
    VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)
    RETURNING *
  `, [
    data.user_id, data.name, data.slug, data.workspace, data.product_name, 
    data.product_vision, data.status || 'active', data.current_phase || 'collection',
    data.phase_status || 'not_started', JSON.stringify(data.phase_data || {})
  ]);
  
  return result[0];
}

export async function getProject(id: number): Promise<Project | null> {
  return await queryOne<Project>('SELECT * FROM projects WHERE id = $1', [id]);
}

export async function getUserProjects(userId: number): Promise<Project[]> {
  return await query<Project>('SELECT * FROM projects WHERE user_id = $1 ORDER BY updated_at DESC', [userId]);
}

export async function updateProject(id: number, data: Partial<Project>): Promise<Project | null> {
  const fields = Object.keys(data).filter(k => !['id', 'created_at', 'updated_at'].includes(k));
  const values = fields.map((_, i) => `$${i + 2}`);
  const setClause = fields.map((f, i) => `${f} = ${values[i]}`).join(', ');
  
  const fieldValues = fields.map(f => {
    const val = (data as any)[f];
    return (f === 'phase_data' && typeof val === 'object') ? JSON.stringify(val) : val;
  });
  
  const result = await query<Project>(`
    UPDATE projects 
    SET ${setClause}, updated_at = NOW()
    WHERE id = $1
    RETURNING *
  `, [id, ...fieldValues]);
  
  return result[0] || null;
}

// ==================================================
// Session operations (replaces Firebase + Railway logging)
// ==================================================

export interface Session {
  id: number;
  session_id: string;
  project_id?: number;
  user_id: number;
  started_at: Date;
  ended_at?: Date;
  duration_minutes: number;
  workspace_path?: string;
  workspace_name?: string;
  conversation: any[];
  total_tokens: number;
  estimated_cost_usd: number;
  model: string;
  summary?: string;
}

export async function createSession(data: {
  session_id: string;
  project_id?: number;
  user_id: number;
  workspace_path?: string;
  workspace_name?: string;
  model?: string;
}): Promise<Session> {
  const result = await query<Session>(`
    INSERT INTO sessions (session_id, project_id, user_id, workspace_path, workspace_name, model)
    VALUES ($1, $2, $3, $4, $5, $6)
    RETURNING *
  `, [data.session_id, data.project_id, data.user_id, data.workspace_path, data.workspace_name, data.model || 'unknown']);
  
  return result[0];
}

export async function getSession(sessionId: string): Promise<Session | null> {
  return await queryOne<Session>('SELECT * FROM sessions WHERE session_id = $1', [sessionId]);
}

export async function getProjectSessions(projectId: number): Promise<Session[]> {
  return await query<Session>(
    'SELECT * FROM sessions WHERE project_id = $1 ORDER BY started_at DESC',
    [projectId]
  );
}

export async function updateSession(sessionId: string, data: {
  conversation?: any[];
  total_tokens?: number;
  estimated_cost_usd?: number;
  ended_at?: Date;
  duration_minutes?: number;
  summary?: string;
}): Promise<Session | null> {
  const fields = Object.keys(data);
  const values = fields.map((_, i) => `$${i + 2}`);
  const setClause = fields.map((f, i) => `${f} = ${values[i]}`).join(', ');
  
  const fieldValues = fields.map(f => {
    const val = (data as any)[f];
    return (f === 'conversation' && typeof val === 'object') ? JSON.stringify(val) : val;
  });
  
  const result = await query<Session>(`
    UPDATE sessions 
    SET ${setClause}, last_updated = NOW()
    WHERE session_id = $1
    RETURNING *
  `, [sessionId, ...fieldValues]);
  
  return result[0] || null;
}

// ==================================================
// Analysis operations
// ==================================================

export interface Analysis {
  id: number;
  project_id: number;
  type: string;
  summary: string;
  tech_stack: string[];
  features: string[];
  raw_data: any;
  created_at: Date;
}

export async function createAnalysis(data: Omit<Analysis, 'id' | 'created_at'>): Promise<Analysis> {
  const result = await query<Analysis>(`
    INSERT INTO analyses (project_id, type, summary, tech_stack, features, raw_data)
    VALUES ($1, $2, $3, $4, $5, $6)
    RETURNING *
  `, [
    data.project_id, data.type, data.summary, 
    JSON.stringify(data.tech_stack), 
    JSON.stringify(data.features), 
    JSON.stringify(data.raw_data)
  ]);
  
  return result[0];
}

export async function getProjectAnalyses(projectId: number): Promise<Analysis[]> {
  return await query<Analysis>(
    'SELECT * FROM analyses WHERE project_id = $1 ORDER BY created_at DESC',
    [projectId]
  );
}

// ==================================================
// Health check
// ==================================================

export async function checkConnection(): Promise<boolean> {
  try {
    await query('SELECT 1');
    return true;
  } catch (error) {
    console.error('Database connection failed:', error);
    return false;
  }
}
