/**
 * Main API Routes
 * General API endpoints
 */

import express from 'express'
import { asyncHandler, NotFoundError, ValidationError } from '../middleware/errorHandler.mjs'
import { validate, schemas, rules } from '../middleware/validate.mjs'
import { respond } from '../utils/response.mjs'
import { products, questions, submissions, orders, onboardingState, emailAccounts, emailStats, emailDigests, userPreferences, subscriptions, emailUsage, referrals, db, Collections, Query } from '../services/database.mjs'
import Stripe from 'stripe'
import { config } from '../config/index.mjs'
import { log } from '../middleware/logger.mjs'
import { requireAuth } from '../middleware/auth.mjs'

const router = express.Router()
const stripe = new Stripe(config.stripe.secretKey)

/**
 * GET /api/products
 * Get all active products
 */
router.get('/products', asyncHandler(async (req, res) => {
  const productList = await products.getActive()
  respond.success(res, productList)
}))

/**
 * GET /api/questions
 * Get questions for a product
 */
router.get('/questions', asyncHandler(async (req, res) => {
  const { productSlug } = req.query

  if (!productSlug) {
    throw new ValidationError('productSlug ist erforderlich', { productSlug: ['Pflichtfeld'] })
  }

  const product = await products.getBySlug(productSlug)

  if (!product) {
    throw new NotFoundError('Produkt')
  }

  const questionList = await questions.getByProduct(product.$id)
  respond.success(res, questionList)
}))

/**
 * POST /api/submissions
 * Create a new submission
 */
router.post('/submissions',
  validate({
    body: {
      productSlug: [rules.required('productSlug')],
      answers: [rules.required('answers'), rules.isObject('answers')],
    },
  }),
  asyncHandler(async (req, res) => {
    const { productSlug, answers } = req.body

    const product = await products.getBySlug(productSlug)

    if (!product) {
      throw new NotFoundError('Produkt')
    }

    // Create submission
    const submission = await submissions.create({
      productId: product.$id,
      status: 'draft',
      customerEmail: answers.email || answers.customer_email || null,
      customerName: answers.name || answers.customer_name || null,
      finalSummaryJson: JSON.stringify(answers),
      priceCents: product.priceCents,
      currency: product.currency,
    })

    // Store answers separately
    await orders.create(submission.$id, { answers })

    respond.created(res, { submissionId: submission.$id })
  })
)

/**
 * POST /api/checkout
 * Create Stripe checkout session for one-time payment
 */
router.post('/checkout',
  validate({
    body: {
      submissionId: [rules.required('submissionId')],
    },
  }),
  asyncHandler(async (req, res) => {
    const { submissionId } = req.body

    // Get submission
    const submission = await submissions.create
    let submissionDoc
    try {
      const { db, Collections } = await import('../services/database.mjs')
      submissionDoc = await db.get(Collections.SUBMISSIONS, submissionId)
    } catch (error) {
      throw new NotFoundError('Submission')
    }

    // Create Stripe checkout session
    const session = await stripe.checkout.sessions.create({
      payment_method_types: ['card'],
      line_items: [
        {
          price_data: {
            currency: submissionDoc.currency || 'eur',
            product_data: {
              name: 'Email Sortierer Service',
              description: 'Personalisiertes E-Mail-Sortier-Setup',
            },
            unit_amount: submissionDoc.priceCents || 4900,
          },
          quantity: 1,
        },
      ],
      mode: 'payment',
      success_url: `${config.frontendUrl}/success?session_id={CHECKOUT_SESSION_ID}`,
      cancel_url: `${config.frontendUrl}/cancel`,
      metadata: {
        submissionId,
      },
      customer_email: submissionDoc.customerEmail || undefined,
    })

    respond.success(res, { url: session.url, sessionId: session.id })
  })
)

/**
 * GET /api/submission/:id
 * Get submission details
 */
router.get('/submission/:id', asyncHandler(async (req, res) => {
  const { id } = req.params

  const { db, Collections } = await import('../services/database.mjs')
  const submission = await db.get(Collections.SUBMISSIONS, id)

  // Don't expose sensitive data
  respond.success(res, {
    id: submission.$id,
    status: submission.status,
    createdAt: submission.$createdAt,
  })
}))

/**
 * GET /api/config
 * Get public configuration
 */
router.get('/config', (req, res) => {
  respond.success(res, {
    features: {
      gmail: Boolean(config.google.clientId),
      outlook: Boolean(config.microsoft.clientId),
      ai: Boolean(config.mistral.apiKey),
    },
    pricing: {
      basic: { price: 9, currency: 'EUR', accounts: 1 },
      pro: { price: 19, currency: 'EUR', accounts: 3 },
      business: { price: 49, currency: 'EUR', accounts: 10 },
    },
  })
})

/**
 * GET /api/onboarding/status
 * Get current onboarding state
 */
router.get('/onboarding/status',
  requireAuth,
  asyncHandler(async (req, res) => {
    const userId = req.appwriteUser.id
    const state = await onboardingState.getByUser(userId)
    respond.success(res, state)
  })
)

/**
 * POST /api/onboarding/step
 * Update onboarding step progress
 */
router.post('/onboarding/step',
  requireAuth,
  validate({
    body: {
      step: [rules.required('step')],
      completedSteps: [rules.isArray('completedSteps')],
    },
  }),
  asyncHandler(async (req, res) => {
    const userId = req.appwriteUser.id
    const { step, completedSteps = [] } = req.body
    await onboardingState.updateStep(userId, step, completedSteps)
    respond.success(res, { step, completedSteps })
  })
)

/**
 * POST /api/onboarding/skip
 * Skip onboarding
 */
router.post('/onboarding/skip',
  requireAuth,
  asyncHandler(async (req, res) => {
    const userId = req.appwriteUser.id
    await onboardingState.skip(userId)
    respond.success(res, { skipped: true })
  })
)

/**
 * POST /api/onboarding/resume
 * Resume onboarding
 */
router.post('/onboarding/resume',
  requireAuth,
  asyncHandler(async (req, res) => {
    const userId = req.appwriteUser.id
    await onboardingState.resume(userId)
    const state = await onboardingState.getByUser(userId)
    respond.success(res, state)
  })
)

/**
 * DELETE /api/account/delete
 * Delete all user data and account
 */
router.delete('/account/delete',
  requireAuth,
  asyncHandler(async (req, res) => {
    const userId = req.appwriteUser.id

    log.info(`Account deletion requested for user ${userId}`)

    // Delete all user data
    try {
      // Delete email accounts
      const accounts = await emailAccounts.getByUser(userId)
      for (const account of accounts) {
        try {
          await db.delete(Collections.EMAIL_ACCOUNTS, account.$id)
        } catch (err) {
          log.warn(`Failed to delete account ${account.$id}`, { error: err.message })
        }
      }

      // Delete stats
      const stats = await emailStats.getByUser(userId)
      if (stats) {
        try {
          await db.delete(Collections.EMAIL_STATS, stats.$id)
        } catch (err) {
          log.warn(`Failed to delete stats`, { error: err.message })
        }
      }

      // Delete digests
      const digests = await emailDigests.getByUser(userId)
      for (const digest of digests) {
        try {
          await db.delete(Collections.EMAIL_DIGESTS, digest.$id)
        } catch (err) {
          log.warn(`Failed to delete digest ${digest.$id}`, { error: err.message })
        }
      }

      // Delete preferences
      const prefs = await userPreferences.getByUser(userId)
      if (prefs) {
        try {
          await db.delete(Collections.USER_PREFERENCES, prefs.$id)
        } catch (err) {
          log.warn(`Failed to delete preferences`, { error: err.message })
        }
      }

      // Delete subscription
      const subscription = await subscriptions.getByUser(userId, req.appwriteUser?.email)
      if (subscription && subscription.$id) {
        try {
          await db.delete(Collections.SUBSCRIPTIONS, subscription.$id)
        } catch (err) {
          log.warn(`Failed to delete subscription`, { error: err.message })
        }
      }

      // Delete email usage
      const usageRecords = await db.list(Collections.EMAIL_USAGE, [Query.equal('userId', userId)])
      for (const usage of usageRecords) {
        try {
          await db.delete(Collections.EMAIL_USAGE, usage.$id)
        } catch (err) {
          log.warn(`Failed to delete usage record`, { error: err.message })
        }
      }

      // Delete onboarding state
      const onboarding = await onboardingState.getByUser(userId)
      if (onboarding && onboarding.$id) {
        try {
          await db.delete(Collections.ONBOARDING_STATE, onboarding.$id)
        } catch (err) {
          log.warn(`Failed to delete onboarding state`, { error: err.message })
        }
      }

      log.success(`Account deletion completed for user ${userId}`)
      respond.success(res, { success: true, message: 'All data deleted successfully' })
    } catch (err) {
      log.error('Account deletion failed', { error: err.message, userId })
      throw new ValidationError('Failed to delete account data')
    }
  })
)

/**
 * GET /api/referrals/code
 * Get or create referral code for user
 */
router.get('/referrals/code',
  requireAuth,
  asyncHandler(async (req, res) => {
    const userId = req.appwriteUser.id
    const referral = await referrals.getOrCreateCode(userId)
    respond.success(res, {
      referralCode: referral.referralCode,
      referralCount: referral.referralCount || 0,
    })
  })
)

/**
 * POST /api/referrals/track
 * Track a referral (when new user signs up with referral code)
 */
router.post('/referrals/track',
  requireAuth,
  validate({
    body: {
      referralCode: [rules.required('referralCode')],
    },
  }),
  asyncHandler(async (req, res) => {
    const userId = req.appwriteUser.id
    const { referralCode } = req.body

    // Find referrer by code
    const referrer = await referrals.getByCode(referralCode)
    if (!referrer) {
      throw new NotFoundError('Referral code')
    }

    // Don't allow self-referral
    if (referrer.userId === userId) {
      throw new ValidationError('Cannot refer yourself')
    }

    // Update referrer's count
    await referrals.incrementCount(referrer.userId)

    // Store referral relationship
    await referrals.getOrCreateCode(userId)
    const userReferral = await referrals.getOrCreateCode(userId)
    await db.update(Collections.REFERRALS, userReferral.$id, {
      referredBy: referrer.userId,
    })

    log.info(`Referral tracked: ${userId} referred by ${referrer.userId} (code: ${referralCode})`)

    respond.success(res, { success: true })
  })
)

export default router
