// One-off population of a single, explicitly named presentation account with
// fictional example content across all four terminals — Trading, Portfolio,
// Capital Management and the Management Cockpit. This is not automatic
// seeding: it runs once, on request, against exactly one account, the same
// way a real user's own data gets there (a row per module in `app_state`),
// just written directly instead of through the UI.
//
// Refuses to run against any account that is not itself flagged read-only
// (`users.is_read_only`), so this can never overwrite a real user's real
// trading/portfolio/capital/management state by a mistyped email.
import 'dotenv/config';
import { and, eq } from 'drizzle-orm';
import { drizzle } from 'drizzle-orm/node-postgres';
import { Pool } from 'pg';
import { appState, users } from '../src/database/schema';
import { buildCapitalDemoState } from './demo-data/capital';
import { buildManagementDemoState } from './demo-data/management';
import { buildPortfolioDemoState } from './demo-data/portfolio';
import { buildTradingDemoState } from './demo-data/trading';

function requiredEnvironmentValue(name: string): string {
  const value = process.env[name]?.trim();
  if (!value) throw new Error(`${name} is required.`);
  return value;
}

const databaseUrl = requiredEnvironmentValue('DATABASE_URL');
const email = requiredEnvironmentValue('DEMO_ACCOUNT_EMAIL').toLowerCase();

const STATE_ENTRIES: Array<{ key: string; label: string; build: () => unknown }> = [
  { key: 'ck_trading_terminal_v10_30_live', label: 'Trading Terminal', build: buildTradingDemoState },
  { key: 'ck_portfolio_terminal_v6', label: 'Portfolio Terminal', build: buildPortfolioDemoState },
  { key: 'ck_capital_management_money_flows_v1', label: 'Capital Management', build: buildCapitalDemoState },
  { key: 'ckBusinessCockpitV6', label: 'Management Cockpit', build: buildManagementDemoState },
];

async function main(): Promise<void> {
  const pool = new Pool({
    connectionString: databaseUrl,
    ssl:
      process.env.DATABASE_SSL === 'true'
        ? { rejectUnauthorized: process.env.DATABASE_SSL_REJECT_UNAUTHORIZED !== 'false' }
        : false,
    application_name: 'ck-terminal-seed-demo-account',
  });

  try {
    const db = drizzle(pool);
    const [user] = await db
      .select({ id: users.id, email: users.email, isReadOnly: users.isReadOnly, isActive: users.isActive })
      .from(users)
      .where(eq(users.email, email))
      .limit(1);

    if (!user) {
      throw new Error(
        `No account with email ${email}. Create it first under Admin → Nutzerverwaltung, `
        + 'with "Streng schreibgeschützter Präsentationszugang" checked, then re-run this script.',
      );
    }
    if (!user.isReadOnly) {
      throw new Error(
        `${email} is not marked read-only (isReadOnly=false). Refusing to seed example data into an `
        + 'account that is not a designated presentation account — this would silently overwrite '
        + 'real data if the email were ever mistyped. Mark it read-only under Admin → '
        + 'Nutzerverwaltung first.',
      );
    }
    if (!user.isActive) {
      console.warn(`Warning: ${email} is currently deactivated. Seeding it anyway; it just cannot log in yet.`);
    }

    for (const entry of STATE_ENTRIES) {
      const value = JSON.stringify(entry.build());
      await db
        .insert(appState)
        .values({ ownerId: user.id, key: entry.key, value, updatedAt: new Date() })
        .onConflictDoUpdate({
          target: [appState.ownerId, appState.key],
          set: { value, updatedAt: new Date() },
        });
      console.log(`Wrote ${entry.label} (${entry.key}) — ${value.length} bytes.`);
    }

    // Belt and suspenders: re-check that every row actually landed on the
    // intended (read-only) account and nowhere else, using the same
    // conjunctive condition the writes above targeted.
    const written = await db
      .select({ key: appState.key })
      .from(appState)
      .where(and(eq(appState.ownerId, user.id)));
    console.log(`\n${email} now holds ${written.length} state row(s): ${written.map((row) => row.key).join(', ')}`);
  } finally {
    await pool.end();
  }
}

void main().catch((error: unknown) => {
  console.error(error instanceof Error ? error.message : error);
  process.exitCode = 1;
});
