const { Pool } = require('pg');
require('dotenv').config({ path: '.env.local' });

const SYSTEM_USER_ID = '00000000-0000-0000-0000-000000000000';

function short(value, length = 160) {
  if (value == null) return value;
  const text = typeof value === 'string' ? value : JSON.stringify(value);
  return text.length > length ? `${text.slice(0, length)}...` : text;
}

async function main() {
  const pool = new Pool({ connectionString: process.env.LOCAL_DB_URL });
  const client = await pool.connect();
  try {
    const tableColumns = await client.query(`
      SELECT table_schema, table_name, column_name, data_type
      FROM information_schema.columns
      WHERE (table_schema = 'public' AND table_name IN ('profiles', 'works', 'user_api_keys', 'orders', 'credit_transactions'))
         OR (table_schema = 'auth' AND table_name = 'users')
      ORDER BY table_schema, table_name, ordinal_position
    `);

    const userSummary = await client.query(`
      SELECT
        (SELECT COUNT(*)::int FROM auth.users) AS auth_users,
        (SELECT COUNT(*)::int FROM profiles) AS profiles,
        (SELECT COUNT(*)::int FROM profiles WHERE role = 'admin') AS admins,
        (SELECT COUNT(*)::int FROM profiles WHERE role <> 'admin') AS non_admin_profiles,
        (SELECT COUNT(*)::int FROM auth.users u LEFT JOIN profiles p ON p.id = u.id WHERE p.id IS NULL) AS auth_without_profile,
        (SELECT COUNT(*)::int FROM profiles p LEFT JOIN auth.users u ON u.id = p.id WHERE u.id IS NULL) AS profile_without_auth,
        (SELECT COUNT(*)::int FROM auth.users WHERE password_hash IS NULL OR password_hash = '') AS auth_without_password_hash,
        (SELECT COUNT(*)::int FROM auth.users WHERE password_hash IS NOT NULL AND password_hash <> '') AS auth_with_password_hash
    `);

    const userSamples = await client.query(`
      SELECT p.id, p.email, p.nickname, p.role, p.membership_tier, p.is_active,
             u.id IS NOT NULL AS has_auth,
             (u.password_hash IS NOT NULL AND u.password_hash <> '') AS has_password_hash,
             p.created_at
      FROM profiles p
      LEFT JOIN auth.users u ON u.id = p.id
      ORDER BY p.created_at DESC NULLS LAST
      LIMIT 80
    `);

    const workSummary = await client.query(`
      SELECT
        COUNT(*)::int AS total,
        COUNT(*) FILTER (WHERE status = 'completed')::int AS completed,
        COUNT(*) FILTER (WHERE is_public = true AND status = 'completed')::int AS public_completed,
        COUNT(*) FILTER (WHERE is_public = false AND status = 'completed')::int AS private_completed,
        COUNT(*) FILTER (WHERE user_id IS NULL)::int AS null_user_id,
        COUNT(*) FILTER (WHERE user_id = $1)::int AS system_user_id,
        COUNT(*) FILTER (WHERE p.id IS NULL)::int AS missing_profile,
        COUNT(*) FILTER (WHERE p.id IS NOT NULL)::int AS linked_profile
      FROM works w
      LEFT JOIN profiles p ON p.id = w.user_id
    `, [SYSTEM_USER_ID]);

    const publicWorkSummary = await client.query(`
      SELECT
        COUNT(*)::int AS public_total,
        COUNT(*) FILTER (WHERE w.user_id IS NULL)::int AS null_user_id,
        COUNT(*) FILTER (WHERE w.user_id = $1)::int AS system_user_id,
        COUNT(*) FILTER (WHERE p.id IS NULL)::int AS missing_profile,
        COUNT(*) FILTER (WHERE p.id IS NOT NULL)::int AS linked_profile
      FROM works w
      LEFT JOIN profiles p ON p.id = w.user_id
      WHERE w.is_public = true AND w.status = 'completed'
    `, [SYSTEM_USER_ID]);

    const workByUser = await client.query(`
      SELECT
        COALESCE(p.email, '[missing-profile]') AS email,
        COALESCE(p.nickname, '') AS nickname,
        COALESCE(p.role, '') AS role,
        w.user_id,
        COUNT(*)::int AS total_works,
        COUNT(*) FILTER (WHERE w.status = 'completed')::int AS completed_works,
        COUNT(*) FILTER (WHERE w.is_public = true AND w.status = 'completed')::int AS public_works,
        COUNT(*) FILTER (WHERE w.is_public = false AND w.status = 'completed')::int AS history_works
      FROM works w
      LEFT JOIN profiles p ON p.id = w.user_id
      GROUP BY w.user_id, p.email, p.nickname, p.role
      ORDER BY total_works DESC
      LIMIT 120
    `);

    const orphanSamples = await client.query(`
      SELECT w.id, w.user_id, w.type, w.status, w.is_public, w.result_url,
             LEFT(COALESCE(w.prompt, ''), 140) AS prompt,
             w.params,
             w.created_at
      FROM works w
      LEFT JOIN profiles p ON p.id = w.user_id
      WHERE p.id IS NULL OR w.user_id = $1 OR w.user_id IS NULL
      ORDER BY w.created_at DESC NULLS LAST
      LIMIT 80
    `, [SYSTEM_USER_ID]);

    const paramKeys = await client.query(`
      SELECT key, COUNT(*)::int AS count
      FROM works w
      CROSS JOIN LATERAL jsonb_object_keys(COALESCE(w.params, '{}'::jsonb)) AS key
      LEFT JOIN profiles p ON p.id = w.user_id
      WHERE w.is_public = true
        AND w.status = 'completed'
        AND (p.id IS NULL OR w.user_id = $1 OR w.user_id IS NULL)
      GROUP BY key
      ORDER BY count DESC, key
      LIMIT 80
    `, [SYSTEM_USER_ID]);

    const possibleOwnerFields = await client.query(`
      SELECT
        id,
        user_id,
        params->>'user_id' AS params_user_id,
        params->>'userId' AS params_user_id_camel,
        params->>'publisher_id' AS publisher_id,
        params->>'publisherId' AS publisher_id_camel,
        params->>'owner_id' AS owner_id,
        params->>'ownerId' AS owner_id_camel,
        params->>'created_by' AS created_by,
        params->>'createdBy' AS created_by_camel,
        params->>'email' AS params_email,
        params->>'userEmail' AS params_user_email,
        params->>'publisherEmail' AS params_publisher_email,
        params->>'nickname' AS params_nickname,
        params->>'userName' AS params_user_name,
        LEFT(COALESCE(prompt, ''), 120) AS prompt
      FROM works
      WHERE is_public = true
        AND status = 'completed'
        AND (user_id IS NULL OR user_id = $1 OR NOT EXISTS (SELECT 1 FROM profiles p WHERE p.id = works.user_id))
      ORDER BY created_at DESC NULLS LAST
      LIMIT 80
    `, [SYSTEM_USER_ID]);

    const duplicateCandidates = await client.query(`
      SELECT
        public.id AS orphan_id,
        public.user_id AS orphan_user_id,
        private.id AS owned_id,
        private.user_id AS owner_user_id,
        p.email,
        p.nickname,
        CASE
          WHEN private.result_url = public.result_url THEN 'result_url'
          WHEN COALESCE(private.thumbnail_url, '') <> '' AND private.thumbnail_url = public.thumbnail_url THEN 'thumbnail_url'
          WHEN COALESCE(private.prompt, '') <> '' AND private.prompt = public.prompt THEN 'prompt_time'
          ELSE 'unknown'
        END AS match_type,
        ABS(EXTRACT(EPOCH FROM (private.created_at - public.created_at)))::int AS seconds_apart,
        LEFT(COALESCE(public.prompt, ''), 120) AS prompt
      FROM works public
      JOIN works private
        ON private.id <> public.id
       AND private.user_id IS NOT NULL
       AND private.user_id <> $1
       AND (
         private.result_url = public.result_url
         OR (
           COALESCE(public.thumbnail_url, '') <> ''
           AND private.thumbnail_url = public.thumbnail_url
         )
         OR (
           COALESCE(private.prompt, '') <> ''
           AND private.prompt = public.prompt
           AND private.created_at BETWEEN public.created_at - INTERVAL '30 minutes' AND public.created_at + INTERVAL '30 minutes'
         )
       )
      JOIN profiles p ON p.id = private.user_id
      LEFT JOIN profiles public_profile ON public_profile.id = public.user_id
      WHERE public.is_public = true
        AND public.status = 'completed'
        AND (public_profile.id IS NULL OR public.user_id = $1 OR public.user_id IS NULL)
      ORDER BY public.created_at DESC NULLS LAST, match_type, seconds_apart
      LIMIT 100
    `, [SYSTEM_USER_ID]);

    const output = {
      columns: tableColumns.rows,
      userSummary: userSummary.rows[0],
      userSamples: userSamples.rows,
      workSummary: workSummary.rows[0],
      publicWorkSummary: publicWorkSummary.rows[0],
      workByUser: workByUser.rows,
      orphanSamples: orphanSamples.rows.map(row => ({ ...row, result_url: short(row.result_url, 120), params: short(row.params, 300) })),
      anonymousParamKeys: paramKeys.rows,
      possibleOwnerFields: possibleOwnerFields.rows,
      duplicateCandidates: duplicateCandidates.rows,
    };

    console.log(JSON.stringify(output, null, 2));
  } finally {
    client.release();
    await pool.end();
  }
}

main().catch(error => {
  console.error(error);
  process.exit(1);
});
