import type { FastifyInstance } from 'fastify';
import { z } from 'zod';
import { MeiliSearch } from 'meilisearch';
import pino from 'pino';
import { config } from '../config/index.js';

const logger = pino({ name: 'api-search' });

let meili: MeiliSearch | null = null;

function getMeili(): MeiliSearch {
  if (!meili) {
    meili = new MeiliSearch({ host: config.MEILI_URL, apiKey: config.MEILI_KEY || undefined });
  }
  return meili;
}

const searchQuerySchema = z.object({
  q: z.string().min(1).max(500),
  limit: z.coerce.number().min(1).max(50).default(20),
  offset: z.coerce.number().min(0).default(0),
  filter: z.string().optional(), // Meilisearch filter syntax
});

export function registerSearchRoutes(app: FastifyInstance) {
  // Full-text search across services
  app.get('/api/v1/search', async (req, reply) => {
    const query = searchQuerySchema.parse(req.query);
    const tenantId = (req as any).tenantId;

    try {
      const index = getMeili().index(`services_${tenantId}`);
      const results = await index.search(query.q, {
        limit: query.limit,
        offset: query.offset,
        filter: query.filter,
        attributesToHighlight: ['name', 'description', 'owner'],
      });

      return {
        hits: results.hits,
        total: results.estimatedTotalHits,
        query: query.q,
        processingTimeMs: results.processingTimeMs,
      };
    } catch (err) {
      logger.warn({ error: (err as Error).message }, 'Meilisearch unavailable — falling back to PG');

      // Fallback: basic ILIKE search on PostgreSQL
      const { withTenant } = await import('../data/db.js');
      const result = await withTenant(tenantId, async (client) => {
        return client.query(
          `SELECT * FROM services WHERE name ILIKE $1 OR description ILIKE $1 OR owner ILIKE $1 LIMIT $2 OFFSET $3`,
          [`%${query.q}%`, query.limit, query.offset],
        );
      });

      return { hits: result.rows, total: result.rowCount, query: query.q, fallback: true };
    }
  });

  // Sync services to Meilisearch index
  app.post('/api/v1/search/reindex', async (req, reply) => {
    const tenantId = (req as any).tenantId;

    const { withTenant } = await import('../data/db.js');
    const services = await withTenant(tenantId, async (client) => {
      return client.query('SELECT * FROM services');
    });

    const index = getMeili().index(`services_${tenantId}`);
    await index.addDocuments(services.rows.map(s => ({ ...s, id: s.id })));

    logger.info({ tenantId, count: services.rowCount }, 'Reindex triggered');
    return { status: 'reindexing', documents: services.rowCount };
  });
}
