/**
 * Express REST API Routes
 * All endpoints for A2P AutoPilot management
 */

import express, { type Request, type Response, Router } from 'express';
import { z } from 'zod';
import {
  createSubmission,
  getSubmission,
  getAllSubmissions,
  updateSubmissionStatus,
  getAuditLog,
  getSubmissionStats,
  incrementAttemptCount,
} from '../db/repository';
import {
  asyncHandler,
  validateBody,
  validateQuery,
  authenticateApiKey,
  publicEndpoint,
} from './middleware';
import { logger } from '../utils/logger';
import type { RegistrationInput, SubmissionStatus } from '../types';

const router = Router();

// ============================================================
// VALIDATION SCHEMAS
// ============================================================

// Registration input validation (simplified - extend as needed)
const registrationInputSchema = z.object({
  business: z.object({
    businessName: z.string().min(1),
    businessType: z.string(),
    businessIndustry: z.string(),
    registrationIdentifier: z.string(),
    registrationNumber: z.string(),
    websiteUrl: z.string().url(),
    socialMediaUrls: z.array(z.string().url()).optional(),
    businessIdentity: z.enum(['direct_customer', 'isv_reseller_or_partner']),
    regionsOfOperation: z.array(z.string()),
    companyType: z.enum(['public', 'private', 'non-profit', 'government']),
    stockExchange: z.string().optional(),
    stockTicker: z.string().optional(),
    brandContactEmail: z.string().email().optional(),
    skipAutoSecVet: z.boolean().optional(),
  }),
  authorizedRep: z.object({
    firstName: z.string().min(1),
    lastName: z.string().min(1),
    businessTitle: z.string().min(1),
    jobPosition: z.string(),
    phoneNumber: z.string(),
    email: z.string().email(),
  }),
  address: z.object({
    customerName: z.string().min(1),
    street: z.string().min(1),
    streetSecondary: z.string().optional(),
    city: z.string().min(1),
    region: z.string().length(2),
    postalCode: z.string().min(1),
    isoCountry: z.string().length(2),
  }),
  campaign: z.object({
    useCase: z.string(),
    description: z.string().min(10),
    sampleMessages: z.array(z.string()).min(1).max(5),
    messageFlow: z.string().min(10),
    optInType: z.string(),
    optInMessage: z.string().min(1),
    optOutMessage: z.string().min(1),
    helpMessage: z.string().min(1),
    optInKeywords: z.array(z.string()).optional(),
    optOutKeywords: z.array(z.string()).optional(),
    helpKeywords: z.array(z.string()).optional(),
    hasEmbeddedLinks: z.boolean(),
    hasEmbeddedPhone: z.boolean(),
  }),
  phone: z.object({
    messagingServiceSid: z.string().optional(),
    phoneNumbers: z.array(z.string()).optional(),
  }),
  externalId: z.string().optional(),
  notifyWebhook: z.string().url().optional(),
  notifyEmail: z.string().email().optional(),
}) as z.ZodSchema<RegistrationInput>;

const listSubmissionsQuerySchema = z.object({
  status: z.string().optional(),
  externalId: z.string().optional(),
  startDate: z.string().datetime().optional(),
  endDate: z.string().datetime().optional(),
  limit: z.coerce.number().int().positive().max(100).optional().default(50),
  offset: z.coerce.number().int().nonnegative().optional().default(0),
});

const bulkImportSchema = z.object({
  submissions: z.array(registrationInputSchema).min(1).max(100),
});

// ============================================================
// SUBMISSION ENDPOINTS
// ============================================================

/**
 * POST /api/submissions
 * Create a new A2P registration
 */
router.post(
  '/submissions',
  authenticateApiKey,
  validateBody(registrationInputSchema),
  asyncHandler(async (req: Request, res: Response) => {
    const input = req.body as RegistrationInput;
    
    logger.info({ businessName: input.business.businessName }, 'Creating new submission');

    // TODO: Generate landing pages (implement in separate module)
    // const landingPages = await generateLandingPages(input);

    const submission = await createSubmission(input);

    // TODO: Enqueue job to start submission engine
    // await queueSubmissionJob(submission.id);

    res.status(201).json({
      success: true,
      data: submission,
    });
  })
);

/**
 * GET /api/submissions
 * List all submissions with filtering
 */
router.get(
  '/submissions',
  authenticateApiKey,
  validateQuery(listSubmissionsQuerySchema),
  asyncHandler(async (req: Request, res: Response) => {
    const { status, externalId, startDate, endDate, limit, offset } = req.query as any;

    const statusArray = status ? (status.split(',') as SubmissionStatus[]) : undefined;

    const submissions = await getAllSubmissions({
      status: statusArray,
      externalId,
      startDate: startDate ? new Date(startDate) : undefined,
      endDate: endDate ? new Date(endDate) : undefined,
      limit,
      offset,
    });

    res.json({
      success: true,
      data: submissions,
      pagination: {
        limit,
        offset,
        total: submissions.length, // TODO: Add total count query
      },
    });
  })
);

/**
 * GET /api/submissions/:id
 * Get full details of a submission
 */
router.get(
  '/submissions/:id',
  authenticateApiKey,
  asyncHandler(async (req: Request, res: Response) => {
    const { id } = req.params;

    const submission = await getSubmission(id);

    if (!submission) {
      return res.status(404).json({
        success: false,
        error: 'Submission not found',
      });
    }

    res.json({
      success: true,
      data: submission,
    });
  })
);

/**
 * POST /api/submissions/:id/retry
 * Manually retry a failed submission
 */
router.post(
  '/submissions/:id/retry',
  authenticateApiKey,
  asyncHandler(async (req: Request, res: Response) => {
    const { id } = req.params;

    const submission = await getSubmission(id);

    if (!submission) {
      return res.status(404).json({
        success: false,
        error: 'Submission not found',
      });
    }

    if (submission.attemptCount >= submission.maxAttempts) {
      return res.status(400).json({
        success: false,
        error: 'Maximum retry attempts reached',
      });
    }

    // Reset to pending and increment attempt count
    await updateSubmissionStatus(id, 'pending', {
      failureReason: undefined,
    });
    await incrementAttemptCount(id);

    // TODO: Re-queue submission job
    // await queueSubmissionJob(id);

    logger.info({ submissionId: id }, 'Submission queued for retry');

    res.json({
      success: true,
      message: 'Submission queued for retry',
    });
  })
);

/**
 * POST /api/submissions/:id/cancel
 * Cancel a pending submission
 */
router.post(
  '/submissions/:id/cancel',
  authenticateApiKey,
  asyncHandler(async (req: Request, res: Response) => {
    const { id } = req.params;

    const submission = await getSubmission(id);

    if (!submission) {
      return res.status(404).json({
        success: false,
        error: 'Submission not found',
      });
    }

    if (submission.status === 'completed') {
      return res.status(400).json({
        success: false,
        error: 'Cannot cancel completed submission',
      });
    }

    await updateSubmissionStatus(id, 'manual_review', {
      failureReason: 'Cancelled by user',
    });

    logger.info({ submissionId: id }, 'Submission cancelled');

    res.json({
      success: true,
      message: 'Submission cancelled',
    });
  })
);

/**
 * GET /api/submissions/:id/audit-log
 * Get audit trail for a submission
 */
router.get(
  '/submissions/:id/audit-log',
  authenticateApiKey,
  asyncHandler(async (req: Request, res: Response) => {
    const { id } = req.params;

    const submission = await getSubmission(id);

    if (!submission) {
      return res.status(404).json({
        success: false,
        error: 'Submission not found',
      });
    }

    const auditLog = await getAuditLog(id);

    res.json({
      success: true,
      data: auditLog,
    });
  })
);

/**
 * POST /api/submissions/bulk
 * Bulk import submissions from CSV/JSON
 */
router.post(
  '/submissions/bulk',
  authenticateApiKey,
  validateBody(bulkImportSchema),
  asyncHandler(async (req: Request, res: Response) => {
    const { submissions } = req.body;

    logger.info({ count: submissions.length }, 'Bulk import started');

    const results = {
      success: [] as string[],
      failed: [] as { index: number; error: string }[],
    };

    for (let i = 0; i < submissions.length; i++) {
      try {
        const submission = await createSubmission(submissions[i]);
        results.success.push(submission.id);
        
        // TODO: Queue submission job
        // await queueSubmissionJob(submission.id);
      } catch (error) {
        logger.error({ error, index: i }, 'Bulk import item failed');
        results.failed.push({
          index: i,
          error: error instanceof Error ? error.message : 'Unknown error',
        });
      }
    }

    res.status(201).json({
      success: true,
      data: results,
      summary: {
        total: submissions.length,
        succeeded: results.success.length,
        failed: results.failed.length,
      },
    });
  })
);

// ============================================================
// STATS ENDPOINT
// ============================================================

/**
 * GET /api/stats
 * Dashboard statistics
 */
router.get(
  '/stats',
  authenticateApiKey,
  asyncHandler(async (_req: Request, res: Response) => {
    const stats = await getSubmissionStats();

    res.json({
      success: true,
      data: stats,
    });
  })
);

// ============================================================
// WEBHOOK ENDPOINTS (Public)
// ============================================================

/**
 * POST /webhooks/twilio/brand
 * Twilio brand status webhook
 */
router.post(
  '/webhooks/twilio/brand',
  publicEndpoint,
  asyncHandler(async (req: Request, res: Response) => {
    logger.info({ body: req.body }, 'Twilio brand webhook received');

    // TODO: Implement webhook handler
    // Parse webhook data and update submission status

    res.status(200).json({ received: true });
  })
);

/**
 * POST /webhooks/twilio/campaign
 * Twilio campaign status webhook
 */
router.post(
  '/webhooks/twilio/campaign',
  publicEndpoint,
  asyncHandler(async (req: Request, res: Response) => {
    logger.info({ body: req.body }, 'Twilio campaign webhook received');

    // TODO: Implement webhook handler
    // Parse webhook data and update submission status

    res.status(200).json({ received: true });
  })
);

// ============================================================
// HEALTH CHECK
// ============================================================

/**
 * GET /health
 * Health check endpoint
 */
router.get('/health', (_req: Request, res: Response) => {
  res.json({
    success: true,
    service: 'a2p-autopilot',
    timestamp: new Date().toISOString(),
  });
});

export default router;
