import { Hono } from 'hono';
import { db, dbGet, dbAll, faqQuestions } from '../db/index.js';
import { eq, asc } from 'drizzle-orm';
import { requireAuth } from '../lib/auth.js';
import { getNow, generateId } from '../lib/utils.js';

const faqRouter = new Hono();

// Upper bounds for admin-supplied FAQ content (guards against accidental/abusive huge payloads)
const MAX_QUESTION_LEN = 1000;
const MAX_ANSWER_LEN = 20000;

// Returns an error message if any provided field exceeds its limit, else null.
function faqLengthError(fields: { question?: any; questionEs?: any; answer?: any; answerEs?: any }): string | null {
  const check = (v: any, max: number, label: string) =>
    typeof v === 'string' && v.length > max ? `${label} must be at most ${max} characters` : null;
  return (
    check(fields.question, MAX_QUESTION_LEN, 'Question') ||
    check(fields.questionEs, MAX_QUESTION_LEN, 'Question (ES)') ||
    check(fields.answer, MAX_ANSWER_LEN, 'Answer') ||
    check(fields.answerEs, MAX_ANSWER_LEN, 'Answer (ES)')
  );
}

// ==================== Public Routes ====================

// Get FAQ list for public (only enabled; optional filter for homepage)
faqRouter.get('/', async (c) => {
  const homepage = c.req.query('homepage') === 'true';

  let query = (db as any)
    .select()
    .from(faqQuestions)
    .where(eq((faqQuestions as any).enabled, 1))
    .orderBy(asc((faqQuestions as any).rank), asc((faqQuestions as any).createdAt));

  const rows = await dbAll<any>(query);

  let items = rows;
  if (homepage) {
    items = rows.filter((r: any) => r.showOnHomepage === true || r.showOnHomepage === 1 || r.show_on_homepage === true || r.show_on_homepage === 1);
  }

  return c.json({
    faqs: items.map((r: any) => ({
      id: r.id,
      question: r.question,
      questionEs: r.questionEs ?? r.question_es ?? null,
      answer: r.answer,
      answerEs: r.answerEs ?? r.answer_es ?? null,
      rank: r.rank ?? 0,
    })),
  });
});

// ==================== Admin Routes ====================

// Get all FAQ questions for admin (all, ordered by rank)
faqRouter.get('/admin/list', requireAuth(['admin']), async (c) => {
  const rows = await dbAll<any>(
    (db as any)
      .select()
      .from(faqQuestions)
      .orderBy(asc((faqQuestions as any).rank), asc((faqQuestions as any).createdAt))
  );

  const list = rows.map((r: any) => ({
    id: r.id,
    question: r.question,
    questionEs: r.questionEs ?? r.question_es ?? null,
    answer: r.answer,
    answerEs: r.answerEs ?? r.answer_es ?? null,
    enabled: r.enabled === true || r.enabled === 1,
    showOnHomepage: r.showOnHomepage === true || r.showOnHomepage === 1 || r.show_on_homepage === true || r.show_on_homepage === 1,
    rank: r.rank ?? 0,
    createdAt: r.createdAt,
    updatedAt: r.updatedAt,
  }));

  return c.json({ faqs: list });
});

// Get one FAQ by id (admin)
faqRouter.get('/admin/:id', requireAuth(['admin']), async (c) => {
  const { id } = c.req.param();
  const row = await dbGet<any>(
    (db as any).select().from(faqQuestions).where(eq((faqQuestions as any).id, id))
  );
  if (!row) {
    return c.json({ error: 'FAQ not found' }, 404);
  }
  return c.json({
    faq: {
      id: row.id,
      question: row.question,
      questionEs: row.questionEs ?? row.question_es ?? null,
      answer: row.answer,
      answerEs: row.answerEs ?? row.answer_es ?? null,
      enabled: row.enabled === true || row.enabled === 1,
      showOnHomepage: row.showOnHomepage === true || row.showOnHomepage === 1 || row.show_on_homepage === true || row.show_on_homepage === 1,
      rank: row.rank ?? 0,
      createdAt: row.createdAt,
      updatedAt: row.updatedAt,
    },
  });
});

// Create FAQ (admin)
faqRouter.post('/admin', requireAuth(['admin']), async (c) => {
  const body = await c.req.json();
  const { question, questionEs, answer, answerEs, enabled, showOnHomepage } = body;

  if (!question || typeof question !== 'string' || !answer || typeof answer !== 'string') {
    return c.json({ error: 'Question and answer (EN) are required' }, 400);
  }

  const lengthError = faqLengthError({ question, questionEs, answer, answerEs });
  if (lengthError) {
    return c.json({ error: lengthError }, 400);
  }

  const now = getNow();
  const id = generateId();

  const allForRank = await dbAll<any>(
    (db as any).select({ rank: (faqQuestions as any).rank }).from(faqQuestions)
  );
  const maxRank = allForRank.length
    ? Math.max(...allForRank.map((r: any) => Number(r.rank ?? 0)))
    : 0;
  const nextRank = maxRank + 1;

  await (db as any).insert(faqQuestions).values({
    id,
    question: String(question).trim(),
    questionEs: questionEs != null ? String(questionEs).trim() : null,
    answer: String(answer).trim(),
    answerEs: answerEs != null ? String(answerEs).trim() : null,
    enabled: enabled !== false ? 1 : 0,
    showOnHomepage: showOnHomepage === true ? 1 : 0,
    rank: nextRank,
    createdAt: now,
    updatedAt: now,
  });

  const created = await dbGet<any>(
    (db as any).select().from(faqQuestions).where(eq((faqQuestions as any).id, id))
  );
  return c.json(
    {
      faq: {
        id: created.id,
        question: created.question,
        questionEs: created.questionEs ?? created.question_es ?? null,
        answer: created.answer,
        answerEs: created.answerEs ?? created.answer_es ?? null,
        enabled: created.enabled === true || created.enabled === 1,
        showOnHomepage: created.showOnHomepage === true || created.showOnHomepage === 1 || created.show_on_homepage === true || created.show_on_homepage === 1,
        rank: created.rank ?? 0,
        createdAt: created.createdAt,
        updatedAt: created.updatedAt,
      },
    },
    201
  );
});

// Update FAQ (admin)
faqRouter.put('/admin/:id', requireAuth(['admin']), async (c) => {
  const { id } = c.req.param();
  const body = await c.req.json();
  const { question, questionEs, answer, answerEs, enabled, showOnHomepage } = body;

  const existing = await dbGet<any>(
    (db as any).select().from(faqQuestions).where(eq((faqQuestions as any).id, id))
  );
  if (!existing) {
    return c.json({ error: 'FAQ not found' }, 404);
  }

  const lengthError = faqLengthError({ question, questionEs, answer, answerEs });
  if (lengthError) {
    return c.json({ error: lengthError }, 400);
  }

  const updateData: Record<string, unknown> = {
    updatedAt: getNow(),
  };
  if (question !== undefined) updateData.question = String(question).trim();
  if (questionEs !== undefined) updateData.questionEs = questionEs == null ? null : String(questionEs).trim();
  if (answer !== undefined) updateData.answer = String(answer).trim();
  if (answerEs !== undefined) updateData.answerEs = answerEs == null ? null : String(answerEs).trim();
  if (typeof enabled === 'boolean') updateData.enabled = enabled ? 1 : 0;
  if (typeof showOnHomepage === 'boolean') updateData.showOnHomepage = showOnHomepage ? 1 : 0;

  await (db as any).update(faqQuestions).set(updateData).where(eq((faqQuestions as any).id, id));

  const updated = await dbGet<any>(
    (db as any).select().from(faqQuestions).where(eq((faqQuestions as any).id, id))
  );
  return c.json({
    faq: {
      id: updated.id,
      question: updated.question,
      questionEs: updated.questionEs ?? updated.question_es ?? null,
      answer: updated.answer,
      answerEs: updated.answerEs ?? updated.answer_es ?? null,
      enabled: updated.enabled === true || updated.enabled === 1,
      showOnHomepage: updated.showOnHomepage === true || updated.showOnHomepage === 1 || updated.show_on_homepage === true || updated.show_on_homepage === 1,
      rank: updated.rank ?? 0,
      createdAt: updated.createdAt,
      updatedAt: updated.updatedAt,
    },
  });
});

// Delete FAQ (admin)
faqRouter.delete('/admin/:id', requireAuth(['admin']), async (c) => {
  const { id } = c.req.param();
  const existing = await dbGet<any>(
    (db as any).select().from(faqQuestions).where(eq((faqQuestions as any).id, id))
  );
  if (!existing) {
    return c.json({ error: 'FAQ not found' }, 404);
  }
  await (db as any).delete(faqQuestions).where(eq((faqQuestions as any).id, id));
  return c.json({ message: 'FAQ deleted' });
});

// Reorder FAQs (admin) – body: { ids: string[] } (ordered list of ids)
faqRouter.post('/admin/reorder', requireAuth(['admin']), async (c) => {
  const body = await c.req.json();
  const { ids } = body;
  if (!Array.isArray(ids) || ids.length === 0) {
    return c.json({ error: 'ids array is required' }, 400);
  }

  // Verify every id exists before applying ranks (prevents silent no-ops on bad input).
  const existingRows = await dbAll<any>(
    (db as any).select({ id: (faqQuestions as any).id }).from(faqQuestions)
  );
  const existingIds = new Set(existingRows.map((r: any) => r.id));
  if (ids.some((id: string) => !existingIds.has(id))) {
    return c.json({ error: 'One or more FAQ ids are invalid' }, 400);
  }

  const now = getNow();
  for (let i = 0; i < ids.length; i++) {
    await (db as any)
      .update(faqQuestions)
      .set({ rank: i, updatedAt: now })
      .where(eq((faqQuestions as any).id, ids[i]));
  }

  const rows = await dbAll<any>(
    (db as any)
      .select()
      .from(faqQuestions)
      .orderBy(asc((faqQuestions as any).rank), asc((faqQuestions as any).createdAt))
  );
  const list = rows.map((r: any) => ({
    id: r.id,
    question: r.question,
    questionEs: r.questionEs ?? r.question_es ?? null,
    answer: r.answer,
    answerEs: r.answerEs ?? r.answer_es ?? null,
    enabled: r.enabled === true || r.enabled === 1,
    showOnHomepage: r.showOnHomepage === true || r.showOnHomepage === 1 || r.show_on_homepage === true || r.show_on_homepage === 1,
    rank: r.rank ?? 0,
    createdAt: r.createdAt,
    updatedAt: r.updatedAt,
  }));

  return c.json({ faqs: list });
});

export default faqRouter;
