import { FastifyInstance, FastifyRequest, FastifyReply } from 'fastify';
import {
  voiceEnrollmentService,
  analysisService,
  batchAnalysisService,
  voicePrintEnv,
  AnalysisJobStatus,
} from '../services/voiceprint';

export async function voiceprintRoutes(fastify: FastifyInstance) {
  // Enroll a new voice profile
  fastify.post('/enroll', async (request: FastifyRequest, reply: FastifyReply) => {
    const authReq = request as FastifyRequest & { user?: { id: string } };
    const userId = authReq.user?.id;

    if (!userId) {
      return reply.code(401).send({ error: 'User ID required' });
    }

    const body = request.body as {
      name: string;
      audio: Buffer;
    };

    if (!body.name || !body.audio) {
      return reply.code(400).send({ error: 'name and audio are required' });
    }

    try {
      const enrollment = await voiceEnrollmentService.enroll(
        userId,
        body.name,
        body.audio
      );
      return reply.code(201).send({
        enrollment: {
          id: enrollment.id,
          name: enrollment.name,
          isActive: enrollment.isActive,
          createdAt: enrollment.createdAt,
        },
      });
    } catch (error) {
      const message = error instanceof Error ? error.message : 'Enrollment failed';
      return reply.code(422).send({ error: message });
    }
  });

  // List user's voice enrollments
  fastify.get('/enrollments', async (request: FastifyRequest, reply: FastifyReply) => {
    const authReq = request as FastifyRequest & { user?: { id: string } };
    const userId = authReq.user?.id;

    if (!userId) {
      return reply.code(401).send({ error: 'User ID required' });
    }

    const isActive = request.query as { isActive?: string };
    const limit = request.query as { limit?: string };
    const offset = request.query as { offset?: string };

    const enrollments = await voiceEnrollmentService.listEnrollments(userId, {
      isActive: isActive.isActive !== undefined
        ? isActive.isActive === 'true'
        : undefined,
      limit: limit.limit ? parseInt(limit.limit, 10) : undefined,
      offset: offset.offset ? parseInt(offset.offset, 10) : undefined,
    });

    return reply.send({
      enrollments: enrollments.map((e) => ({
        id: e.id,
        name: e.name,
        isActive: e.isActive,
        createdAt: e.createdAt,
      })),
    });
  });

  // Remove an enrollment
  fastify.delete('/enrollments/:id', async (request: FastifyRequest, reply: FastifyReply) => {
    const authReq = request as FastifyRequest & { user?: { id: string } };
    const userId = authReq.user?.id;

    if (!userId) {
      return reply.code(401).send({ error: 'User ID required' });
    }

    const enrollmentId = (request.params as { id: string }).id;

    try {
      const enrollment = await voiceEnrollmentService.removeEnrollment(
        enrollmentId,
        userId
      );
      return reply.send({
        enrollment: {
          id: enrollment.id,
          name: enrollment.name,
          isActive: enrollment.isActive,
        },
      });
    } catch (error) {
      const message = error instanceof Error ? error.message : 'Removal failed';
      return reply.code(404).send({ error: message });
    }
  });

  // Analyze a single audio file
  fastify.post('/analyze', async (request: FastifyRequest, reply: FastifyReply) => {
    const authReq = request as FastifyRequest & { user?: { id: string } };
    const userId = authReq.user?.id;

    if (!userId) {
      return reply.code(401).send({ error: 'User ID required' });
    }

    const body = request.body as {
      audio: Buffer;
      enrollmentId?: string;
      audioUrl?: string;
    };

    if (!body.audio) {
      return reply.code(400).send({ error: 'audio is required' });
    }

    try {
      const result = await analysisService.analyze(userId, body.audio, {
        enrollmentId: body.enrollmentId,
        audioUrl: body.audioUrl,
      });
      return reply.code(201).send({
        analysis: {
          id: result.id,
          isSynthetic: result.isSynthetic,
          confidence: result.confidence,
          analysisResult: result.analysisResult,
          createdAt: result.createdAt,
        },
      });
    } catch (error) {
      const message = error instanceof Error ? error.message : 'Analysis failed';
      return reply.code(422).send({ error: message });
    }
  });

  // Get analysis result by ID
  fastify.get('/results/:id', async (request: FastifyRequest, reply: FastifyReply) => {
    const authReq = request as FastifyRequest & { user?: { id: string } };
    const userId = authReq.user?.id;

    if (!userId) {
      return reply.code(401).send({ error: 'User ID required' });
    }

    const analysisId = (request.params as { id: string }).id;
    const result = await analysisService.getResult(analysisId, userId);

    if (!result) {
      return reply.code(404).send({ error: 'Analysis not found' });
    }

    return reply.send({
      analysis: {
        id: result.id,
        isSynthetic: result.isSynthetic,
        confidence: result.confidence,
        analysisResult: result.analysisResult,
        createdAt: result.createdAt,
      },
    });
  });

  // Get analysis history
  fastify.get('/history', async (request: FastifyRequest, reply: FastifyReply) => {
    const authReq = request as FastifyRequest & { user?: { id: string } };
    const userId = authReq.user?.id;

    if (!userId) {
      return reply.code(401).send({ error: 'User ID required' });
    }

    const query = request.query as {
      limit?: string;
      offset?: string;
      isSynthetic?: string;
    };

    const results = await analysisService.getHistory(userId, {
      limit: query.limit ? parseInt(query.limit, 10) : undefined,
      offset: query.offset ? parseInt(query.offset, 10) : undefined,
      isSynthetic: query.isSynthetic !== undefined
        ? query.isSynthetic === 'true'
        : undefined,
    });

    return reply.send({
      analyses: results.map((r) => ({
        id: r.id,
        isSynthetic: r.isSynthetic,
        confidence: r.confidence,
        createdAt: r.createdAt,
      })),
    });
  });

  // Batch analyze multiple audio files
  fastify.post('/batch', async (request: FastifyRequest, reply: FastifyReply) => {
    const authReq = request as FastifyRequest & { user?: { id: string } };
    const userId = authReq.user?.id;

    if (!userId) {
      return reply.code(401).send({ error: 'User ID required' });
    }

    const body = request.body as {
      files: Array<{
        name: string;
        audio: Buffer;
        audioUrl?: string;
      }>;
      enrollmentId?: string;
    };

    if (!body.files || body.files.length === 0) {
      return reply.code(400).send({ error: 'files array is required' });
    }

    try {
      const result = await batchAnalysisService.analyzeBatch(
        userId,
        body.files.map((f) => ({
          name: f.name,
          buffer: f.audio,
          audioUrl: f.audioUrl,
        })),
        {
          enrollmentId: body.enrollmentId,
        }
      );

      return reply.code(201).send({
        jobId: result.jobId,
        results: result.results.map((r) => ({
          id: r.id,
          isSynthetic: r.isSynthetic,
          confidence: r.confidence,
        })),
        summary: result.summary,
      });
    } catch (error) {
      const message = error instanceof Error ? error.message : 'Batch analysis failed';
      return reply.code(422).send({ error: message });
    }
  });
}
