const { Client } = require('pg');
const fs = require('fs');
const path = require('path');
require('dotenv').config({ path: '/root/miaojingAI/.env.local' });
const c = new Client({ connectionString: process.env.LOCAL_DB_URL });
const root = '/root/miaojingAI';
function storageKeyFromUrl(url) {
  if (!url || typeof url !== 'string') return null;
  const marker = '/api/local-storage/';
  const idx = url.indexOf(marker);
  if (idx < 0) return null;
  try { return decodeURIComponent(url.slice(idx + marker.length).split('?')[0]); } catch { return null; }
}
async function query(name, sql, params=[]) {
  try { const r = await c.query(sql, params); return { name, rows: r.rows }; }
  catch (e) { return { name, error: e.message }; }
}
(async () => {
  await c.connect();
  const out = {};
  out.db = await query('db', `select current_database() as database, current_user as user, now() as checked_at`);
  out.tables = await query('tables', `select schemaname, tablename from pg_tables where schemaname in ('public','auth') order by schemaname, tablename`);
  const tableNames = out.tables.rows || [];
  out.counts = [];
  for (const t of tableNames) {
    const full = t.schemaname === 'public' ? t.tablename : `${t.schemaname}.${t.tablename}`;
    const r = await query(full, `select count(*)::int as count from ${full}`);
    out.counts.push({ table: full, count: r.rows?.[0]?.count ?? null, error: r.error });
  }
  out.admins = await query('admins', `select id,email,nickname,role,membership_tier,is_active,created_at,updated_at from profiles where role='admin' or email in ('admin@example.com','admin@miaojing.ai') order by created_at`);
  out.authAdmins = await query('auth_admins', `select id,email,created_at, password_hash is not null as has_password from auth.users where email in ('admin@example.com','admin@miaojing.ai') order by created_at`);
  out.profileWithoutAuth = await query('profile_without_auth', `select p.id,p.email,p.role from profiles p left join auth.users u on u.id=p.id where u.id is null order by p.created_at limit 50`);
  out.authWithoutProfile = await query('auth_without_profile', `select u.id,u.email from auth.users u left join profiles p on p.id=u.id where p.id is null order by u.created_at limit 50`);
  out.worksMissingUser = await query('works_missing_user', `select w.id,w.user_id,w.title,w.type,w.status,w.created_at from works w left join profiles p on p.id=w.user_id where w.user_id is not null and p.id is null order by w.created_at desc limit 50`);
  out.worksNullUser = await query('works_null_user', `select id,title,type,status,created_at from works where user_id is null order by created_at desc limit 50`);
  out.worksByStatus = await query('works_by_status', `select status, count(*)::int from works group by status order by status`);
  out.worksByUser = await query('works_by_user', `select p.email,p.nickname,w.user_id,count(*)::int as works from works w left join profiles p on p.id=w.user_id group by p.email,p.nickname,w.user_id order by works desc nulls last limit 20`);
  out.workLikesMissing = await query('work_likes_missing_refs', `select wl.id,wl.user_id,wl.work_id from work_likes wl left join profiles p on p.id=wl.user_id left join works w on w.id=wl.work_id where p.id is null or w.id is null limit 50`);
  out.creditMissingUser = await query('credit_missing_user', `select ct.id,ct.user_id,ct.amount,ct.type,ct.created_at from credit_transactions ct left join profiles p on p.id=ct.user_id where p.id is null limit 50`);
  out.ordersMissingUser = await query('orders_missing_user', `select o.id,o.user_id,o.order_no,o.status,o.created_at from orders o left join profiles p on p.id=o.user_id where o.user_id is not null and p.id is null limit 50`);
  out.apiKeysMissingUser = await query('api_keys_missing_user', `select k.id,k.user_id,k.provider,k.type from user_api_keys k left join profiles p on p.id=k.user_id where p.id is null limit 50`);
  out.jobsMissingUser = await query('jobs_missing_user', `select j.id,j.user_id,j.type,j.status,j.created_at from generation_jobs j left join profiles p on p.id=j.user_id where j.user_id is not null and p.id is null order by j.created_at desc limit 50`);
  out.jobsNullUser = await query('jobs_null_user', `select id,type,status,created_at from generation_jobs where user_id is null order by created_at desc limit 50`);
  out.jobsByUser = await query('jobs_by_user', `select p.email,p.nickname,j.user_id,count(*)::int as jobs from generation_jobs j left join profiles p on p.id=j.user_id group by p.email,p.nickname,j.user_id order by jobs desc nulls last limit 20`);
  out.worksFileCheck = { totalLocalUrls: 0, missing: [] };
  const works = await query('works_urls', `select id,result_url,thumbnail_url from works order by created_at desc`);
  for (const w of works.rows || []) {
    for (const field of ['result_url','thumbnail_url']) {
      const key = storageKeyFromUrl(w[field]);
      if (!key) continue;
      out.worksFileCheck.totalLocalUrls++;
      const abs = path.join(root, 'local-storage', key);
      if (!fs.existsSync(abs)) out.worksFileCheck.missing.push({ workId: w.id, field, key });
    }
  }
  out.storage = {
    localStorageExists: fs.existsSync(path.join(root,'local-storage')),
    backupsExists: fs.existsSync(path.join(root,'backups')),
    localFiles: 0,
    galleryFiles: 0,
  };
  function walk(dir) { if (!fs.existsSync(dir)) return 0; let n=0; for (const e of fs.readdirSync(dir,{withFileTypes:true})) { const p=path.join(dir,e.name); n += e.isDirectory()?walk(p):1; } return n; }
  out.storage.localFiles = walk(path.join(root,'local-storage'));
  out.storage.galleryFiles = walk(path.join(root,'local-storage','gallery'));
  console.log(JSON.stringify(out, null, 2));
  await c.end();
})().catch(e => { console.error(e); process.exit(1); });
