/**
 * Metabase integration service.
 * Automatically registers newly-provisioned tenant databases in Metabase.
 */

const METABASE_URL = process.env.METABASE_URL || 'http://192.168.10.170:3000';
const METABASE_USERNAME = process.env.METABASE_USERNAME || 'ialcarazsalazar@consultoria-as.com';
const METABASE_PASSWORD = process.env.METABASE_PASSWORD || '';

// PostgreSQL connection details exposed to Metabase
const PG_HOST = process.env.METABASE_PG_HOST || '192.168.10.90';
const PG_PORT = parseInt(process.env.METABASE_PG_PORT || '5432', 10);
const PG_USER = process.env.METABASE_PG_USER || 'postgres';
const PG_PASSWORD = process.env.METABASE_PG_PASSWORD || '';

let cachedSessionToken: string | null = null;
let tokenExpiresAt = 0;

async function getSessionToken(): Promise<string | null> {
  // Re-use cached token if still valid (Metabase sessions last 2 weeks by default)
  if (cachedSessionToken && Date.now() < tokenExpiresAt) {
    return cachedSessionToken;
  }

  if (!METABASE_PASSWORD) {
    console.error('[METABASE] METABASE_PASSWORD not configured');
    return null;
  }

  try {
    const res = await fetch(`${METABASE_URL}/api/session`, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        username: METABASE_USERNAME,
        password: METABASE_PASSWORD,
      }),
    });

    if (!res.ok) {
      const text = await res.text();
      console.error(`[METABASE] Auth failed: ${res.status} ${text}`);
      return null;
    }

    const data = await res.json() as { id?: string };
    if (!data.id) {
      console.error('[METABASE] Auth response missing session id');
      return null;
    }

    cachedSessionToken = data.id;
    tokenExpiresAt = Date.now() + 13 * 24 * 60 * 60 * 1000; // 13 days
    return cachedSessionToken;
  } catch (err) {
    console.error('[METABASE] Error fetching session token:', err);
    return null;
  }
}

interface RegisterDatabaseInput {
  nombre: string;
  dbName: string;
}

export async function registerDatabase(input: RegisterDatabaseInput): Promise<void> {
  const sessionToken = await getSessionToken();
  if (!sessionToken) {
    console.error('[METABASE] Skipping database registration — no session token');
    return;
  }

  if (!PG_PASSWORD) {
    console.error('[METABASE] METABASE_PG_PASSWORD not configured');
    return;
  }

  const payload = {
    name: input.nombre,
    engine: 'postgres',
    details: {
      host: PG_HOST,
      port: PG_PORT,
      dbname: input.dbName,
      user: PG_USER,
      password: PG_PASSWORD,
      ssl: false,
      'tunnel-enabled': false,
      'advanced-options': false,
      'schema-filters-type': 'all',
    },
    auto_run_queries: true,
    is_full_sync: true,
    is_on_demand: false,
  };

  try {
    const res = await fetch(`${METABASE_URL}/api/database`, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'X-Metabase-Session': sessionToken,
      },
      body: JSON.stringify(payload),
    });

    if (!res.ok) {
      const text = await res.text();
      // 409 or duplicate name is not fatal — log and continue
      if (res.status === 400 && text.includes('already exists')) {
        console.log(`[METABASE] Database "${input.nombre}" already registered`);
        return;
      }
      console.error(`[METABASE] Register database failed: ${res.status} ${text}`);
      return;
    }

    const data = await res.json() as { id?: number };
    console.log(`[METABASE] Database "${input.nombre}" registered with id=${data.id}`);
  } catch (err) {
    console.error('[METABASE] Error registering database:', err);
  }
}

export async function deleteDatabase(databaseName: string): Promise<void> {
  const sessionToken = await getSessionToken();
  if (!sessionToken) {
    console.error('[METABASE] Skipping database deletion — no session token');
    return;
  }

  try {
    // Find database by name
    const listRes = await fetch(`${METABASE_URL}/api/database`, {
      headers: { 'X-Metabase-Session': sessionToken },
    });

    if (!listRes.ok) {
      console.error(`[METABASE] Failed to list databases: ${listRes.status}`);
      return;
    }

    const listData = await listRes.json() as { data?: Array<{ id: number; name: string; details?: { dbname?: string } }> };
    const db = listData.data?.find(
      (d) => d.details?.dbname === databaseName || d.name.includes(databaseName)
    );

    if (!db) {
      console.log(`[METABASE] No database found for ${databaseName}`);
      return;
    }

    const deleteRes = await fetch(`${METABASE_URL}/api/database/${db.id}`, {
      method: 'DELETE',
      headers: { 'X-Metabase-Session': sessionToken },
    });

    if (!deleteRes.ok) {
      console.error(`[METABASE] Delete database failed: ${deleteRes.status}`);
      return;
    }

    console.log(`[METABASE] Database ${db.id} (${databaseName}) deleted`);
  } catch (err) {
    console.error('[METABASE] Error deleting database:', err);
  }
}
