/**
 * Admin Jobs Routes
 *
 * Admin endpoints for managing and monitoring translation jobs
 */

import { Router, Request, Response } from 'express';
import { PrismaClient, TranslationJobStatus } from '@prisma/client';
import { authenticateAdmin } from '../../middleware/auth';
import { logger } from '../../utils/logger';
import { PaginatedResponse, JobStatusResponse } from '../../types';

const router = Router();
const prisma = new PrismaClient();

/**
 * Admin-specific job list item with webhook delivery info
 */
interface AdminJobListItem {
  id: string;
  userId: string;
  userEmail: string;
  clientJobId: string | null;
  plugin: string;
  status: TranslationJobStatus;
  sourceLang: string;
  targetLang: string;
  model: string;
  charactersUsed: number;
  tokensUsed: number;
  inputTokens: number;
  outputTokens: number;
  cost: string;
  customerCost: string;
  callbackUrl: string | null;
  webhookDeliveries: number;
  lastWebhookStatus: boolean | null;
  createdAt: string;
  completedAt: string | null;
}

/**
 * Admin job details with full webhook delivery history
 */
interface AdminJobDetails extends Omit<JobStatusResponse, 'customerCost'> {
  userId: string;
  userEmail: string;
  model: string;
  tokensUsed?: number;
  inputTokens?: number;
  outputTokens?: number;
  customerCost?: number;
  contentPreview: string;
  translationPreview?: string;
  callbackUrl: string | null;
  webhookDeliveries: Array<{
    id: string;
    attemptNumber: number;
    success: boolean;
    httpStatus: number | null;
    responseBody: string | null;
    errorMessage: string | null;
    attemptedAt: string;
  }>;
}

/**
 * GET /v1/admin/jobs
 * List all translation jobs with pagination and filters
 */
router.get('/', authenticateAdmin, async (req: Request, res: Response) => {
  try {
    const {
      page = '1',
      limit = '50',
      status,
      userId,
      plugin,
      sourceLang,
      targetLang,
      startDate,
      endDate,
      sortBy = 'createdAt',
      sortOrder = 'desc',
    } = req.query;

    const pageNum = Math.max(1, parseInt(page as string, 10));
    const limitNum = Math.min(100, Math.max(1, parseInt(limit as string, 10)));
    const skip = (pageNum - 1) * limitNum;

    // Build filter conditions
    const where: any = {};

    if (status) {
      const statuses = (status as string).split(',') as TranslationJobStatus[];
      where.status = statuses.length === 1 ? statuses[0] : { in: statuses };
    }

    if (userId) {
      where.user_id = userId as string;
    }

    if (sourceLang) {
      where.source_lang = sourceLang as string;
    }

    if (targetLang) {
      where.target_lang = targetLang as string;
    }

    if (plugin) {
      where.plugin = plugin as string;
    }

    if (startDate || endDate) {
      where.created_at = {};
      if (startDate) {
        where.created_at.gte = new Date(startDate as string);
      }
      if (endDate) {
        where.created_at.lte = new Date(endDate as string);
      }
    }

    // Validate sort field
    const allowedSortFields = ['created_at', 'completed_at', 'characters_used', 'cost', 'status'];
    const sortField = allowedSortFields.includes(sortBy as string) ? sortBy : 'created_at';
    const sortDirection = sortOrder === 'asc' ? 'asc' : 'desc';

    // Execute queries in parallel
    const [jobs, total] = await Promise.all([
      prisma.translationJob.findMany({
        where,
        skip,
        take: limitNum,
        orderBy: { [sortField as string]: sortDirection },
        include: {
          user: {
            select: {
              email: true,
            },
          },
          webhook_deliveries: {
            orderBy: { attempted_at: 'desc' },
            take: 1,
            select: {
              success: true,
            },
          },
        },
      }),
      prisma.translationJob.count({ where }),
    ]);

    // Format response
    const data: AdminJobListItem[] = jobs.map((job) => ({
      id: job.id,
      userId: job.user_id,
      userEmail: job.user.email,
      clientJobId: job.client_job_id,
      plugin: job.plugin,
      status: job.status,
      sourceLang: job.source_lang,
      targetLang: job.target_lang,
      model: job.model,
      charactersUsed: job.characters_used,
      tokensUsed: job.tokens_used,
      inputTokens: job.input_tokens,
      outputTokens: job.output_tokens,
      cost: job.cost.toString(),
      customerCost: job.customer_cost.toString(),
      callbackUrl: job.callback_url,
      webhookDeliveries: job.webhook_deliveries.length,
      lastWebhookStatus: job.webhook_deliveries[0]?.success ?? null,
      createdAt: job.created_at.toISOString(),
      completedAt: job.completed_at?.toISOString() ?? null,
    }));

    const totalPages = Math.ceil(total / limitNum);

    const response: PaginatedResponse<AdminJobListItem> = {
      data,
      pagination: {
        page: pageNum,
        limit: limitNum,
        total,
        totalPages,
        hasNext: pageNum < totalPages,
        hasPrev: pageNum > 1,
      },
    };

    res.json(response);
  } catch (error) {
    logger.error('Error fetching admin jobs list', { error });
    res.status(500).json({
      error: true,
      code: 'INTERNAL_ERROR',
      message: 'Failed to fetch jobs',
      timestamp: new Date().toISOString(),
    });
  }
});

/**
 * GET /v1/admin/jobs/filters
 * Get distinct filter values (languages, users) for populating filter dropdowns
 */
router.get('/filters', authenticateAdmin, async (req: Request, res: Response) => {
  try {
    const { plugin } = req.query;
    const scope = plugin ? { plugin: plugin as string } : {};

    const [sourceLangs, targetLangs, users, plugins] = await Promise.all([
      prisma.translationJob.findMany({
        where: scope,
        distinct: ['source_lang'],
        select: { source_lang: true },
        orderBy: { source_lang: 'asc' },
      }),
      prisma.translationJob.findMany({
        where: scope,
        distinct: ['target_lang'],
        select: { target_lang: true },
        orderBy: { target_lang: 'asc' },
      }),
      prisma.translationJob.findMany({
        where: scope,
        distinct: ['user_id'],
        select: {
          user_id: true,
          user: { select: { email: true } },
        },
        orderBy: { user_id: 'asc' },
      }),
      prisma.translationJob.findMany({
        distinct: ['plugin'],
        select: { plugin: true },
        orderBy: { plugin: 'asc' },
      }),
    ]);

    res.json({
      sourceLangs: sourceLangs.map((r) => r.source_lang),
      targetLangs: targetLangs.map((r) => r.target_lang),
      users: users.map((r) => ({ id: r.user_id, email: r.user.email })),
      plugins: plugins.map((r) => r.plugin),
    });
  } catch (error) {
    logger.error('Error fetching job filter options', { error });
    res.status(500).json({
      error: true,
      code: 'INTERNAL_ERROR',
      message: 'Failed to fetch filter options',
      timestamp: new Date().toISOString(),
    });
  }
});

/**
 * GET /v1/admin/jobs/:id
 * Get detailed job information including webhook delivery history
 */
router.get('/:id', authenticateAdmin, async (req: Request, res: Response) => {
  try {
    const { id } = req.params;

    const job = await prisma.translationJob.findUnique({
      where: { id },
      include: {
        user: {
          select: {
            email: true,
          },
        },
        webhook_deliveries: {
          orderBy: { attempted_at: 'desc' },
        },
      },
    });

    if (!job) {
      res.status(404).json({
        error: true,
        code: 'JOB_NOT_FOUND',
        message: `Job with ID ${id} not found`,
        timestamp: new Date().toISOString(),
      });
      return;
    }

    // Create content preview (first 200 chars)
    const contentPreview = job.content.substring(0, 200) + (job.content.length > 200 ? '...' : '');
    const translationPreview = job.translation
      ? job.translation.substring(0, 200) + (job.translation.length > 200 ? '...' : '')
      : undefined;

    const response: AdminJobDetails = {
      jobId: job.id,
      userId: job.user_id,
      userEmail: job.user.email,
      clientJobId: job.client_job_id ?? undefined,
      status: job.status as any,
      sourceLang: job.source_lang,
      targetLang: job.target_lang,
      tone: job.tone as any,
      model: job.model,
      contentPreview,
      translation: job.translation ?? undefined,
      translationPreview,
      charactersUsed: job.characters_used ?? undefined,
      tokensUsed: job.tokens_used ?? undefined,
      inputTokens: job.input_tokens ?? undefined,
      outputTokens: job.output_tokens ?? undefined,
      cost: job.cost ? parseFloat(job.cost.toString()) : undefined,
      customerCost: job.customer_cost ? parseFloat(job.customer_cost.toString()) : undefined,
      errorMessage: job.error_message ?? undefined,
      processingTimeMs: job.processing_time_ms ?? undefined,
      callbackUrl: job.callback_url,
      createdAt: job.created_at.toISOString(),
      updatedAt: job.updated_at.toISOString(),
      completedAt: job.completed_at?.toISOString(),
      webhookDeliveries: job.webhook_deliveries.map((delivery) => ({
        id: delivery.id,
        attemptNumber: delivery.attempt_number,
        success: delivery.success,
        httpStatus: delivery.http_status,
        responseBody: delivery.response_body,
        errorMessage: delivery.error_message,
        attemptedAt: delivery.attempted_at.toISOString(),
      })),
    };

    res.json(response);
  } catch (error) {
    logger.error('Error fetching admin job details', { error, jobId: req.params.id });
    res.status(500).json({
      error: true,
      code: 'INTERNAL_ERROR',
      message: 'Failed to fetch job details',
      timestamp: new Date().toISOString(),
    });
  }
});

export default router;
