import { NextRequest, NextResponse } from 'next/server';
import { requireAuth } from '@/lib/auth-utils';
import postgresClient from '@/lib/services/postgres-client';

// ─── Company filter helper (duplicated from /api/mobile/tickets/route.ts per D-04) ───

async function getMobileCompanyFilter(): Promise<{ join: string; condition: string }> {
  try {
    const result = await postgresClient.query(
      `SELECT setting_key, setting_value FROM kiosk_settings WHERE setting_key IN ('mobile_company_category_ids', 'mobile_excluded_company_ids')`
    );
    const map: Record<string, string> = {};
    result.rows.forEach((r: any) => { map[r.setting_key] = r.setting_value || ''; });

    const catIds = (map['mobile_company_category_ids'] || '1')
      .split(',').map((s: string) => parseInt(s.trim(), 10)).filter((n: number) => !isNaN(n));
    const exclIds = (map['mobile_excluded_company_ids'] || '')
      .split(',').map((s: string) => parseInt(s.trim(), 10)).filter((n: number) => !isNaN(n));

    const catCond = catIds.length > 0 ? `c.company_category_id IN (${catIds.join(',')})` : 'true';
    const exclCond = exclIds.length > 0 ? `c.id NOT IN (${exclIds.join(',')})` : '';
    const condition = [catCond, exclCond].filter(Boolean).join(' AND ');

    return { join: 'INNER JOIN companies c ON c.id = t.company_id', condition };
  } catch (error) {
    console.error('Error fetching mobile company filter:', error);
    return { join: 'INNER JOIN companies c ON c.id = t.company_id', condition: 'c.company_category_id = 1' };
  }
}

// ─── Exported response interfaces (D-26) ─────────────────────────────────────

export interface AnalyzerFeedRow {
  id: string;                    // analyzer_analyses UUID
  ticketNumber: string;
  title: string;
  companyName: string;
  summary: string | null;
  confidenceScore: number | null;
  haikuUsed: boolean;
  sonnetUsed: boolean;
  opusUsed: boolean;
  needsHumanReview: boolean;
  completedAt: string;           // ISO string
  analysisVersion: number;
}

export interface AnalyzerFeedResponse {
  analyses: AnalyzerFeedRow[];
  nextCursor: string | null;
  hasMore: boolean;
}

// ─── Cursor encode/decode (inline per D-06) ──────────────────────────────────

interface CursorPayload { completed_at: string; id: string; }

function encodeCursor(p: CursorPayload): string {
  return Buffer.from(JSON.stringify(p), 'utf8').toString('base64');
}

function decodeCursor(raw: string | null): CursorPayload | null {
  if (!raw) return null;
  try {
    const parsed = JSON.parse(Buffer.from(raw, 'base64').toString('utf8'));
    if (typeof parsed?.completed_at === 'string' && typeof parsed?.id === 'string') {
      return parsed as CursorPayload;
    }
    return null;
  } catch { return null; }
}

// ─── GET handler ─────────────────────────────────────────────────────────────

export async function GET(request: NextRequest): Promise<NextResponse> {
  const { error: authError } = await requireAuth();
  if (authError) return authError;

  try {
    const { searchParams } = request.nextUrl;
    const cursorParam = searchParams.get('cursor');

    // Server-side limit cap — D-05 (page size 25, cap at 25)
    const limit = Math.min(25, Math.max(1, parseInt(searchParams.get('limit') ?? '25')));

    const cursor = decodeCursor(cursorParam);

    // Apply kiosk_settings company scoping (D-04, T-06-02)
    const { condition: companyCondition } = await getMobileCompanyFilter();

    // Build WHERE conditions — absorb status='complete' into the CTE and
    // t.is_deleted=false into the JOIN; only company scoping and cursor predicate here
    const conditions: string[] = [
      companyCondition,   // D-04: kiosk_settings scoping (security boundary)
    ];
    const params: unknown[] = [];

    // Cursor seek predicate (D-03, D-06) — keyset on (completed_at DESC, id DESC)
    if (cursor) {
      params.push(cursor.completed_at);
      params.push(cursor.id);
      conditions.push(`(aa.completed_at, aa.id) < ($${params.length - 1}::timestamptz, $${params.length}::uuid)`);
    }

    const where = conditions.join(' AND ');

    // Latest-per-ticket CTE (D-02): DISTINCT ON returns the highest analysis_version
    // per ticket among status='complete' rows. The CTE result is then joined to the
    // main query so each ticket appears exactly once.
    const sql = `
      WITH latest_per_ticket AS (
        SELECT DISTINCT ON (ticket_number) id
          FROM analyzer_analyses
         WHERE status = 'complete'
         ORDER BY ticket_number, analysis_version DESC
      )
      SELECT aa.id, aa.ticket_number, aa.completed_at, aa.analysis_version,
             aa.summary, aa.confidence_score, aa.needs_human_review,
             aa.haiku_used, aa.sonnet_used, aa.opus_used,
             t.title,
             c.company_name
        FROM analyzer_analyses aa
        INNER JOIN latest_per_ticket l ON l.id = aa.id
        INNER JOIN tickets t ON t.ticket_number = aa.ticket_number AND t.is_deleted = false
        INNER JOIN companies c ON c.id = t.company_id
       WHERE ${where}
       ORDER BY aa.completed_at DESC NULLS LAST, aa.id DESC
       LIMIT ${limit + 1}
    `;

    const result = await postgresClient.query(sql, params);

    const rows = result.rows;
    const hasMore = rows.length > limit;
    const sliced = hasMore ? rows.slice(0, limit) : rows;

    // Transform snake_case → camelCase (CLAUDE.md: manual transform, no ORM)
    const analyses: AnalyzerFeedRow[] = sliced.map(row => ({
      id: String(row.id),
      ticketNumber: row.ticket_number,
      title: row.title ?? '',
      companyName: row.company_name ?? '',
      summary: row.summary ?? null,
      confidenceScore: row.confidence_score === null ? null : Number(row.confidence_score),
      haikuUsed: row.haiku_used,
      sonnetUsed: row.sonnet_used,
      opusUsed: row.opus_used,
      needsHumanReview: row.needs_human_review,
      completedAt: row.completed_at instanceof Date ? row.completed_at.toISOString() : String(row.completed_at),
      analysisVersion: row.analysis_version,
    }));

    // Compute nextCursor from the last row of the current page (D-06)
    const nextCursor = hasMore && analyses.length > 0
      ? encodeCursor({
          completed_at: analyses[analyses.length - 1].completedAt,
          id: analyses[analyses.length - 1].id,
        })
      : null;

    return NextResponse.json({ analyses, nextCursor, hasMore } satisfies AnalyzerFeedResponse);
  } catch (error) {
    console.error('GET /api/mobile/analyzer/feed failed:', error);
    return NextResponse.json(
      { error: 'Failed to fetch analyses', message: error instanceof Error ? error.message : 'unknown' },
      { status: 500 },
    );
  }
}
