import express, { Request, Response } from 'express';
import cors from 'cors';
import { MockPrintProvider, LuluPrintProvider, PrintProvider } from '@book-print/printer';
import { LocalStorageProvider, S3StorageProvider, ObjectStorage } from '@book-print/storage';
import { QuoteInput, ValidationInput } from '@book-print/printer';

const app = express();
app.use(cors());
app.use(express.json({ limit: '50mb' }));

const PORT = process.env.PORT || 3000;
const PRINT_ENV = (process.env.PRINT_ENVIRONMENT as 'sandbox' | 'production') || 'sandbox';
const SERVICE_MARKUP_CENTS = parseInt(process.env.SERVICE_MARKUP_FIXED_CENTS || '400', 10); // $4.00 default margin

// Initialize Storage Provider
let storage: ObjectStorage = new LocalStorageProvider();
if (process.env.S3_BUCKET_NAME && process.env.AWS_ACCESS_KEY_ID && process.env.AWS_SECRET_ACCESS_KEY) {
  storage = new S3StorageProvider({
    bucketName: process.env.S3_BUCKET_NAME,
    region: process.env.AWS_REGION || 'us-east-1',
    accessKeyId: process.env.AWS_ACCESS_KEY_ID,
    secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,
    endpoint: process.env.S3_ENDPOINT,
  });
}

// Initialize Printer Provider
let printer: PrintProvider = new MockPrintProvider();
if (process.env.LULU_CLIENT_KEY && process.env.LULU_CLIENT_SECRET) {
  printer = new LuluPrintProvider({
    clientKey: process.env.LULU_CLIENT_KEY,
    clientSecret: process.env.LULU_CLIENT_SECRET,
    environment: PRINT_ENV,
  });
}

// Health Check
app.get('/v1/health', (_req: Request, res: Response) => {
  res.json({
    status: 'ok',
    environment: PRINT_ENV,
    printerProvider: printer.name,
    storageProvider: storage.constructor.name,
  });
});

// 1. PDF Upload Endpoint (Receives base64/binary PDF from Obsidian plugin)
app.post('/v1/uploads', async (req: Request, res: Response) => {
  try {
    const { filename, pdfBase64, contentType } = req.body;
    if (!pdfBase64 || !filename) {
      return res.status(400).json({ success: false, error: 'Missing pdfBase64 or filename' });
    }

    const buffer = Buffer.from(pdfBase64, 'base64');
    const storedObj = await storage.put(filename, buffer, contentType || 'application/pdf');
    const signedUrl = await storage.createDownloadUrl(storedObj.key, 24 * 3600); // 24hr link for Lulu

    res.json({
      success: true,
      key: storedObj.key,
      downloadUrl: signedUrl,
      sizeBytes: storedObj.sizeBytes,
    });
  } catch (err: any) {
    res.status(500).json({ success: false, error: err.message });
  }
});

// 2. Lulu File Validation Endpoint
app.post('/v1/validate', async (req: Request, res: Response) => {
  try {
    const input: ValidationInput = req.body;
    const result = await printer.validateFiles(input);
    res.json({ success: true, result });
  } catch (err: any) {
    res.status(400).json({ success: false, error: err.message });
  }
});

// 3. Live Shipping & Manufacturing Pricing Quote Endpoint
app.post('/v1/quotes', async (req: Request, res: Response) => {
  try {
    const input: QuoteInput = req.body;
    const quote = await printer.getQuote(input);

    // Apply configured business markup
    quote.serviceFeeCents = SERVICE_MARKUP_CENTS;
    quote.totalCostCents = quote.manufacturingCostCents + quote.selectedShipping.costCents + SERVICE_MARKUP_CENTS;

    res.json({ success: true, quote });
  } catch (err: any) {
    res.status(400).json({ success: false, error: err.message });
  }
});

// 4. Stripe Checkout Session Creation Endpoint
app.post('/v1/checkout', async (req: Request, res: Response) => {
  try {
    const { projectId, quoteId, amountCents, currency, bookTitle, interiorPdfUrl, coverPdfUrl, shippingAddress } = req.body;

    // In production with Stripe SDK:
    // const session = await stripe.checkout.sessions.create({ ... })
    const mockSessionId = `cs_test_${Date.now()}`;
    const mockCheckoutUrl = `https://checkout.stripe.com/pay/mock-${mockSessionId}`;

    res.json({
      success: true,
      sessionId: mockSessionId,
      checkoutUrl: mockCheckoutUrl,
    });
  } catch (err: any) {
    res.status(500).json({ success: false, error: err.message });
  }
});

// 5. Verified Stripe Webhook Endpoint (Triggers print order to Lulu upon payment)
app.post('/v1/webhooks/stripe', async (req: Request, res: Response) => {
  try {
    const sig = req.headers['stripe-signature'];
    // Verification logic:
    // const event = stripe.webhooks.constructEvent(req.body, sig, process.env.STRIPE_WEBHOOK_SECRET);

    console.log('[Stripe Webhook] Verified payment event received');
    // Extract metadata & trigger Lulu print order
    const projectId = req.body?.data?.object?.metadata?.projectId || 'proj-sample';
    const interiorPdfUrl = req.body?.data?.object?.metadata?.interiorPdfUrl;
    const coverPdfUrl = req.body?.data?.object?.metadata?.coverPdfUrl;

    if (interiorPdfUrl && coverPdfUrl) {
      const order = await printer.createOrder({
        projectId,
        quoteId: `quote-${Date.now()}`,
        interiorPdfUrl,
        coverPdfUrl,
        shippingAddress: req.body?.data?.object?.metadata?.shippingAddress,
        idempotencyKey: `idempotent-${projectId}`,
      });
      console.log('[Lulu Order Created]', order.id, order.status);
    }

    res.json({ received: true });
  } catch (err: any) {
    res.status(400).send(`Webhook Error: ${err.message}`);
  }
});

// 6. Lulu Webhook Listener (Updates status when book is printed/shipped)
app.post('/v1/webhooks/lulu', (req: Request, res: Response) => {
  console.log('[Lulu Webhook Status Update]', req.body);
  res.json({ received: true });
});

app.listen(PORT, () => {
  console.log(`Book Print API service running on port ${PORT}`);
  console.log(`Printer Provider: ${printer.name} (${PRINT_ENV})`);
  console.log(`Storage Provider: ${storage.constructor.name}`);
});
